import 'package:flutter/material.dart';
import 'package:forui/forui.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/domain/ports/tmdb_gateway.dart';
import '../../../providers/di_providers.dart';
import '../../../providers/sm_account_provider.dart';
import '../../../providers/tmdb_settings_provider.dart';
import '../../../shared/widgets/app_inline_alert.dart';
import '../../../shared/widgets/app_loading_ring.dart';
import '../../../shared/widgets/setting_select.dart';
import '../utils/settings_labels.dart';
import '../widgets/settings_card.dart';
import '../widgets/settings_text_field_row.dart';

class TmdbSettingsTab extends ConsumerWidget {
  final void Function(String message, {AppAlertTone tone}) onFeedback;

  const TmdbSettingsTab({super.key, required this.onFeedback});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final tmdb = ref.watch(tmdbSettingsProvider);

    return SettingsTabScroll(
      children: [
        tmdb.when(
          data: (data) =>
              TmdbSettingsSection(state: data, onFeedback: onFeedback),
          loading: () => const Padding(
            padding: EdgeInsets.symmetric(vertical: 32),
            child: Center(child: AppLoadingRing()),
          ),
          error: (e, _) => SettingsCard(children: [settingsLoadError(e)]),
        ),
      ],
    );
  }
}

class TmdbSettingsSection extends ConsumerStatefulWidget {
  final TmdbSettingsState state;
  final void Function(String message, {AppAlertTone tone}) onFeedback;

  const TmdbSettingsSection({
    super.key,
    required this.state,
    required this.onFeedback,
  });

  @override
  ConsumerState<TmdbSettingsSection> createState() =>
      TmdbSettingsSectionState();
}

class TmdbSettingsSectionState extends ConsumerState<TmdbSettingsSection> {
  late final TextEditingController _apiKeyCtrl;
  late final TextEditingController _accessTokenCtrl;
  final _apiKeyFocus = FocusNode();
  final _accessTokenFocus = FocusNode();
  bool _testingConnection = false;

  @override
  void initState() {
    super.initState();
    _apiKeyCtrl = TextEditingController(text: widget.state.apiKey);
    _accessTokenCtrl = TextEditingController(text: widget.state.accessToken);
  }

  @override
  void didUpdateWidget(covariant TmdbSettingsSection oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (!_apiKeyFocus.hasFocus && _apiKeyCtrl.text != widget.state.apiKey) {
      _apiKeyCtrl.text = widget.state.apiKey;
    }
    if (!_accessTokenFocus.hasFocus &&
        _accessTokenCtrl.text != widget.state.accessToken) {
      _accessTokenCtrl.text = widget.state.accessToken;
    }
  }

  @override
  void dispose() {
    _apiKeyCtrl.dispose();
    _accessTokenCtrl.dispose();
    _apiKeyFocus.dispose();
    _accessTokenFocus.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final s = widget.state;
    final account = ref.watch(smAccountProvider).value;
    final accountStatus = account?.status ?? SmAuthStatus.unauthenticated;
    final canRequest = s.canRequestWithAccount(
      dataPlaneReady: account?.canUseDataPlane ?? false,
    );
    final String statusSubtitle;
    if (!s.enabled) {
      statusSubtitle = '关闭时不请求 TMDB 数据';
    } else if (s.accessMode == TmdbAccessMode.smAccount) {
      statusSubtitle = switch (accountStatus) {
        SmAuthStatus.authenticated => '已启用（内置代理），使用账号 ${account!.email}',
        SmAuthStatus.restoring => '已启用（内置代理），正在恢复登录…',
        SmAuthStatus.expired => '已启用（内置代理），登录已过期，请重新登录',
        SmAuthStatus.degraded => '已启用（内置代理），账号凭据不完整，请重新登录',
        SmAuthStatus.unauthenticated => '已启用（内置代理），需登录 sm-server 账号',
      };
    } else {
      statusSubtitle = canRequest ? '已启用，媒体详情和发现页会请求 TMDB 数据' : '已启用，请补全认证信息';
    }

    return Column(
      children: [
        SettingsCard(
          children: [
            SettingRow(
              title: '启用 TMDB',
              subtitle: statusSubtitle,
              trailing: FSwitch(
                value: s.enabled,
                onChange: (v) =>
                    ref.read(tmdbSettingsProvider.notifier).setEnabled(v),
              ),
            ),
            if (s.enabled)
              SettingRow(
                title: '接入方式',
                subtitle: s.accessMode == TmdbAccessMode.smAccount
                    ? null
                    : '数据接口：${TmdbSettingsState.officialApiBaseUrl}',
                trailing: SettingSelect<TmdbAccessMode>(
                  value: s.accessMode,
                  options: TmdbAccessMode.values,
                  labelOf: tmdbAccessModeLabel,
                  onChanged: (v) {
                    if (v != null) {
                      ref.read(tmdbSettingsProvider.notifier).setAccessMode(v);
                    }
                  },
                ),
              ),
          ],
        ),

        if (s.enabled && s.accessMode == TmdbAccessMode.smAccount) ...[
          _SmAccountTmdbSection(
            accountState: account,
            language: s.language,
            onFeedback: widget.onFeedback,
            onTestConnection: _testConnectionSmAccount,
            testingConnection: _testingConnection,
          ),
          _LanguageCard(language: s.language),
        ],

        if (s.enabled && s.accessMode == TmdbAccessMode.official) ...[
          SettingsCard(
            children: [
              SettingRow(
                title: '认证方式',
                trailing: SettingSelect<TmdbAuthMode>(
                  value: s.authMode,
                  options: TmdbAuthMode.values,
                  labelOf: tmdbAuthModeLabel,
                  onChanged: (v) {
                    if (v != null) {
                      ref.read(tmdbSettingsProvider.notifier).setAuthMode(v);
                    }
                  },
                ),
              ),
              if (s.authMode == TmdbAuthMode.apiKey)
                SettingsTextFieldRow(
                  title: 'API Key',
                  hintText: '粘贴 TMDB API Key',
                  controller: _apiKeyCtrl,
                  focusNode: _apiKeyFocus,
                  onChanged: (v) =>
                      ref.read(tmdbSettingsProvider.notifier).setApiKey(v),
                )
              else
                SettingsTextFieldRow(
                  title: 'Bearer Token',
                  hintText: '粘贴 TMDB Read Access Token',
                  controller: _accessTokenCtrl,
                  focusNode: _accessTokenFocus,
                  obscureText: true,
                  onChanged: (v) =>
                      ref.read(tmdbSettingsProvider.notifier).setAccessToken(v),
                ),
              _LanguageRow(language: s.language),
            ],
          ),
          SettingsCard(
            children: [
              SettingRow(
                title: '配置状态',
                subtitle: s.isConfigured ? '认证信息已填写' : '请填写当前认证方式对应的密钥',
                trailing: Icon(
                  s.canRequest ? Icons.check_circle : Icons.info_outline,
                  size: 18,
                  color: s.canRequest
                      ? const Color(0xFF52C41A)
                      : const Color(0xFFFAAD14),
                ),
              ),
              SettingRow(
                title: '测试连接',
                subtitle: '请求 TMDB /configuration 验证认证和网络',
                trailing: FilledButton.tonalIcon(
                  onPressed: s.isConfigured && !_testingConnection
                      ? _testConnectionOfficial
                      : null,
                  icon: _testingConnection
                      ? const AppLoadingRing(size: 14)
                      : const Icon(Icons.network_check_rounded, size: 16),
                  label: const Text('测试'),
                ),
              ),
            ],
          ),
        ],
      ],
    );
  }

  Future<void> _testConnectionOfficial() async {
    final s = widget.state;
    final accessToken = _accessTokenCtrl.text.trim();
    final apiKey = _apiKeyCtrl.text.trim();
    final hasCredential = switch (s.authMode) {
      TmdbAuthMode.bearer => accessToken.isNotEmpty,
      TmdbAuthMode.apiKey => apiKey.isNotEmpty,
    };
    if (!hasCredential) {
      widget.onFeedback('请先填写当前认证方式对应的密钥', tone: AppAlertTone.warning);
      return;
    }

    setState(() => _testingConnection = true);
    final ok = await ref
        .read(tmdbGatewayProvider)
        .testConnection(
          TmdbRequestConfig(
            apiBaseUrl: TmdbSettingsState.officialApiBaseUrl,
            imageBaseUrl: TmdbSettingsState.officialImageBaseUrl,
            accessToken: s.authMode == TmdbAuthMode.bearer ? accessToken : '',
            apiKey: s.authMode == TmdbAuthMode.apiKey ? apiKey : '',
          ),
          language: s.language,
        );
    if (!mounted) return;
    setState(() => _testingConnection = false);
    widget.onFeedback(
      ok ? 'TMDB 连接测试成功' : 'TMDB 连接测试失败，请检查密钥或网络',
      tone: ok ? AppAlertTone.success : AppAlertTone.error,
    );
  }

  Future<void> _testConnectionSmAccount() async {
    setState(() => _testingConnection = true);
    final token = await ref
        .read(smAccountProvider.notifier)
        .getAccessToken(force: true);
    if (!mounted) return;
    if (token == null) {
      setState(() => _testingConnection = false);
      widget.onFeedback('无法获取访问凭据，请重新登录账号', tone: AppAlertTone.error);
      return;
    }
    final account = ref.read(smAccountProvider).value;
    final accountState = account ?? const SmAccountState();
    final ok = await ref
        .read(tmdbGatewayProvider)
        .testConnection(
          TmdbRequestConfig(
            apiBaseUrl: accountState.tmdbApiBaseUrl,
            imageBaseUrl: TmdbSettingsState.officialImageBaseUrl,
            accessToken: token,
            apiKey: '',
          ),
          language: widget.state.language,
        );
    if (!mounted) return;
    setState(() => _testingConnection = false);
    widget.onFeedback(
      ok ? 'TMDB 内置代理测试成功' : 'TMDB 内置代理测试失败，请检查账号或网络',
      tone: ok ? AppAlertTone.success : AppAlertTone.error,
    );
  }
}


class _SmAccountTmdbSection extends ConsumerWidget {
  final SmAccountState? accountState;
  final String language;
  final void Function(String message, {AppAlertTone tone}) onFeedback;
  final VoidCallback onTestConnection;
  final bool testingConnection;

  const _SmAccountTmdbSection({
    required this.accountState,
    required this.language,
    required this.onFeedback,
    required this.onTestConnection,
    required this.testingConnection,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final dataPlaneReady = accountState?.canUseDataPlane == true;

    return SettingsCard(
      children: [
        SettingRow(
          title: '测试连接',
          subtitle: '验证当前账号凭据与 TMDB 代理可达性',
          trailing: FilledButton.tonalIcon(
            onPressed: dataPlaneReady && !testingConnection
                ? onTestConnection
                : null,
            icon: testingConnection
                ? const AppLoadingRing(size: 14)
                : const Icon(Icons.network_check_rounded, size: 16),
            label: const Text('测试'),
          ),
        ),
      ],
    );
  }
}


class _LanguageRow extends ConsumerWidget {
  final String language;
  const _LanguageRow({required this.language});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return SettingRow(
      title: '语言',
      trailing: _LanguageSelect(language: language),
    );
  }
}


class _LanguageCard extends ConsumerWidget {
  final String language;
  const _LanguageCard({required this.language});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return SettingsCard(
      children: [
        SettingRow(
          title: '语言',
          trailing: _LanguageSelect(language: language),
        ),
      ],
    );
  }
}

class _LanguageSelect extends ConsumerWidget {
  final String language;
  const _LanguageSelect({required this.language});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return SettingSelect<String>(
      value: language,
      options: const ['zh-CN', 'zh-TW', 'en-US', 'ja-JP', 'ko-KR'],
      labelOf: tmdbLanguageLabel,
      onChanged: (v) {
        if (v != null) {
          ref.read(tmdbSettingsProvider.notifier).setLanguage(v);
        }
      },
    );
  }
}
