import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'shared/settings_persistence.dart';

enum TmdbAuthMode { bearer, apiKey }


enum TmdbAccessMode {

  official,


  smAccount,
}

class TmdbSettingsState {

  static const officialApiBaseUrl = 'https://api.themoviedb.org/3';
  static const officialImageBaseUrl = 'https://image.tmdb.org/t/p';


  static const smAccountApiBaseUrl = 'https://your-server.example';

  final bool enabled;
  final TmdbAccessMode accessMode;
  final TmdbAuthMode authMode;
  final String accessToken;
  final String apiKey;
  final String language;

  const TmdbSettingsState({
    this.enabled = false,
    this.accessMode = TmdbAccessMode.official,
    this.authMode = TmdbAuthMode.apiKey,
    this.accessToken = '',
    this.apiKey = '',
    this.language = 'zh-CN',
  });

  bool get isConfigured => switch (accessMode) {
    TmdbAccessMode.smAccount => true,
    TmdbAccessMode.official => switch (authMode) {
      TmdbAuthMode.bearer => accessToken.isNotEmpty,
      TmdbAuthMode.apiKey => apiKey.isNotEmpty,
    },
  };

  bool get canRequest => enabled && isConfigured;


  bool canRequestWithAccount({required bool dataPlaneReady}) =>
      switch (accessMode) {
        TmdbAccessMode.official => canRequest,
        TmdbAccessMode.smAccount => enabled && dataPlaneReady,
      };

  String get effectiveApiBaseUrl => switch (accessMode) {
    TmdbAccessMode.smAccount => smAccountApiBaseUrl,
    TmdbAccessMode.official => officialApiBaseUrl,
  };


  String get effectiveImageBaseUrl => officialImageBaseUrl;

  String get effectiveAccessToken =>
      accessMode == TmdbAccessMode.official && authMode == TmdbAuthMode.bearer
      ? accessToken
      : '';

  String get effectiveApiKey =>
      accessMode == TmdbAccessMode.official && authMode == TmdbAuthMode.apiKey
      ? apiKey
      : '';

  TmdbSettingsState copyWith({
    bool? enabled,
    TmdbAccessMode? accessMode,
    TmdbAuthMode? authMode,
    String? accessToken,
    String? apiKey,
    String? language,
  }) => TmdbSettingsState(
    enabled: enabled ?? this.enabled,
    accessMode: accessMode ?? this.accessMode,
    authMode: authMode ?? this.authMode,
    accessToken: accessToken ?? this.accessToken,
    apiKey: apiKey ?? this.apiKey,
    language: language ?? this.language,
  );
}

class TmdbSettingsNotifier extends AsyncNotifier<TmdbSettingsState>
    with SettingsPersistence {
  static const _keyEnabled = 'smplayer.tmdb_enabled';
  static const _keyAccessMode = 'smplayer.tmdb_access_mode';
  static const _keyAuthMode = 'smplayer.tmdb_auth_mode';
  static const _keyAccessToken = 'smplayer.tmdb_access_token';
  static const _keyApiKey = 'smplayer.tmdb_api_key';
  static const _keyLanguage = 'smplayer.tmdb_language';

  @override
  Future<TmdbSettingsState> build() async {
    final prefs = await getPrefs();
    final accessToken = prefs.getString(_keyAccessToken)?.trim() ?? '';
    final apiKey = prefs.getString(_keyApiKey)?.trim() ?? '';
    return TmdbSettingsState(
      enabled: prefs.getBool(_keyEnabled) ?? false,
      accessMode: _parseAccessMode(prefs.getString(_keyAccessMode)),
      authMode: _parseAuthMode(
        prefs.getString(_keyAuthMode),
        hasLegacyAccessToken: accessToken.isNotEmpty,
      ),
      accessToken: accessToken,
      apiKey: apiKey,
      language: prefs.getString(_keyLanguage) ?? 'zh-CN',
    );
  }

  Future<void> setEnabled(bool v) async {
    final current = state.value ?? const TmdbSettingsState();
    state = AsyncValue.data(current.copyWith(enabled: v));
    await persistField(_keyEnabled, v);
  }

  Future<void> setAccessMode(TmdbAccessMode mode) async {
    final current = state.value ?? const TmdbSettingsState();
    state = AsyncValue.data(current.copyWith(accessMode: mode));
    await persistField(_keyAccessMode, mode.name);
  }

  Future<void> enableSmAccountProxy() async {
    final current = state.value ?? await future;
    state = AsyncValue.data(
      current.copyWith(enabled: true, accessMode: TmdbAccessMode.smAccount),
    );
    await persistFields(<String, dynamic>{
      _keyEnabled: true,
      _keyAccessMode: TmdbAccessMode.smAccount.name,
    });
  }

  Future<void> setAuthMode(TmdbAuthMode mode) async {
    final current = state.value ?? const TmdbSettingsState();
    state = AsyncValue.data(current.copyWith(authMode: mode));
    await persistField(_keyAuthMode, mode.name);
  }

  Future<void> setAccessToken(String token) async {
    final trimmed = token.trim();
    final current = state.value ?? const TmdbSettingsState();
    state = AsyncValue.data(current.copyWith(accessToken: trimmed));
    await persistField(_keyAccessToken, trimmed);
  }

  Future<void> setApiKey(String key) async {
    final trimmed = key.trim();
    final current = state.value ?? const TmdbSettingsState();
    state = AsyncValue.data(current.copyWith(apiKey: trimmed));
    await persistField(_keyApiKey, trimmed);
  }

  Future<void> setLanguage(String lang) async {
    final current = state.value ?? const TmdbSettingsState();
    state = AsyncValue.data(current.copyWith(language: lang));
    await persistField(_keyLanguage, lang);
  }
}

final tmdbSettingsProvider =
    AsyncNotifierProvider<TmdbSettingsNotifier, TmdbSettingsState>(
      TmdbSettingsNotifier.new,
    );

TmdbAccessMode _parseAccessMode(String? value) => TmdbAccessMode.values
    .firstWhere((m) => m.name == value, orElse: () => TmdbAccessMode.official);

TmdbAuthMode _parseAuthMode(
  String? value, {
  bool hasLegacyAccessToken = false,
}) {
  if (value == null && hasLegacyAccessToken) {
    return TmdbAuthMode.bearer;
  }
  return TmdbAuthMode.values.firstWhere(
    (mode) => mode.name == value,
    orElse: () => TmdbAuthMode.apiKey,
  );
}
