import 'dart:io';
import 'package:flutter/material.dart';
import 'package:lucide_icons/lucide_icons.dart';
import 'package:open_file/open_file.dart';
import 'package:logger/logger.dart' show Level;
import 'package:provider/provider.dart';
import '../../../core/constants/storage_keys.dart';
import '../../../core/utils/app_logger.dart';
import '../../../data/models/cache_settings_model.dart';
import '../../../services/cache_manager_service.dart';
import '../../../services/download_service.dart';
import '../../../services/storage_service.dart';
import '../../providers/download_manager_provider.dart';
import '../../providers/theme_provider.dart';
import '../../providers/user_setting_provider.dart';
import '../../widgets/glassmorphism_container.dart';
import '../../widgets/toast_helper.dart';
import '../../widgets/desktop_constrained.dart';
import 'log_viewer_page.dart';

/// 应用设置页（缓存、主题、语言）
class AppSettingsPage extends StatefulWidget {
  const AppSettingsPage({super.key});

  @override
  State<AppSettingsPage> createState() => _AppSettingsPageState();
}

class _AppSettingsPageState extends State<AppSettingsPage> {
  CacheSettingsModel _cacheSettings = CacheSettingsModel();
  bool _isLoading = true;
  int? _currentCacheSize;
  bool _isCleaning = false;
  bool _wifiOnlyEnabled = false;
  int _downloadRetries = 3;
  int _taskRetentionDays = 7;
  bool _gravatarMirrorEnabled = true;
  String _gravatarMirrorUrl = 'https://weavatar.com';
  String _logFilePath = '';
  int? _logFileSize;
  String _cacheDirPath = '';
  Level _logLevel = Level.info;

  @override
  void initState() {
    super.initState();
    _loadCacheSettings();
    _loadWifiOnlySetting();
    _loadGravatarMirrorSetting();
    _loadLogInfo();
    _loadLogLevel();
  }

  Future<void> _loadCacheSettings() async {
    try {
      final service = CacheManagerService.instance;
      await service.initialize();
      final settings = service.settings;

      if (mounted) {
        setState(() {
          _cacheSettings = settings;
          _isLoading = false;
        });
      }

      Future.delayed(const Duration(milliseconds: 100), () async {
        final cacheSize = await service.getCacheSize();
        final cacheDir = await service.getCacheDir();
        if (mounted) {
          setState(() {
            _currentCacheSize = cacheSize;
            _cacheDirPath = cacheDir.path;
          });
        }
      });
    } catch (e) {
      if (mounted) setState(() => _isLoading = false);
    }
  }

  Future<void> _saveCacheSettings() async {
    final service = CacheManagerService.instance;
    await service.saveSettings(_cacheSettings);
    if (mounted) ToastHelper.success('设置已保存');
  }

  Future<void> _loadLogInfo() async {
    final path = await AppLogger.logFilePath;
    final size = await AppLogger.logFileSize;
    if (mounted) {
      setState(() {
        _logFilePath = path;
        _logFileSize = size;
      });
    }
  }

  Future<void> _loadWifiOnlySetting() async {
    final enabled = await StorageService.instance
            .getBool(StorageKeys.downloadWifiOnly) ??
        false;
    final retries = await StorageService.instance
            .getInt(StorageKeys.downloadRetries) ??
        3;
    final retentionDays = await StorageService.instance
            .getInt(StorageKeys.taskRetentionDays) ??
        7;
    if (mounted) {
      setState(() {
        _wifiOnlyEnabled = enabled;
        _downloadRetries = retries;
        _taskRetentionDays = retentionDays;
      });
    }
  }

  Future<void> _loadGravatarMirrorSetting() async {
    final enabled = await StorageService.instance
            .getBool(StorageKeys.gravatarMirrorEnabled) ??
        true;
    final url = await StorageService.instance
            .getString(StorageKeys.gravatarMirrorUrl) ??
        'https://weavatar.com';
    if (mounted) {
      setState(() {
        _gravatarMirrorEnabled = enabled;
        _gravatarMirrorUrl = url;
      });
    }
  }

  Future<void> _loadLogLevel() async {
    final saved = await StorageService.instance.getString(StorageKeys.logLevel);
    if (saved != null && mounted) {
      setState(() {
        _logLevel = _parseLogLevel(saved);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('应用设置')),
      body: _isLoading
          ? const Center(child: CircularProgressIndicator())
          : DesktopConstrained(
              child: ListView(
              children: [
                _buildSection(
                  title: '外观',
                  children: [
                    ListTile(
                      leading: const Icon(Icons.dark_mode_outlined),
                      title: const Text('深色模式'),
                      subtitle: Text(_themeModeLabel(context)),
                      trailing: const Icon(Icons.chevron_right),
                      onTap: () => _showThemeModeDialog(context),
                    ),
                    ListTile(
                      leading: const Icon(Icons.palette_outlined),
                      title: const Text('主题色'),
                      trailing: Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          CircleAvatar(
                            backgroundColor: context.watch<ThemeProvider>().seedColor,
                            radius: 10,
                          ),
                          const SizedBox(width: 8),
                          const Icon(Icons.chevron_right),
                        ],
                      ),
                      onTap: () => _showThemeColorPicker(context),
                    ),
                    ListTile(
                      leading: const Icon(Icons.language),
                      title: const Text('语言'),
                      subtitle: const Text('跟随系统'),
                      trailing: const Icon(Icons.chevron_right),
                      onTap: () => _showLanguageDialog(context),
                    ),
                  ],
                ),
                _buildSection(
                  title: 'Gravatar 镜像',
                  children: [
                    SwitchListTile(
                      title: const Text('启用 Gravatar 镜像'),
                      subtitle: const Text('国内网络建议启用，加速 Gravatar 头像加载'),
                      value: _gravatarMirrorEnabled,
                      onChanged: (value) async {
                        setState(() => _gravatarMirrorEnabled = value);
                        await StorageService.instance
                            .setBool(StorageKeys.gravatarMirrorEnabled, value);
                      },
                    ),
                    if (_gravatarMirrorEnabled)
                      ListTile(
                        leading: const Icon(Icons.dns_outlined),
                        title: const Text('镜像地址'),
                        subtitle: Text(_gravatarMirrorUrl),
                        trailing: const Icon(Icons.chevron_right),
                        onTap: () => _showGravatarMirrorUrlDialog(context),
                      ),
                  ],
                ),
                _buildSection(
                  title: '下载设置',
                  children: [
                    SwitchListTile(
                      title: const Text('仅WiFi下载'),
                      subtitle: const Text('非WiFi环境下暂停下载，等待WiFi后自动恢复'),
                      value: _wifiOnlyEnabled,
                      onChanged: (value) async {
                        setState(() => _wifiOnlyEnabled = value);
                        await StorageService.instance
                            .setBool(StorageKeys.downloadWifiOnly, value);
                        if (mounted) {
                          if (!context.mounted) return;
                          context
                              .read<DownloadManagerProvider>()
                              .setWifiOnlyEnabled(value);
                        }
                      },
                    ),
                    ListTile(
                      title: const Text('重试次数'),
                      subtitle: Text(_downloadRetries == 0 ? '不重试' : '失败后自动重试 $_downloadRetries 次'),
                      trailing: const Icon(Icons.chevron_right),
                      onTap: () => _showRetriesDialog(context),
                    ),
                    ListTile(
                      title: const Text('任务记录保留'),
                      subtitle: Text(_taskRetentionDays == -1 ? '永久保留' : '保留 $_taskRetentionDays 天'),
                      trailing: const Icon(Icons.chevron_right),
                      onTap: () => _showRetentionDaysDialog(context),
                    ),
                  ],
                ),
                _buildSection(
                  title: '缓存设置',
                  children: [
                    ListTile(
                      title: const Text('最大缓存大小'),
                      subtitle: Text(_cacheSettings.maxCacheSizeReadable),
                      trailing: const Icon(Icons.chevron_right),
                      onTap: () => _showMaxCacheSizeDialog(context),
                    ),
                    ListTile(
                      title: const Text('缓存过期时间'),
                      subtitle: Text(_cacheSettings.cacheExpireDurationReadable),
                      trailing: const Icon(Icons.chevron_right),
                      onTap: () => _showCacheExpireDurationDialog(context),
                    ),
                    SwitchListTile(
                      title: const Text('自动清理最旧文件'),
                      subtitle: const Text('当超过最大缓存大小时自动清理'),
                      value: _cacheSettings.autoCleanOldFiles,
                      onChanged: (value) {
                        setState(() {
                          _cacheSettings = _cacheSettings.copyWith(autoCleanOldFiles: value);
                        });
                        _saveCacheSettings();
                      },
                    ),
                  ],
                ),
                _buildSection(
                  title: '缓存信息',
                  children: [
                    if (_cacheDirPath.isNotEmpty)
                      ListTile(
                        title: const Text('缓存目录'),
                        subtitle: Text(
                          _cacheDirPath,
                          style: const TextStyle(fontSize: 11),
                          maxLines: 2,
                          overflow: TextOverflow.ellipsis,
                        ),
                        trailing: (Platform.isWindows || Platform.isLinux)
                            ? const Icon(Icons.open_in_new, size: 18)
                            : null,
                        onTap: (Platform.isWindows || Platform.isLinux)
                            ? _openCacheDir
                            : null,
                      ),
                    ListTile(
                      title: const Text('当前缓存大小'),
                      subtitle: Text(_formatBytes(_currentCacheSize)),
                    ),
                    ListTile(
                      title: const Text('清空缓存'),
                      leading: const Icon(Icons.delete_outline, color: Colors.red),
                      trailing: _isCleaning
                          ? const SizedBox(
                              width: 20,
                              height: 20,
                              child: CircularProgressIndicator(strokeWidth: 2),
                            )
                          : const Icon(Icons.chevron_right),
                      onTap: _isCleaning ? null : _clearCache,
                    ),
                  ],
                ),
                _buildSection(
                  title: '日志管理',
                  children: [
                    ListTile(
                      leading: const Icon(Icons.tune),
                      title: const Text('日志级别'),
                      subtitle: Text(_logLevelLabel(_logLevel)),
                      trailing: const Icon(Icons.chevron_right),
                      onTap: () => _pickLogLevel(),
                    ),
                    ListTile(
                      title: const Text('日志文件路径'),
                      subtitle: Text(
                        _logFilePath,
                        style: const TextStyle(fontSize: 11),
                        maxLines: 2,
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                    ListTile(
                      title: const Text('日志文件大小'),
                      subtitle: Text(_formatBytes(_logFileSize)),
                    ),
                    if (!Platform.isAndroid)
                      ListTile(
                        title: const Text('打开日志目录'),
                        leading: const Icon(Icons.folder_open),
                        trailing: const Icon(Icons.chevron_right),
                        onTap: _openLogFolder,
                      ),
                    ListTile(
                      title: const Text('导出日志'),
                      leading: const Icon(Icons.file_download_outlined),
                      subtitle: const Text('导出到 Download 目录'),
                      trailing: const Icon(Icons.chevron_right),
                      onTap: _exportLog,
                    ),
                    ListTile(
                      title: const Text('预览日志'),
                      leading: const Icon(Icons.visibility_outlined),
                      trailing: const Icon(Icons.chevron_right),
                      onTap: _previewLog,
                    ),
                    ListTile(
                      title: const Text('清空日志'),
                      leading: const Icon(Icons.delete_outline, color: Colors.red),
                      trailing: const Icon(Icons.chevron_right),
                      onTap: _clearLog,
                    ),
                  ],
                ),
              ],
              ),
            ),
    );
  }

  Widget _buildSection({required String title, required List<Widget> children}) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: Text(
              title,
              style: TextStyle(
                fontSize: 14,
                fontWeight: FontWeight.bold,
                color: Theme.of(context).colorScheme.primary,
              ),
            ),
          ),
          Card(
            margin: const EdgeInsets.symmetric(horizontal: 16),
            child: Column(children: children),
          ),
        ],
      ),
    );
  }

  Future<void> _showThemeColorPicker(BuildContext context) async {
    final colors = [
      ('默认蓝', Colors.blue),
      ('靛蓝', Colors.indigo),
      ('紫色', Colors.purple),
      ('粉红', Colors.pink),
      ('红色', Colors.red),
      ('橙色', Colors.orange),
      ('琥珀', Colors.amber),
      ('绿色', Colors.green),
      ('青色', Colors.teal),
      ('青蓝', Colors.cyan),
    ];
    final currentColor = context.read<ThemeProvider>().seedColor;

    final selected = await showDialog<Color>(
      context: context,
      builder: (ctx) => SimpleDialog(
        title: const Text('选择主题色'),
        children: colors.map((c) {
          final isSelected = currentColor.toARGB32() == c.$2.toARGB32();
          return SimpleDialogOption(
            onPressed: () => Navigator.of(ctx).pop(c.$2),
            child: Row(
              children: [
                CircleAvatar(backgroundColor: c.$2, radius: 14),
                const SizedBox(width: 12),
                Expanded(child: Text(c.$1)),
                if (isSelected)
                  Icon(Icons.check, color: Theme.of(ctx).colorScheme.primary),
              ],
            ),
          );
        }).toList(),
      ),
    );

    if (selected == null || !mounted) return;
    if (!context.mounted) return;
    // 立即更新本地主题
    await context.read<ThemeProvider>().setSeedColor(selected);
    if (!context.mounted) return;

    // 同步到服务端
    final hex = '#${selected.toARGB32().toRadixString(16).padLeft(8, '0').substring(2)}';
    final success = await context.read<UserSettingProvider>().updatePreferredTheme(hex);
    if (!mounted) return;
    if (success) {
      ToastHelper.success('主题色已更新');
    } else {
      ToastHelper.failure('同步主题色到服务端失败');
    }
  }

  String _themeModeLabel(BuildContext context) {
    final mode = context.watch<ThemeProvider>().themeMode;
    return switch (mode) {
      AppThemeMode.light => '浅色',
      AppThemeMode.dark => '深色',
      AppThemeMode.system => '跟随系统',
    };
  }

  Future<void> _showThemeModeDialog(BuildContext context) async {
    final currentMode = context.read<ThemeProvider>().themeMode;
    final options = [
      (AppThemeMode.system, '跟随系统', Icons.brightness_auto),
      (AppThemeMode.light, '浅色', Icons.light_mode),
      (AppThemeMode.dark, '深色', Icons.dark_mode),
    ];

    final selected = await showDialog<AppThemeMode>(
      context: context,
      builder: (ctx) => SimpleDialog(
        title: const Text('深色模式'),
        children: options.map((opt) {
          final isSelected = currentMode == opt.$1;
          return SimpleDialogOption(
            onPressed: () => Navigator.of(ctx).pop(opt.$1),
            child: Row(
              children: [
                Icon(opt.$3),
                const SizedBox(width: 12),
                Expanded(child: Text(opt.$2)),
                if (isSelected)
                  Icon(Icons.check, color: Theme.of(ctx).colorScheme.primary),
              ],
            ),
          );
        }).toList(),
      ),
    );

    if (selected == null || !mounted) return;
    if (!context.mounted) return;
    await context.read<ThemeProvider>().setThemeMode(selected);
  }

  Future<void> _showLanguageDialog(BuildContext context) async {
    final languages = [
      ('zh-CN', '简体中文'),
      ('zh-TW', '繁體中文'),
      ('en-US', 'English'),
      ('ja-JP', '日本語'),
    ];

    final selected = await showDialog<String>(
      context: context,
      builder: (ctx) => SimpleDialog(
        title: const Text('选择语言'),
        children: languages.map((l) {
          return SimpleDialogOption(
            onPressed: () => Navigator.of(ctx).pop(l.$1),
            child: Text(l.$2),
          );
        }).toList(),
      ),
    );

    if (selected == null || !mounted) return;
    if (!context.mounted) return;
    final success = await context.read<UserSettingProvider>().updateLanguage(selected);
    if (!mounted) return;
    if (success) {
      ToastHelper.success('语言偏好已保存');
    } else {
      ToastHelper.failure('更新语言失败');
    }
  }

  Future<void> _showMaxCacheSizeDialog(BuildContext context) async {
    final availableSizes = CacheSettingsModel.availableSizes;
    final currentValue = _cacheSettings.maxCacheSize ~/ (1024 * 1024);

    final selected = await _showGlassOptionDialog<int>(
      context,
      title: '最大缓存大小',
      icon: LucideIcons.hardDrive,
      options: availableSizes.map((size) => (size, '$size MB', currentValue == size)).toList(),
    );

    if (selected != null && mounted) {
      setState(() => _cacheSettings = CacheSettingsModel.fromMB(selected));
      _saveCacheSettings();
    }
  }

  Future<void> _showCacheExpireDurationDialog(BuildContext context) async {
    final availableDurations = CacheSettingsModel.availableDurations;
    final currentValue = _cacheSettings.cacheExpireDuration ~/ (24 * 60 * 60 * 1000);

    final selected = await _showGlassOptionDialog<int>(
      context,
      title: '缓存过期时间',
      icon: LucideIcons.timer,
      options: availableDurations.map((days) => (days, '$days 天', currentValue == days)).toList(),
    );

    if (selected != null && mounted) {
      setState(() => _cacheSettings = CacheSettingsModel.fromDays(selected));
      _saveCacheSettings();
    }
  }

  Future<void> _showRetriesDialog(BuildContext context) async {
    final retriesOptions = [0, 1, 2, 3, 5, 10];

    final selected = await _showGlassOptionDialog<int>(
      context,
      title: '重试次数',
      icon: LucideIcons.refreshCw,
      subtitle: '下载失败后自动重试的次数',
      options: retriesOptions.map((retries) =>
        (retries, retries == 0 ? '不重试' : '$retries 次', _downloadRetries == retries)).toList(),
    );

    if (selected != null && mounted) {
      setState(() => _downloadRetries = selected);
      await StorageService.instance
          .setInt(StorageKeys.downloadRetries, selected);
    }
  }

  Future<void> _showRetentionDaysDialog(BuildContext context) async {
    final options = [
      (7, '7 天'),
      (15, '15 天'),
      (30, '30 天'),
      (-1, '永久保留'),
    ];

    final selected = await _showGlassOptionDialog<int>(
      context,
      title: '任务记录保留时间',
      icon: LucideIcons.clock,
      subtitle: '超过保留时间的已完成任务将被自动清理',
      options: options.map((opt) => (opt.$1, opt.$2, _taskRetentionDays == opt.$1)).toList(),
    );

    if (selected != null && mounted) {
      setState(() => _taskRetentionDays = selected);
      await StorageService.instance
          .setInt(StorageKeys.taskRetentionDays, selected);
    }
  }

  /// 通用毛玻璃选项选择对话框
  Future<T?> _showGlassOptionDialog<T>(
    BuildContext context, {
    required String title,
    required IconData icon,
    String? subtitle,
    required List<(T, String, bool)> options,
  }) {
    return showGeneralDialog<T>(
      context: context,
      barrierDismissible: true,
      barrierLabel: title,
      barrierColor: Colors.black38,
      transitionDuration: const Duration(milliseconds: 250),
      transitionBuilder: (context, animation, secondaryAnimation, child) {
        final scaleAnim = CurvedAnimation(
          parent: animation,
          curve: Curves.easeOutCubic,
        ).drive(Tween(begin: 0.92, end: 1.0));
        final fadeAnim = CurvedAnimation(
          parent: animation,
          curve: Curves.easeOut,
        ).drive(Tween(begin: 0.0, end: 1.0));
        return ScaleTransition(
          scale: scaleAnim,
          child: FadeTransition(opacity: fadeAnim, child: child),
        );
      },
      pageBuilder: (context, animation, secondaryAnimation) {
        final screenWidth = MediaQuery.of(context).size.width;
        final dialogWidth = screenWidth >= 600 ? 380.0 : screenWidth - 48.0;
        final colorScheme = Theme.of(context).colorScheme;
        final theme = Theme.of(context);

        return Center(
          child: SizedBox(
            width: dialogWidth,
            child: GlassmorphismContainer(
              borderRadius: 16,
              sigmaX: 20,
              sigmaY: 20,
              child: ClipRRect(
                borderRadius: BorderRadius.circular(16),
                child: Material(
                  color: Colors.transparent,
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      // Header
                      Padding(
                        padding: const EdgeInsets.fromLTRB(20, 16, 8, 12),
                        child: Row(
                          children: [
                            Icon(icon, size: 20, color: colorScheme.primary),
                            const SizedBox(width: 10),
                            Expanded(
                              child: Text(
                                title,
                                style: theme.textTheme.titleMedium?.copyWith(
                                  fontWeight: FontWeight.w600,
                                ),
                              ),
                            ),
                            IconButton(
                              icon: const Icon(LucideIcons.x, size: 20),
                              onPressed: () => Navigator.of(context).pop(),
                              padding: EdgeInsets.zero,
                              constraints: const BoxConstraints(minWidth: 36, minHeight: 36),
                            ),
                          ],
                        ),
                      ),
                      if (subtitle != null)
                        Padding(
                          padding: const EdgeInsets.fromLTRB(24, 0, 24, 8),
                          child: Align(
                            alignment: Alignment.centerLeft,
                            child: Text(
                              subtitle,
                              style: TextStyle(fontSize: 13, color: theme.hintColor),
                            ),
                          ),
                        ),
                      const Divider(height: 1),
                      // Options
                      ConstrainedBox(
                        constraints: BoxConstraints(
                          maxHeight: MediaQuery.of(context).size.height * 0.5,
                        ),
                        child: ListView.builder(
                          shrinkWrap: true,
                          padding: const EdgeInsets.symmetric(vertical: 4),
                          itemCount: options.length,
                          itemBuilder: (context, index) {
                            final (value, label, isSelected) = options[index];
                            return ListTile(
                              leading: Icon(
                                isSelected
                                    ? LucideIcons.checkCircle2
                                    : LucideIcons.circle,
                                size: 20,
                                color: isSelected
                                    ? colorScheme.primary
                                    : theme.hintColor,
                              ),
                              title: Text(label),
                              selected: isSelected,
                              onTap: () => Navigator.of(context).pop(value),
                            );
                          },
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ),
        );
      },
    );
  }

  Future<void> _showGravatarMirrorUrlDialog(BuildContext context) async {
    final controller = TextEditingController(text: _gravatarMirrorUrl);
    final presets = [
      'https://weavatar.com',
      'https://gravatar.loli.net',
      'https://cdn.v2ex.com/gravatar',
    ];

    final selected = await showDialog<String>(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text('Gravatar 镜像地址'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            TextField(
              controller: controller,
              decoration: const InputDecoration(
                labelText: '镜像地址',
                hintText: '例如: https://weavatar.com',
                isDense: true,
              ),
            ),
            const SizedBox(height: 16),
            const Text('常用镜像：', style: TextStyle(fontSize: 12, color: Colors.grey)),
            const SizedBox(height: 8),
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: presets.map((url) => ActionChip(
                label: Text(url, style: const TextStyle(fontSize: 11)),
                onPressed: () => controller.text = url,
              )).toList(),
            ),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(ctx).pop(),
            child: const Text('取消'),
          ),
          FilledButton(
            onPressed: () => Navigator.of(ctx).pop(controller.text.trim()),
            child: const Text('确定'),
          ),
        ],
      ),
    );

    if (selected != null && selected.isNotEmpty && mounted) {
      var url = selected;
      if (url.endsWith('/')) url = url.substring(0, url.length - 1);
      setState(() => _gravatarMirrorUrl = url);
      await StorageService.instance
          .setString(StorageKeys.gravatarMirrorUrl, url);
    }
  }

  Future<void> _clearCache() async {
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (dialogContext) => AlertDialog(
        title: const Text('清空缓存'),
        content: const Text('确定要清空所有缓存吗？'),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(dialogContext).pop(false),
            child: const Text('取消'),
          ),
          FilledButton(
            onPressed: () => Navigator.of(dialogContext).pop(true),
            style: FilledButton.styleFrom(backgroundColor: Theme.of(context).colorScheme.error),
            child: const Text('清空'),
          ),
        ],
      ),
    );

    if (confirmed == true && mounted) {
      setState(() => _isCleaning = true);
      try {
        final service = CacheManagerService.instance;
        await service.clearCache();
        final newCacheSize = await service.getCacheSize();
        if (mounted) {
          setState(() {
            _currentCacheSize = newCacheSize;
            _isCleaning = false;
          });
          ToastHelper.success('缓存已清空');
        }
      } catch (e) {
        if (mounted) {
          setState(() => _isCleaning = false);
          ToastHelper.failure('清空缓存失败: $e');
        }
      }
    }
  }

  String _formatBytes(int? bytes) {
    if (bytes == null) return '未知';
    if (bytes < 1024) return '$bytes B';
    if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)} KB';
    if (bytes < 1024 * 1024 * 1024) return '${(bytes / (1024 * 1024)).toStringAsFixed(1)} MB';
    return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(1)} GB';
  }

  Future<void> _openLogFolder() async {
    try {
      final path = _logFilePath;
      if (path.isEmpty) {
        ToastHelper.error('日志文件路径未获取');
        return;
      }
      final dir = File(path).parent.path;
      final result = await OpenFile.open(dir);
      if (result.type != ResultType.done) {
        if (mounted) ToastHelper.error('无法打开目录：${result.message}');
      }
    } catch (e) {
      if (mounted) ToastHelper.error('打开目录失败：$e');
    }
  }

  Future<void> _openCacheDir() async {
    try {
      if (_cacheDirPath.isEmpty) {
        ToastHelper.error('缓存目录路径未获取');
        return;
      }
      final result = await OpenFile.open(_cacheDirPath);
      if (result.type != ResultType.done) {
        if (mounted) ToastHelper.error('无法打开目录：${result.message}');
      }
    } catch (e) {
      if (mounted) ToastHelper.error('打开目录失败：$e');
    }
  }

  Future<void> _exportLog() async {
    try {
      final dir = await DownloadService().getDownloadDirectory();
      final destPath = await AppLogger.exportLog(dir.path);
      if (destPath != null && mounted) {
        ToastHelper.success('日志已导出到：$destPath');
      } else if (mounted) {
        ToastHelper.error('导出失败：日志文件不存在');
      }
    } catch (e) {
      if (mounted) ToastHelper.error('导出日志失败：$e');
    }
  }

  Future<void> _previewLog() async {
    Navigator.of(context).push(
      MaterialPageRoute(builder: (_) => const LogViewerPage()),
    );
  }

  Future<void> _clearLog() async {
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (dialogContext) => AlertDialog(
        title: const Text('清空日志'),
        content: const Text('确定要清空日志文件内容吗？此操作不可恢复。'),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(dialogContext).pop(false),
            child: const Text('取消'),
          ),
          FilledButton(
            onPressed: () => Navigator.of(dialogContext).pop(true),
            style: FilledButton.styleFrom(backgroundColor: Theme.of(context).colorScheme.error),
            child: const Text('清空'),
          ),
        ],
      ),
    );

    if (confirmed == true && mounted) {
      await AppLogger.clearLog();
      await _loadLogInfo();
      if (mounted) ToastHelper.success('日志已清空');
    }
  }

  String _logLevelLabel(Level level) {
    return switch (level) {
      Level.error => 'Error — 仅错误',
      Level.warning => 'Warning — 错误 + 警告',
      Level.info => 'Info — 常规信息',
      Level.debug => 'Debug — 调试信息（含FFI交互）',
      Level.trace => 'Trace — 全量追踪',
      _ => level.name,
    };
  }

  Level _parseLogLevel(String level) {
    return switch (level) {
      'error' => Level.error,
      'warning' => Level.warning,
      'info' => Level.info,
      'debug' => Level.debug,
      'trace' => Level.trace,
      _ => Level.info,
    };
  }

  Future<void> _pickLogLevel() async {
    final levels = [
      (Level.error, 'Error — 仅错误'),
      (Level.warning, 'Warning — 错误 + 警告'),
      (Level.info, 'Info — 常规信息'),
      (Level.debug, 'Debug — 调试信息（含FFI）'),
      (Level.trace, 'Trace — 全量追踪'),
    ];

    final result = await showDialog<Level>(
      context: context,
      builder: (ctx) => SimpleDialog(
        title: const Text('日志级别'),
        children: levels.map((e) {
          final isSelected = _logLevel == e.$1;
          return SimpleDialogOption(
            onPressed: () => Navigator.pop(ctx, e.$1),
            child: Row(
              children: [
                Icon(
                  isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
                  size: 20,
                  color: isSelected ? Theme.of(ctx).colorScheme.primary : Theme.of(ctx).hintColor,
                ),
                const SizedBox(width: 8),
                Flexible(child: Text(e.$2)),
              ],
            ),
          );
        }).toList(),
      ),
    );

    if (result != null && result != _logLevel) {
      setState(() => _logLevel = result);
      AppLogger.setLevel(result);
      await StorageService.instance.setString(
        StorageKeys.logLevel,
        result.name,
      );
      if (mounted) ToastHelper.success('日志级别已切换为 ${_logLevelLabel(result)}');
    }
  }
}
