import 'dart:convert';
import 'dart:io';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:fpdart/fpdart.dart';
import 'package:get/get.dart';

import 'package:hooks_riverpod/hooks_riverpod.dart';

import 'package:kaer_with_panels/singbox/service/singbox_service.dart';
import 'package:kaer_with_panels/singbox/service/singbox_service_provider.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;

import '../../../core/model/directories.dart';
import '../../../singbox/model/singbox_config_option.dart';
import '../../../singbox/model/singbox_outbound.dart';
import '../../../singbox/model/singbox_stats.dart';
import '../../../singbox/model/singbox_status.dart';
import '../../utils/kr_country_util.dart';
import '../../utils/kr_log_util.dart';
import '../../utils/kr_secure_storage.dart';
import '../../utils/kr_windows_dns_util.dart';
import '../../utils/kr_macos_proxy_util.dart';
import '../../common/app_run_data.dart';
import '../../common/app_config.dart';
import 'package:flutter/foundation.dart';

enum KRConnectionType {
  global,
  rule,
  // direct,
}

class KRSingBoxImp {
  /// 私有构造函数
  KRSingBoxImp._();

  /// 单例实例
  static final KRSingBoxImp _instance = KRSingBoxImp._();

  /// 工厂构造函数
  factory KRSingBoxImp() => _instance;

  /// 获取实例的静态方法
  static KRSingBoxImp get instance => _instance;

  /// 配置文件目录
  late Directories kr_configDics;

  /// 配置文件名称
  String kr_configName = "hiFastVPN";

  /// 存储键：用户选择的节点
  static const String _keySelectedNode = 'SELECTED_NODE_TAG';

  /// 通道方法
  final _kr_methodChannel = const MethodChannel("com.hi.app/platform");

  final _kr_container = ProviderContainer();

  /// 核心服务
  late SingboxService kr_singBox;

  /// more配置
  Map<String, dynamic> kr_configOption = {};

  List<Map<String, dynamic>> kr_outbounds = [];

  /// 首次启动
  RxBool kr_isFristStart = false.obs;

  /// 状态
  final kr_status = SingboxStatus.stopped().obs;

  /// 拦截广告
  final kr_blockAds = false.obs;

  /// 是否自动自动选择线路
  final kr_isAutoOutbound = false.obs;

  /// 连接类型
  final kr_connectionType = KRConnectionType.rule.obs;

  String _cutPath = "";

  /// 端口
  int kr_port = 51213;

  /// 统计
  final kr_stats = SingboxStats(
    connectionsIn: 0,
    connectionsOut: 0,
    uplink: 0,
    downlink: 0,
    uplinkTotal: 0,
    downlinkTotal: 0,
  ).obs;

  /// 活动的出站分组
  RxList<SingboxOutboundGroup> kr_activeGroups = <SingboxOutboundGroup>[].obs;

  // 🔒 Windows DNS 优化：标志位，记录 DNS 是否已备份
  bool _dnsBackedUp = false;

  /// 所有的出站分组
  RxList<SingboxOutboundGroup> kr_allGroups = <SingboxOutboundGroup>[].obs;

  /// Stream 订阅管理器
  final List<StreamSubscription<dynamic>> _kr_subscriptions = [];

  StreamSubscription<SingboxStatus>? _kr_statusSubscription;

  /// 初始化标志，防止重复初始化
  bool _kr_isInitialized = false;

  /// 初始化进行中共享 Future（single-flight 防并发）
  Future<void>? _kr_initFuture;

  /// 当前混合代理端口是否就绪
  bool get kr_isProxyReady => kr_status.value is SingboxStarted;

  String? _lastProxyRule;

  /// 构建 Dart HttpClient 可识别的代理规则字符串
  ///
  /// 当 sing-box 尚未启动时返回 `DIRECT`，启动后返回
  /// `PROXY 127.0.0.1:<port>; DIRECT`，以便在代理不可用时自动回落。
  String kr_buildProxyRule({bool includeDirectFallback = true}) {
    if (!kr_isProxyReady) {
      const directRule = 'DIRECT';
      if (_lastProxyRule != directRule) {
        KRLogUtil.kr_i('⏳ sing-box 未就绪，使用 DIRECT 直连', tag: 'SingBox');
        _lastProxyRule = directRule;
      }
      return directRule;
    }
    final proxyRule = StringBuffer('PROXY 127.0.0.1:$kr_port');
    if (includeDirectFallback) {
      proxyRule.write('; DIRECT');
    }
    final ruleString = proxyRule.toString();
    if (_lastProxyRule != ruleString) {
      KRLogUtil.kr_i('🛠️ 使用代理规则: $ruleString', tag: 'SingBox');
      _lastProxyRule = ruleString;
    }
    return ruleString;
  }

  /// 初始化
  Future<void> init() async {
    // 防止重复初始化（已完成）
    if (_kr_isInitialized) {
      KRLogUtil.kr_i('SingBox 已经初始化，跳过重复初始化', tag: 'SingBox');
      return;
    }

    // 防止并发重复初始化（进行中复用同一个 Future）
    if (_kr_initFuture != null) {
      KRLogUtil.kr_i('SingBox 初始化进行中，等待完成（single-flight）', tag: 'SingBox');
      await _kr_initFuture;
      return;
    }

    // 建立 single-flight 共享 Future
    final completer = Completer<void>();
    _kr_initFuture = completer.future;

    try {
      KRLogUtil.kr_i('开始初始化 SingBox');
      // 在应用启动时初始化
      await KRCountryUtil.kr_init();
      KRLogUtil.kr_i('国家工具初始化完成');

      final oOption = SingboxConfigOption.fromJson(_getConfigOption());
      KRLogUtil.kr_i('配置选项初始化完成');

      KRLogUtil.kr_i('开始初始化 SingBox 服务');
      kr_singBox = await _kr_container.read(singboxServiceProvider);
      await _kr_container.read(singboxServiceProvider).init();
      KRLogUtil.kr_i('SingBox 服务初始化完成');

      KRLogUtil.kr_i('开始初始化目录');

      /// 初始化目录
      if (Platform.isIOS) {
        final paths = await _kr_methodChannel.invokeMethod<Map>("get_paths");
        KRLogUtil.kr_i('iOS 路径获取完成: $paths');

        kr_configDics = (
          baseDir: Directory(paths?["base"]! as String),
          workingDir: Directory(paths?["working"]! as String),
          tempDir: Directory(paths?["temp"]! as String),
        );
      } else {
        final baseDir = await getApplicationSupportDirectory();
        final workingDir =
            Platform.isAndroid ? await getExternalStorageDirectory() : baseDir;
        final tempDir = await getTemporaryDirectory();

        // Windows 路径规范化：确保使用正确的路径分隔符
        Directory normalizePath(Directory dir) {
          if (Platform.isWindows) {
            final normalized = dir.path.replaceAll('/', '\\');
            if (normalized != dir.path) {
              KRLogUtil.kr_i('路径规范化: ${dir.path} -> $normalized',
                  tag: 'SingBox');
              return Directory(normalized);
            }
          }
          return dir;
        }

        kr_configDics = (
          baseDir: normalizePath(baseDir),
          workingDir: normalizePath(workingDir!),
          tempDir: normalizePath(tempDir),
        );
        KRLogUtil.kr_i('其他平台路径初始化完成');
      }

      KRLogUtil.kr_i('开始创建目录');
      KRLogUtil.kr_i('baseDir: ${kr_configDics.baseDir.path}', tag: 'SingBox');
      KRLogUtil.kr_i('workingDir: ${kr_configDics.workingDir.path}',
          tag: 'SingBox');
      KRLogUtil.kr_i('tempDir: ${kr_configDics.tempDir.path}', tag: 'SingBox');

      // 确保所有目录都存在
      if (!kr_configDics.baseDir.existsSync()) {
        await kr_configDics.baseDir.create(recursive: true);
        KRLogUtil.kr_i('已创建 baseDir', tag: 'SingBox');
      }
      if (!kr_configDics.workingDir.existsSync()) {
        await kr_configDics.workingDir.create(recursive: true);
        KRLogUtil.kr_i('已创建 workingDir', tag: 'SingBox');
      }
      if (!kr_configDics.tempDir.existsSync()) {
        await kr_configDics.tempDir.create(recursive: true);
        KRLogUtil.kr_i('已创建 tempDir', tag: 'SingBox');
      }

      // 创建 libcore 数据库所需的 data 目录（在 workingDir 下）
      // 注意：libcore 的 Setup 会调用 os.Chdir(workingPath)，所以 data 目录必须在 workingDir 下
      final dataDir = Directory(p.join(kr_configDics.workingDir.path, 'data'));

      // 强制确保 data 目录存在（Windows 可能需要多次尝试）
      int retryCount = 0;
      const maxRetries = 5;
      while (!dataDir.existsSync() && retryCount < maxRetries) {
        try {
          await dataDir.create(recursive: true);
          // 等待文件系统同步（Windows 上可能需要一点时间）
          await Future.delayed(const Duration(milliseconds: 100));

          // 验证目录确实创建成功
          if (dataDir.existsSync()) {
            KRLogUtil.kr_i('✅ 已创建 data 目录: ${dataDir.path}', tag: 'SingBox');
            break;
          } else {
            retryCount++;
            KRLogUtil.kr_i('⚠️ data 目录创建后验证失败，重试 $retryCount/$maxRetries',
                tag: 'SingBox');
            await Future.delayed(const Duration(milliseconds: 200));
          }
        } catch (e) {
          retryCount++;
          KRLogUtil.kr_e('❌ 创建 data 目录失败 (尝试 $retryCount/$maxRetries): $e',
              tag: 'SingBox');
          if (retryCount >= maxRetries) {
            throw Exception('无法创建 libcore 数据库目录: ${dataDir.path}，错误: $e');
          }
          final delayMs = 200 * retryCount;
          await Future.delayed(Duration(milliseconds: delayMs));
        }
      }

      if (!dataDir.existsSync()) {
        final error = 'data 目录不存在: ${dataDir.path}';
        KRLogUtil.kr_e('❌ $error', tag: 'SingBox');
        throw Exception(error);
      }

      // 验证目录权限（尝试创建一个测试文件）
      try {
        final testFile = File(p.join(dataDir.path, '.test_write'));
        await testFile.writeAsString('test');
        await testFile.delete();
        KRLogUtil.kr_i('✅ data 目录写入权限验证通过', tag: 'SingBox');
      } catch (e) {
        KRLogUtil.kr_e('⚠️ data 目录写入权限验证失败: $e', tag: 'SingBox');
        // 不抛出异常，让 libcore 自己处理
      }

      // 在 Windows 上额外等待，确保文件系统操作完成
      if (Platform.isWindows) {
        await Future.delayed(const Duration(milliseconds: 300));
        KRLogUtil.kr_i('⏳ Windows 文件系统同步等待完成', tag: 'SingBox');
      }

      // 🍎 macOS 平台：初始化时确保代理关闭（防止上次崩溃残留）
      if (Platform.isMacOS) {
        KRLogUtil.kr_i('🍎 macOS 平台，初始化时清理系统代理残留...', tag: 'SingBox');
        try {
          // 异步执行，不阻塞初始化主流程
          KRMacosProxyUtil.disableSocks5().then((_) {
            KRLogUtil.kr_i('✅ macOS 系统代理残留清理完成', tag: 'SingBox');
          }).catchError((e) {
            KRLogUtil.kr_w('⚠️ macOS 系统代理清理异常: $e', tag: 'SingBox');
          });
        } catch (e) {
          KRLogUtil.kr_w('⚠️ macOS 系统代理清理尝试失败: $e', tag: 'SingBox');
        }
      }

      // 最终验证：在 setup() 之前再次确认 workingDir 和 data 目录都存在且可访问
      // libcore 的 Setup() 会调用 os.Chdir(workingPath)，然后使用相对路径 "./data"
      // 如果 os.Chdir() 失败（路径不存在或权限问题），后续的相对路径访问会失败
      if (!kr_configDics.workingDir.existsSync()) {
        final error =
            '❌ workingDir 不存在，无法调用 setup(): ${kr_configDics.workingDir.path}';
        KRLogUtil.kr_e(error, tag: 'SingBox');
        throw Exception(error);
      }

      // 验证 workingDir 可读可写
      try {
        final testWorkingFile =
            File(p.join(kr_configDics.workingDir.path, '.test_working_dir'));
        await testWorkingFile.writeAsString('test');
        await testWorkingFile.delete();
        KRLogUtil.kr_i('✅ workingDir 写入权限验证通过', tag: 'SingBox');
      } catch (e) {
        final error =
            '❌ workingDir 无写入权限: ${kr_configDics.workingDir.path}, 错误: $e';
        KRLogUtil.kr_e(error, tag: 'SingBox');
        throw Exception(error);
      }

      final finalDataDir =
          Directory(p.join(kr_configDics.workingDir.path, 'data'));
      if (!finalDataDir.existsSync()) {
        KRLogUtil.kr_e('❌ 最终验证失败：data 目录不存在', tag: 'SingBox');
        KRLogUtil.kr_e('路径: ${finalDataDir.path}', tag: 'SingBox');
        KRLogUtil.kr_e(
            'workingDir 是否存在: ${kr_configDics.workingDir.existsSync()}',
            tag: 'SingBox');
        if (kr_configDics.workingDir.existsSync()) {
          try {
            final workingDirContents = kr_configDics.workingDir.listSync();
            KRLogUtil.kr_e(
                'workingDir 内容: ${workingDirContents.map((e) => e.path.split(Platform.pathSeparator).last).join(", ")}',
                tag: 'SingBox');
          } catch (e) {
            KRLogUtil.kr_e('无法列出 workingDir 内容: $e', tag: 'SingBox');
          }
        }
        throw Exception('data 目录在 setup() 前验证失败: ${finalDataDir.path}');
      }

      // 再次尝试写入测试，确保目录确实可用
      try {
        final verifyFile = File(p.join(finalDataDir.path, '.verify_setup'));
        await verifyFile.writeAsString('verify');
        await verifyFile.delete();
        KRLogUtil.kr_i('✅ setup() 前最终验证通过', tag: 'SingBox');
      } catch (e) {
        KRLogUtil.kr_e('❌ setup() 前最终验证失败: $e', tag: 'SingBox');
        // 不抛出异常，让 setup() 自己处理
      }

      final configsDir =
          Directory(p.join(kr_configDics.workingDir.path, "configs"));
      if (!configsDir.existsSync()) {
        try {
          await configsDir.create(recursive: true);
          KRLogUtil.kr_i('✅ 已创建 configs 目录: ${configsDir.path}',
              tag: 'SingBox');
        } catch (e) {
          KRLogUtil.kr_e('⚠️ configs 目录创建失败: $e', tag: 'SingBox');
          // 不抛出异常，继续初始化
        }
      } else {
        KRLogUtil.kr_i('✅ configs 目录已存在: ${configsDir.path}', tag: 'SingBox');
      }

      // 特别处理 extensionData.db 文件 (Windows特定)
      if (Platform.isWindows) {
        try {
          final extensionDataDbPath =
              p.join(finalDataDir.path, 'extensionData.db');
          KRLogUtil.kr_i('👉 准备处理 extensionData.db 路径: $extensionDataDbPath',
              tag: 'SingBox');

          // 确保 extensionData.db 的父目录存在
          final extensionDataParent = Directory(p.dirname(extensionDataDbPath));
          if (!extensionDataParent.existsSync()) {
            await extensionDataParent.create(recursive: true);
            KRLogUtil.kr_i('✅ 已创建 extensionData.db 父目录', tag: 'SingBox');
          }

          // 测试文件创建权限
          final testFile =
              File(p.join(extensionDataParent.path, '.test_extension'));
          await testFile.writeAsString('test');
          await testFile.delete();
          KRLogUtil.kr_i('✅ extensionData 目录权限验证通过', tag: 'SingBox');
        } catch (e) {
          KRLogUtil.kr_e('⚠️ extensionData 目录处理失败: $e', tag: 'SingBox');
          // 不抛出异常，继续初始化
        }
      }

      KRLogUtil.kr_i('✅ 目录创建完成', tag: 'SingBox');
      KRLogUtil.kr_i('开始设置 SingBox', tag: 'SingBox');
      KRLogUtil.kr_i('  - baseDir: ${kr_configDics.baseDir.path}',
          tag: 'SingBox');
      KRLogUtil.kr_i('  - workingDir: ${kr_configDics.workingDir.path}',
          tag: 'SingBox');
      KRLogUtil.kr_i('  - tempDir: ${kr_configDics.tempDir.path}',
          tag: 'SingBox');
      KRLogUtil.kr_i(
          '  - data 目录: ${p.join(kr_configDics.workingDir.path, "data")}',
          tag: 'SingBox');
      KRLogUtil.kr_i('  - data 目录存在: ${finalDataDir.existsSync()}',
          tag: 'SingBox');

      // 在 Windows 上，列出 data 目录内容（如果有文件）
      if (Platform.isWindows && finalDataDir.existsSync()) {
        try {
          final dataContents = finalDataDir.listSync();
          if (dataContents.isNotEmpty) {
            KRLogUtil.kr_i(
                '  - data 目录现有文件: ${dataContents.map((e) => e.path.split(Platform.pathSeparator).last).join(", ")}',
                tag: 'SingBox');
          } else {
            KRLogUtil.kr_i('  - data 目录为空', tag: 'SingBox');
          }
        } catch (e) {
          KRLogUtil.kr_e('  - 无法列出 data 目录内容: $e', tag: 'SingBox');
        }
      }

      KRLogUtil.kr_i(
          '  - libcore 将通过 os.Chdir() 切换到: ${kr_configDics.workingDir.path}',
          tag: 'SingBox');
      KRLogUtil.kr_i('  - 然后使用相对路径 "./data" 访问数据库', tag: 'SingBox');

      // Windows 特定：验证路径格式是否正确
      if (Platform.isWindows) {
        final workingPath = kr_configDics.workingDir.path;
        if (workingPath.contains('/')) {
          KRLogUtil.kr_e('⚠️ 警告：Windows 路径包含正斜杠，可能导致问题: $workingPath',
              tag: 'SingBox');
        }
        // 确保路径使用反斜杠（Windows 标准）
        final normalizedPath = workingPath.replaceAll('/', '\\');
        if (normalizedPath != workingPath) {
          KRLogUtil.kr_e('⚠️ 路径格式可能需要规范化: $workingPath -> $normalizedPath',
              tag: 'SingBox');
        }
      }

      // 🔑 关键步骤：调用 setup() 将 NativePort 传递给 libcore
      // 这样 libcore 才能通过 GoDart_PostCObject() 向 Dart 发送消息
      KRLogUtil.kr_i('📡 开始调用 setup() 注册 FFI 端口', tag: 'SingBox');
      final setupResult = await kr_singBox.setup(kr_configDics, false).run();
      setupResult.match(
        (error) {
          KRLogUtil.kr_e('❌ setup() 失败: $error', tag: 'SingBox');
          throw Exception('FFI setup 失败: $error');
        },
        (_) {
          KRLogUtil.kr_i('✅ setup() 成功，FFI 端口已注册', tag: 'SingBox');
        },
      );

      KRLogUtil.kr_i('✅ SingBox 初始化完成');

      // 🔧 提取 geosite 文件到 workingDir
      KRLogUtil.kr_i('📦 开始提取 geosite 文件...', tag: 'SingBox');
      await _kr_extractGeositeFiles();
      KRLogUtil.kr_i('✅ geosite 文件提取完成', tag: 'SingBox');

      _kr_isInitialized = true;

      // 🔑 关键：在初始化完成后立即订阅状态变化流
      // 这样可以确保 UI 始终与 libcore 的实际状态同步
      _kr_subscribeToStatus();
      KRLogUtil.kr_i('✅ 状态订阅已设置', tag: 'SingBox');

      // 完成 single-flight
      completer.complete();
      _kr_initFuture = null;
    } catch (e, stackTrace) {
      KRLogUtil.kr_e('❌ SingBox 初始化失败: $e');
      KRLogUtil.kr_e('📚 错误堆栈: $stackTrace');

      // 添加额外的诊断信息
      if (Platform.isWindows) {
        try {
          final workingDir = kr_configDics.workingDir;
          final dataDir = Directory(p.join(workingDir.path, 'data'));
          final configsDir = Directory(p.join(workingDir.path, 'configs'));

          KRLogUtil.kr_e('🔍 Windows 路径诊断信息:', tag: 'SingBox');
          KRLogUtil.kr_e('  - workingDir: ${workingDir.path}', tag: 'SingBox');
          KRLogUtil.kr_e('  - workingDir 存在: ${workingDir.existsSync()}',
              tag: 'SingBox');
          KRLogUtil.kr_e('  - data 目录: ${dataDir.path}', tag: 'SingBox');
          KRLogUtil.kr_e('  - data 目录存在: ${dataDir.existsSync()}',
              tag: 'SingBox');
          KRLogUtil.kr_e('  - configs 目录: ${configsDir.path}', tag: 'SingBox');
          KRLogUtil.kr_e('  - configs 目录存在: ${configsDir.existsSync()}',
              tag: 'SingBox');

          // 检查父目录内容
          if (workingDir.existsSync()) {
            try {
              final contents = workingDir.listSync();
              KRLogUtil.kr_e(
                  '  - workingDir 内容: ${contents.map((e) => "${e.path.split(Platform.pathSeparator).last}${e is Directory ? "/" : ""}").join(", ")}',
                  tag: 'SingBox');
            } catch (listErr) {
              KRLogUtil.kr_e('  - 无法列出 workingDir 内容: $listErr',
                  tag: 'SingBox');
            }
          }
        } catch (diagErr) {
          KRLogUtil.kr_e('  - 诊断信息收集失败: $diagErr', tag: 'SingBox');
        }
      }

      // 如果初始化失败，允许下次重试
      _kr_isInitialized = false;
      // 失败时通知等待者并清理 single-flight
      if (!completer.isCompleted) {
        completer.completeError(e, stackTrace);
      }
      _kr_initFuture = null;
      rethrow;
    }
  }

  /// 提取 geosite 文件到 workingDir
  Future<void> _kr_extractGeositeFiles() async {
    try {
      // 创建 geosite 目录
      final geositeDir =
          Directory(p.join(kr_configDics.workingDir.path, 'geosite'));
      if (!geositeDir.existsSync()) {
        await geositeDir.create(recursive: true);
        KRLogUtil.kr_i('✅ 已创建 geosite 目录: ${geositeDir.path}', tag: 'SingBox');
      }

      // 需要提取的文件列表
      final files = ['geoip-cn.srs', 'geosite-cn.srs'];

      for (final filename in files) {
        final assetPath = 'assets/geosite/$filename';
        final targetPath = p.join(geositeDir.path, filename);
        final targetFile = File(targetPath);

        // 检查文件是否已存在
        if (targetFile.existsSync()) {
          final fileSize = await targetFile.length();
          KRLogUtil.kr_i('📄 $filename 已存在 (${fileSize} bytes), 跳过',
              tag: 'SingBox');
          continue;
        }

        // 从 assets 加载文件
        KRLogUtil.kr_i('📥 正在提取 $filename...', tag: 'SingBox');
        final byteData = await rootBundle.load(assetPath);
        final bytes = byteData.buffer.asUint8List();

        // 写入文件系统
        await targetFile.writeAsBytes(bytes);
        final writtenSize = await targetFile.length();

        KRLogUtil.kr_i('✅ 提取成功: $filename (${writtenSize} bytes)',
            tag: 'SingBox');
      }

      KRLogUtil.kr_i('🎉 所有 geosite 文件提取完成', tag: 'SingBox');
    } catch (e, stackTrace) {
      KRLogUtil.kr_e('❌ 提取 geosite 文件失败: $e', tag: 'SingBox');
      KRLogUtil.kr_e('堆栈: $stackTrace', tag: 'SingBox');
      // 不抛出异常,让应用继续运行(使用远程规则集作为后备)
    }
  }

  Map<String, dynamic> _getConfigOption() {
    // 不使用缓存，每次都重新生成配置
    // if (kr_configOption.isNotEmpty) {
    //   return kr_configOption;
    // }

    // 🔧 关键修复：全局代理模式下，region 强制设为 'other'，libcore 就不会生成国家直连规则
    final String effectiveRegion;
    if (kr_connectionType.value == KRConnectionType.global) {
      effectiveRegion = 'other'; // 全局代理：不添加任何国家规则
      KRLogUtil.kr_i('🌐 [全局代理模式] region 设为 other，所有流量走代理', tag: 'SingBox');
    } else {
      effectiveRegion =
          KRCountryUtil.kr_getCurrentCountryCode(); // 智能代理：使用用户选择的国家
      KRLogUtil.kr_i('✅ [智能代理模式] region 设为 $effectiveRegion', tag: 'SingBox');
    }

    final useWindowsDnsDefaults = Platform.isWindows;
    final remoteDnsAddress = useWindowsDnsDefaults
        ? 'udp://1.1.1.1'
        : 'https://dns.google/dns-query';
    final directDnsAddress = effectiveRegion == 'cn'
        ? 'udp://223.5.5.5'  // 中国: 阿里DNS（国内域名解析快）
        : 'udp://1.1.1.1'; // 其他: Cloudflare UDP（避免 local 被污染）
    final dnsDomainStrategy = useWindowsDnsDefaults ? '' : 'prefer_ipv4';

    final op = {
      "region": effectiveRegion, // 🔧 修复：根据出站模式动态设置 region
      "block-ads": false, // 参考 hiddify-app: 默认关闭广告拦截
      "use-xray-core-when-possible": false,
      "execute-config-as-is": true, // 🔧 修复：使用我们生成的完整配置，不让 libcore 重写
      "log-level": "info", // 调试阶段使用 info，生产环境改为 warn
      "resolve-destination": false,
      "ipv6-mode":
          "ipv4_only", // 参考 hiddify-app: 仅使用 IPv4 (有效值: ipv4_only, prefer_ipv4, prefer_ipv6, ipv6_only)
      "remote-dns-address": remoteDnsAddress,  // 使用 Google DoH，避免中转节点 DNS 死锁
      "remote-dns-domain-strategy": dnsDomainStrategy,
      "direct-dns-address": directDnsAddress,  // 使用系统 DNS，确保中转服务器域名能被解析
      "direct-dns-domain-strategy": dnsDomainStrategy,
      "mixed-port": kr_port,
      "tproxy-port": kr_port,
      "local-dns-port": 36450,
      "tun-implementation": "gvisor",
      "mtu": 9000,
      "strict-route": true,
      "connection-test-url":
          "http://cp.cloudflare.com", // 参考 hiddify-app: 使用 Cloudflare 测试端点
      "url-test-interval": 30,
      "enable-clash-api": true,
      "clash-api-port": 36756,
      "enable-tun": Platform.isIOS || Platform.isAndroid,
      "enable-tun-service": false,
      "set-system-proxy":
          Platform.isWindows || Platform.isLinux || Platform.isMacOS,
      "bypass-lan": false,
      "allow-connection-from-lan": false,
      "enable-fake-dns": false,
      "enable-dns-routing": true,
      "independent-dns-cache": true,
      "rules": _kr_buildHiddifyRules(),
      "mux": {
        "enable": false,
        "padding": false,
        "max-streams": 8,
        "protocol": "h2mux"
      },
      "tls-tricks": {
        "enable-fragment": false,
        "fragment-size": "10-30",
        "fragment-sleep": "2-8",
        "mixed-sni-case": false,
        "enable-padding": false,
        "padding-size": "1-1500"
      },
      "warp": {
        "enable": false,
        "mode": "proxy_over_warp",
        "wireguard-config": "",
        "license-key": "",
        "account-id": "",
        "access-token": "",
        "clean-ip": "auto",
        "clean-port": 0,
        "noise": "1-3",
        "noise-size": "10-30",
        "noise-delay": "10-30",
        "noise-mode": "m4"
      },
      "warp2": {
        "enable": false,
        "mode": "proxy_over_warp",
        "wireguard-config": "",
        "license-key": "",
        "account-id": "",
        "access-token": "",
        "clean-ip": "auto",
        "clean-port": 0,
        "noise": "1-3",
        "noise-size": "10-30",
        "noise-delay": "10-30",
        "noise-mode": "m4"
      }
    };
    kr_configOption = op;

    // 🔧 调试日志：确认自定义规则已添加
    final rules = op["rules"] as List?;
    KRLogUtil.kr_i('✅ HiddifyOptions 已生成，包含 ${rules?.length ?? 0} 条自定义路由规则',
        tag: 'SingBox');
    if (rules != null && rules.isNotEmpty) {
      for (var rule in rules) {
        final ruleMap = rule as Map<String, dynamic>;
        KRLogUtil.kr_i(
            '   - 规则: domains=${ruleMap["domains"]}, outbound=${ruleMap["outbound"]}',
            tag: 'SingBox');
      }
    }

    return op;
  }

  List<Map<String, dynamic>> _kr_buildHiddifyRules() {
    final rules = <Map<String, dynamic>>[];
    rules.add({"domains": "domain:api.hifast.biz", "outbound": "bypass"});
    // 使用 domain:crisp.chat (这通常会匹配所有子域名)
    rules.add({"domains": "domain:crisp.chat", "outbound": "bypass"});
    // 某些 sing-box 版本可能需要显式包含 relay 域名
    rules.add({"domains": "domain:client.relay.crisp.chat", "outbound": "bypass"});

    // 🔧 新增：将动态域名列表加入到规则中 (直连)
    // 使用 Set 去重，避免重复添加
    final baseDomains = KRDomain.kr_baseDomains.toSet();
    KRLogUtil.kr_i('🔄 将 ${baseDomains.length} 个动态域名加入直连规则: $baseDomains', tag: 'SingBox');
    
    for (final domain in baseDomains) {
      if (domain.isNotEmpty) {
         // 检查是否已经存在（虽然Set去重了，但上面的硬编码可能重复）
         // 简单起见直接添加，sing-box 通常能处理重复规则，或者规则越前优先级越高
         rules.add({"domains": "domain:$domain", "outbound": "bypass"});
      }
    }

    final nodeDomains = _kr_collectNodeDomains();
    for (final d in nodeDomains) {
      rules.add({"domains": "domain:$d", "outbound": "bypass"});
    }

    KRLogUtil.kr_i('✅ 节点域名白名单数量: ${nodeDomains.length}', tag: 'SingBox');
    KRLogUtil.kr_i('✅ 节点域名白名单集合: ${jsonEncode(nodeDomains.toList())}',
        tag: 'SingBox');
    return rules;
  }

  Set<String> _kr_collectNodeDomains() {
    final set = <String>{};

    void addFromOutbound(Map<String, dynamic> o) {
      final server = o['server']?.toString();
      if (server != null &&
          server.isNotEmpty &&
          InternetAddress.tryParse(server) == null) {
        set.add(server.toLowerCase());
      }

      final tls = o['tls'];
      if (tls is Map) {
        final sni = tls['server_name']?.toString();
        if (sni != null &&
            sni.isNotEmpty &&
            InternetAddress.tryParse(sni) == null) {
          set.add(sni.toLowerCase());
        }
      }
    }

    for (final g in kr_outbounds) {
      addFromOutbound(g);
    }

    return set;
  }

  /// 订阅状态变化流
  /// 参考 hiddify-app: 监听 libcore 发送的状态事件来自动更新 UI
  void _kr_subscribeToStatus() {
    if (kDebugMode) {
      print('🔵 _kr_subscribeToStatus 被调用，重新订阅状态流');
    }
    KRLogUtil.kr_i('🔵 _kr_subscribeToStatus 被调用', tag: 'SingBox');

    _kr_statusSubscription?.cancel();
    _kr_statusSubscription = kr_singBox.watchStatus().listen(
      (status) {
        if (status == kr_status.value) {
          return;
        }
        if (kDebugMode) {
          print('🔵 收到 Native 状态更新: ${status.runtimeType}');
        }
        KRLogUtil.kr_i('📡 收到状态更新: $status', tag: 'SingBox');
        kr_status.value = status;
      },
      onError: (error) {
        if (kDebugMode) {
          print('🔵 状态流错误: $error');
        }
        KRLogUtil.kr_e('📡 状态流错误: $error', tag: 'SingBox');
      },
      cancelOnError: false,
    );

    if (kDebugMode) {
      print('🔵 状态流订阅完成');
    }
  }

  /// 订阅统计数据流
  void _kr_subscribeToStats() {
    // 取消之前的统计订阅
    for (var sub in _kr_subscriptions) {
      if (sub.hashCode.toString().contains('Stats')) {
        sub.cancel();
      }
    }
    _kr_subscriptions
        .removeWhere((sub) => sub.hashCode.toString().contains('Stats'));

    // ⚠️ 关键：watchStats() 内部会调用 FFI startCommandClient
    // 如果此时 command.sock 未就绪，会抛出异常
    // 所以外层必须有 try-catch
    final stream = kr_singBox.watchStats();
    final subscription = stream.listen(
      (stats) {
        kr_stats.value = stats;
      },
      onError: (error) {
        KRLogUtil.kr_e('统计数据监听错误: $error', tag: 'SingBox');
      },
      cancelOnError: false,
    );
    _kr_subscriptions.add(subscription);
  }

  /// 订阅分组数据流
  void _kr_subscribeToGroups() {
    print('[_kr_subscribeToGroups] 🚀 开始订阅分组数据流');
    // 取消之前的分组订阅
    for (var sub in _kr_subscriptions) {
      if (sub.hashCode.toString().contains('Groups')) {
        sub.cancel();
      }
    }
    _kr_subscriptions
        .removeWhere((sub) => sub.hashCode.toString().contains('Groups'));

    _kr_subscriptions.add(
      kr_singBox.watchActiveGroups().listen(
        (groups) {
          print('[watchActiveGroups] 📡 收到活动组更新，数量: ${groups.length}');
          KRLogUtil.kr_i('📡 收到活动组更新，数量: ${groups.length}', tag: 'SingBox');
          kr_activeGroups.value = groups;

          // 详细打印每个组的信息
          for (int i = 0; i < groups.length; i++) {
            final group = groups[i];
            KRLogUtil.kr_i(
                '📋 活动组[$i]: tag=${group.tag}, type=${group.type}, selected=${group.selected}',
                tag: 'SingBox');
            for (int j = 0; j < group.items.length; j++) {
              final item = group.items[j];
              KRLogUtil.kr_i(
                  '  └─ 节点[$j]: tag=${item.tag}, type=${item.type}, delay=${item.urlTestDelay}',
                  tag: 'SingBox');
            }
          }

          KRLogUtil.kr_i('✅ 活动组处理完成', tag: 'SingBox');
        },
        onError: (error) {
          print('[watchActiveGroups] ❌ 活动分组监听错误: $error');
          KRLogUtil.kr_e('❌ 活动分组监听错误: $error', tag: 'SingBox');
        },
        cancelOnError: false,
      ),
    );

    _kr_subscriptions.add(
      kr_singBox.watchGroups().listen(
        (groups) {
          print('[watchGroups] 📡 收到所有组更新，数量: ${groups.length}');
          kr_allGroups.value = groups;
          // 打印每个组的基本信息
          for (int i = 0; i < groups.length; i++) {
            final group = groups[i];
            print(
                '[watchGroups]   组[$i]: tag=${group.tag}, type=${group.type}, selected=${group.selected}');
          }
        },
        onError: (error) {
          print('[watchGroups] ❌ 所有分组监听错误: $error');
          KRLogUtil.kr_e('所有分组监听错误: $error');
        },
        cancelOnError: false,
      ),
    );
    print(
        '[_kr_subscribeToGroups] ✅ 分组数据流订阅完成，当前订阅数: ${_kr_subscriptions.length}');
  }

  /// 验证节点选择是否生效
  ///
  /// 检查活动组中 "select" 组的 selected 字段是否是目标节点
  Future<void> _kr_verifyNodeSelection(String targetTag) async {
    try {
      KRLogUtil.kr_i('🔍 开始验证节点选择: $targetTag', tag: 'SingBox');

      // 查找 "select" 组
      final selectGroup = kr_activeGroups.firstWhere(
        (group) => group.tag == 'select',
        orElse: () => throw Exception('未找到 "select" 选择器组'),
      );

      KRLogUtil.kr_i('📊 Select 组状态:', tag: 'SingBox');
      KRLogUtil.kr_i('  - 组标签: ${selectGroup.tag}', tag: 'SingBox');
      KRLogUtil.kr_i('  - 组类型: ${selectGroup.type}', tag: 'SingBox');
      KRLogUtil.kr_i('  - 当前选中: ${selectGroup.selected}', tag: 'SingBox');
      KRLogUtil.kr_i('  - 目标节点: $targetTag', tag: 'SingBox');
      KRLogUtil.kr_i('  - 可用节点数: ${selectGroup.items.length}', tag: 'SingBox');

      // 验证目标节点是否在可用列表中
      final hasTarget = selectGroup.items.any((item) => item.tag == targetTag);
      if (!hasTarget) {
        KRLogUtil.kr_w('⚠️ 目标节点不在 select 组的可用列表中: $targetTag', tag: 'SingBox');
        KRLogUtil.kr_w('可用节点列表:', tag: 'SingBox');
        for (var item in selectGroup.items) {
          KRLogUtil.kr_w('  - ${item.tag}', tag: 'SingBox');
        }
      }

      // 检查是否切换成功
      if (selectGroup.selected != targetTag) {
        KRLogUtil.kr_e('❌ 节点切换验证失败！', tag: 'SingBox');
        KRLogUtil.kr_e('  - 期望: $targetTag', tag: 'SingBox');
        KRLogUtil.kr_e('  - 实际: ${selectGroup.selected}', tag: 'SingBox');
        throw Exception('节点切换失败：实际选中 ${selectGroup.selected}，期望 $targetTag');
      }

      KRLogUtil.kr_i('✅ 节点切换验证成功: ${selectGroup.selected} == $targetTag',
          tag: 'SingBox');
    } catch (e) {
      KRLogUtil.kr_e('❌ 节点验证异常: $e', tag: 'SingBox');
      // 不抛出异常，只记录日志，避免阻塞流程
    }
  }

  /// 带重试机制的节点选择
  ///
  /// 确保 command.sock 准备好后再执行节点选择
  Future<void> _kr_selectOutboundWithRetry(
    String groupTag,
    String outboundTag, {
    int maxAttempts = 3,
    int initialDelay = 100,
  }) async {
    int attempt = 0;
    int delay = initialDelay;

    while (attempt < maxAttempts) {
      attempt++;
      KRLogUtil.kr_i(
        '🔄 尝试选择节点 $outboundTag (第 $attempt/$maxAttempts 次)',
        tag: 'SingBox',
      );

      // 只在失败后才延迟，首次尝试立即执行
      if (attempt > 1) {
        await Future.delayed(Duration(milliseconds: delay));
      }

      try {
        await kr_singBox.selectOutbound(groupTag, outboundTag).run();
        KRLogUtil.kr_i('✅ 节点选择成功: $outboundTag', tag: 'SingBox');
        return;
      } catch (e) {
        KRLogUtil.kr_w(
          '⚠️ 第 $attempt 次节点选择失败: $e',
          tag: 'SingBox',
        );

        if (attempt >= maxAttempts) {
          KRLogUtil.kr_e(
            '❌ 节点选择失败，已达到最大重试次数',
            tag: 'SingBox',
          );
          throw Exception('节点选择失败: $e');
        }

        // 指数退避
        delay = delay * 2;
      }
    }
  }

  /// 带重试机制的命令客户端初始化
  ///
  /// command.sock 需要时间创建，因此需要重试机制
  /// maxAttempts: 最大重试次数（默认10次，针对macOS优化）
  /// initialDelay: 初始延迟毫秒数（默认1000ms，针对macOS优化）
  Future<void> _kr_initializeCommandClientsWithRetry({
    int maxAttempts = 10,
    int initialDelay = 1000,
  }) async {
    int attempt = 0;
    int delay = initialDelay;

    while (attempt < maxAttempts) {
      attempt++;
      KRLogUtil.kr_i(
        '🔄 尝试初始化命令客户端 (第 $attempt/$maxAttempts 次，延迟 ${delay}ms)',
        tag: 'SingBox',
      );

      await Future.delayed(Duration(milliseconds: delay));

      try {
        // 先验证 command.sock 是否可访问
        final socketFile =
            File(p.join(kr_configDics.baseDir.path, 'command.sock'));
        KRLogUtil.kr_i('🔍 检查 socket 文件: ${socketFile.path}', tag: 'SingBox');

        if (!socketFile.existsSync()) {
          throw Exception('command.sock 文件不存在: ${socketFile.path}');
        }

        KRLogUtil.kr_i('✅ socket 文件存在，开始订阅...', tag: 'SingBox');

        // 尝试订阅统计和分组数据
        // ⚠️ 关键：分别 try-catch，避免一个失败影响另一个
        bool statsSubscribed = false;
        bool groupsSubscribed = false;

        // ⚠️ 关键修复：使用 Future.delayed(Duration.zero) 将订阅推到下一个事件循环
        // 这样可以避免阻塞当前的异步执行
        try {
          KRLogUtil.kr_i('📊 订阅统计数据流...', tag: 'SingBox');
          await Future.delayed(Duration.zero); // 让出 UI 线程
          _kr_subscribeToStats();
          statsSubscribed = true;
          KRLogUtil.kr_i('✅ 统计数据流订阅成功', tag: 'SingBox');
        } catch (e) {
          KRLogUtil.kr_w('⚠️ 统计数据流订阅失败: $e', tag: 'SingBox');
        }

        try {
          KRLogUtil.kr_i('📋 订阅分组数据流...', tag: 'SingBox');
          await Future.delayed(Duration.zero); // 让出 UI 线程
          _kr_subscribeToGroups();
          groupsSubscribed = true;
          KRLogUtil.kr_i('✅ 分组数据流订阅成功', tag: 'SingBox');
        } catch (e) {
          KRLogUtil.kr_w('⚠️ 分组数据流订阅失败: $e', tag: 'SingBox');
        }

        // 至少有一个订阅成功才算初始化成功
        if (!statsSubscribed && !groupsSubscribed) {
          throw Exception('所有订阅都失败了');
        }

        // 等待更长时间验证订阅是否成功，并实际接收到数据
        KRLogUtil.kr_i('⏳ 等待800ms验证订阅状态...', tag: 'SingBox');
        await Future.delayed(const Duration(milliseconds: 800));

        // 验证订阅是否真正工作（检查是否有数据流）
        if (_kr_subscriptions.isEmpty) {
          throw Exception('订阅列表为空，command client 未成功连接');
        }

        KRLogUtil.kr_i('✅ 命令客户端初始化成功，活跃订阅数: ${_kr_subscriptions.length}',
            tag: 'SingBox');
        return;
      } catch (e, stackTrace) {
        // 详细记录失败原因和堆栈信息
        KRLogUtil.kr_w(
          '⚠️ 第 $attempt 次尝试失败',
          tag: 'SingBox',
        );
        KRLogUtil.kr_w('❌ 错误类型: ${e.runtimeType}', tag: 'SingBox');
        KRLogUtil.kr_w('❌ 错误信息: $e', tag: 'SingBox');
        KRLogUtil.kr_w('📚 错误堆栈: $stackTrace', tag: 'SingBox');

        if (attempt >= maxAttempts) {
          KRLogUtil.kr_e(
            '❌ 命令客户端初始化失败，已达到最大重试次数 ($maxAttempts)',
            tag: 'SingBox',
          );
          KRLogUtil.kr_e('💡 提示: command.sock 可能未准备好或权限不足', tag: 'SingBox');
          throw Exception('命令客户端初始化失败: $e');
        }

        // 指数退避：每次失败后延迟翻倍（1000ms -> 2000ms -> 4000ms -> 8000ms）
        delay = delay * 2;
      }
    }
  }

  /// 在后台尝试预连接 command client（不阻塞启动流程）
  ///
  /// 借鉴 Hiddify 的设计思想：
  /// - watchStats/watchGroups 是懒加载的，首次调用时才会 startCommandClient()
  /// - 但我们可以在后台提前尝试连接，提高成功率
  /// - 即使失败也不影响主流程，真正的订阅会在 UI 调用时发生
  void _kr_tryPreconnectCommandClientsInBackground() {
    KRLogUtil.kr_i('🔄 后台启动 command client 预连接任务...', tag: 'SingBox');

    // 使用 Future.microtask 确保不阻塞当前执行
    Future.microtask(() async {
      try {
        // 等待 command.sock 就绪（macOS 需要更长时间）
        await Future.delayed(const Duration(milliseconds: 1500));

        // 检查 socket 文件
        final socketFile =
            File(p.join(kr_configDics.baseDir.path, 'command.sock'));
        if (!socketFile.existsSync()) {
          KRLogUtil.kr_w('⚠️ command.sock 尚未创建，预连接取消', tag: 'SingBox');
          return;
        }

        KRLogUtil.kr_i('✅ command.sock 已就绪，尝试预订阅...', tag: 'SingBox');

        // ⚠️ 注意：这里只是"触发"订阅，不等待结果
        // 如果失败，UI 调用时会重新尝试
        try {
          _kr_subscribeToStats();
          KRLogUtil.kr_i('✅ 统计流预订阅成功', tag: 'SingBox');
        } catch (e) {
          KRLogUtil.kr_w('⚠️ 统计流预订阅失败（正常，UI 调用时会重试）: $e', tag: 'SingBox');
        }

        try {
          _kr_subscribeToGroups();
          KRLogUtil.kr_i('✅ 分组流预订阅成功', tag: 'SingBox');
        } catch (e) {
          KRLogUtil.kr_w('⚠️ 分组流预订阅失败（正常，UI 调用时会重试）: $e', tag: 'SingBox');
        }
      } catch (e) {
        // 静默失败，不影响主流程
        KRLogUtil.kr_w('⚠️ 后台预连接任务失败（不影响正常使用）: $e', tag: 'SingBox');
      }
    });
  }

  /// 确保 command client 已初始化（通过触发订阅来初始化）
  ///
  /// 借鉴 Hiddify:watchGroups() 会在首次调用时自动 startCommandClient()
  Future<void> _kr_ensureCommandClientInitialized() async {
    // 如果已经有订阅,说明 command client 已初始化
    if (_kr_subscriptions.isNotEmpty) {
      KRLogUtil.kr_i('✅ Command client 已初始化（订阅数: ${_kr_subscriptions.length}）',
          tag: 'SingBox');
      return;
    }

    KRLogUtil.kr_i('⚠️ Command client 未初始化,触发订阅...', tag: 'SingBox');

    try {
      // 触发 watchGroups(),这会自动调用 startCommandClient()
      _kr_subscribeToGroups();

      // 等待一小段时间让订阅建立
      await Future.delayed(const Duration(milliseconds: 300));

      if (_kr_subscriptions.isEmpty) {
        throw Exception('订阅失败,command client 未初始化');
      }

      KRLogUtil.kr_i('✅ Command client 初始化成功', tag: 'SingBox');
    } catch (e) {
      KRLogUtil.kr_e('❌ Command client 初始化失败: $e', tag: 'SingBox');
      rethrow;
    }
  }

  /// 在后台恢复用户保存的节点选择（不阻塞启动流程）
  ///
  /// selectOutbound() 依赖 command client，必须延迟执行
  void _kr_restoreSavedNodeInBackground() {
    KRLogUtil.kr_i('🔄 启动节点恢复后台任务...', tag: 'SingBox');

    Future.microtask(() async {
      try {
        // 等待 command client 初始化
        await Future.delayed(const Duration(milliseconds: 2000));

        final savedNode =
            await KRSecureStorage().kr_readData(key: _keySelectedNode);
        if (savedNode != null && savedNode.isNotEmpty && savedNode != 'auto') {
          KRLogUtil.kr_i('🔄 恢复用户选择的节点: $savedNode', tag: 'SingBox');

          try {
            await _kr_selectOutboundWithRetry("select", savedNode);
            KRLogUtil.kr_i('✅ 节点恢复完成', tag: 'SingBox');
          } catch (e) {
            KRLogUtil.kr_w('⚠️ 节点恢复失败（可能 command client 未就绪）: $e',
                tag: 'SingBox');
          }
        } else {
          KRLogUtil.kr_i('ℹ️ 使用默认节点选择 (auto)', tag: 'SingBox');
        }
      } catch (e) {
        KRLogUtil.kr_w('⚠️ 节点恢复后台任务失败: $e', tag: 'SingBox');
      }
    });
  }

  /// 监听活动组的详细实现
  // Future<void> watchActiveGroups() async {
  //   try {
  //     print("开始监听活动组详情...");

  //     final status = await kr_singBox.status();
  //     print("服务状态: ${status.toJson()}");

  //     final outbounds = await kr_singBox.listOutbounds();
  //     print("出站列表: ${outbounds.toJson()}");

  //     for (var outbound in outbounds.outbounds) {
  //       print("出站配置: ${outbound.toJson()}");

  //       // 检查出站是否活动
  //       final isActive = await kr_singBox.isOutboundActive(outbound.tag);
  //       print("出站 ${outbound.tag} 活动状态: $isActive");
  //     }
  //   } catch (e, stack) {
  //     print("监听活动组详情时出错: $e");
  //     print("错误堆栈: $stack");
  //   }
  // }

  /// 保存配置文件
  void kr_saveOutbounds(List<Map<String, dynamic>> outbounds) async {
    KRLogUtil.kr_i('💾 开始保存配置文件...', tag: 'SingBox');
    KRLogUtil.kr_i('📊 出站节点数量: ${outbounds.length}', tag: 'SingBox');

    // 打印每个节点的详细配置
    // for (int i = 0; i < outbounds.length; i++) {
    //   final outbound = outbounds[i];
    //   KRLogUtil.kr_i('📋 节点[$i] 配置:', tag: 'SingBox');
    //   KRLogUtil.kr_i('  - type: ${outbound['type']}', tag: 'SingBox');
    //   KRLogUtil.kr_i('  - tag: ${outbound['tag']}', tag: 'SingBox');
    //   KRLogUtil.kr_i('  - server: ${outbound['server']}', tag: 'SingBox');
    //   KRLogUtil.kr_i('  - server_port: ${outbound['server_port']}',
    //       tag: 'SingBox');
    //   if (outbound['method'] != null) {
    //     KRLogUtil.kr_i('  - method: ${outbound['method']}', tag: 'SingBox');
    //   }
    //   if (outbound['interval'] != null) {
    //     KRLogUtil.kr_i('  - interval: ${outbound['interval']}', tag: 'SingBox');
    //   }
    //   if (outbound['password'] != null) {
    //     KRLogUtil.kr_i(
    //         '  - password: ${outbound['password']?.toString().substring(0, 8)}...',
    //         tag: 'SingBox');
    //   }
    //   if (outbound['uuid'] != null) {
    //     KRLogUtil.kr_i(
    //         '  - uuid: ${outbound['uuid']?.toString().substring(0, 8)}...',
    //         tag: 'SingBox');
    //   }
    //   KRLogUtil.kr_i('  - 完整配置: ${jsonEncode(outbound)}', tag: 'SingBox');
    // }

    // ⚠️ 临时过滤 Hysteria2 节点以避免 libcore 崩溃
    kr_outbounds = outbounds.where((outbound) {
      final type = outbound['type'];
      if (type == 'hysteria2' || type == 'hysteria') {
        KRLogUtil.kr_w('⚠️ 跳过 Hysteria2 节点: ${outbound['tag']} (libcore bug)',
            tag: 'SingBox');
        return false;
      }
      return true;
    }).toList();

    KRLogUtil.kr_i('✅ 过滤后节点数量: ${kr_outbounds.length}/${outbounds.length}',
        tag: 'SingBox');

    // 🔧 修复：生成完整的 SingBox 配置
    // 之前只保存 {"outbounds": [...]}, 导致 libcore 无法正确处理
    // 现在保存完整配置，包含所有必需字段
    final Map<String, dynamic> fullConfig = {
      "log": {"level": "debug", "timestamp": true},
      "dns": {
        "servers": [
          {
            "tag": "dns-remote",
            "address": "https://1.1.1.1/dns-query",
            "address_resolver": "dns-direct"
          },
          {"tag": "dns-direct", "address": "local", "detour": "direct"}
        ],
        "rules": _kr_buildDnsRules(), // ✅ 使用动态构建的 DNS 规则
        "final": "dns-remote",
        "strategy": "prefer_ipv4"
      },
      "inbounds": [
        {
          "type": "tun",
          "tag": "tun-in",
          "interface_name": "utun",
          "inet4_address": "172.19.0.1/30",
          "auto_route": true,
          "strict_route": true,
          "sniff": true,
          "sniff_override_destination": false
        }
      ],
      "outbounds": [
        // 🔧 修复：添加 selector 组，让用户可以手动选择节点
        {
          "type": "selector",
          "tag": "proxy",
          "outbounds": kr_outbounds.map((o) => o['tag'] as String).toList(),
          "default":
              kr_outbounds.isNotEmpty ? kr_outbounds[0]['tag'] : "direct",
        },
        ...kr_outbounds,
        {"type": "direct", "tag": "direct"},
        {"type": "block", "tag": "block"},
        {"type": "dns", "tag": "dns-out"}
      ],
      "route": {
        "rules": _kr_buildRouteRules(), // ✅ 使用动态构建的路由规则
        "rule_set": _kr_buildRuleSets(), // ✅ 使用动态构建的规则集
        "final": "proxy", // 🔧 修复：使用 selector 组作为默认出站
        "auto_detect_interface": true
      }
    };

    final file = _file(kr_configName);
    final temp = _tempFile(kr_configName);
    final mapStr = jsonEncode(fullConfig);

    KRLogUtil.kr_i('📄 完整配置文件长度: ${mapStr.length}', tag: 'SingBox');
    KRLogUtil.kr_i('📄 Outbounds 数量: ${kr_outbounds.length}', tag: 'SingBox');
    KRLogUtil.kr_i(
        '📄 配置前800字符:\n${mapStr.substring(0, mapStr.length > 800 ? 800 : mapStr.length)}',
        tag: 'SingBox');

    await file.writeAsString(mapStr);
    await temp.writeAsString(mapStr);

    _cutPath = file.path;
    KRLogUtil.kr_i('📁 配置文件路径: $_cutPath', tag: 'SingBox');

    await kr_singBox
        .validateConfigByPath(file.path, temp.path, false)
        .mapLeft((err) {
      KRLogUtil.kr_e('❌ 保存配置文件失败: $err', tag: 'SingBox');
    }).run();

    KRLogUtil.kr_i('✅ 配置文件保存完成', tag: 'SingBox');
  }

  /// 构建 DNS 规则
  List<Map<String, dynamic>> _kr_buildDnsRules() {
    final currentCountryCode = KRCountryUtil.kr_getCurrentCountryCode();
    final rules = <Map<String, dynamic>>[];

    // 🔧 关键修复：只有在"智能代理"模式下，才根据国家添加直连规则
    // 如果是"全局代理"模式，即使选择了国家也不添加直连规则
    if (kr_connectionType.value == KRConnectionType.rule &&
        currentCountryCode != 'other') {
      rules.add({
        "rule_set": [
          "geoip-$currentCountryCode",
          "geosite-$currentCountryCode",
        ],
        "server": "dns-direct"
      });

      KRLogUtil.kr_i('✅ [智能代理模式] 添加 DNS 规则: $currentCountryCode 域名使用直连 DNS',
          tag: 'SingBox');
    } else if (kr_connectionType.value == KRConnectionType.global) {
      KRLogUtil.kr_i('🌐 [全局代理模式] 跳过国家 DNS 规则，所有DNS查询走代理', tag: 'SingBox');
    }

    return rules;
  }

  /// 构建路由规则
  List<Map<String, dynamic>> _kr_buildRouteRules() {
    final currentCountryCode = KRCountryUtil.kr_getCurrentCountryCode();
    final rules = <Map<String, dynamic>>[];

    // 基础规则: DNS 查询走 dns-out
    rules.add({"protocol": "dns", "outbound": "dns-out"});

    // ✅ 自定义域名直连规则（优先级高，放在前面）
    // rules.add({
    //   "domain_suffix": ["ip138.com"],
    //   "outbound": "direct"
    // });

    // KRLogUtil.kr_i('✅ 添加自定义域名直连规则: ip138.com -> direct', tag: 'SingBox');

    // 🔧 关键修复：只有在"智能代理"模式下，才根据国家添加直连规则
    // 如果是"全局代理"模式，即使选择了国家也不添加直连规则
    if (kr_connectionType.value == KRConnectionType.rule &&
        currentCountryCode != 'other') {
      rules.add({
        "rule_set": [
          "geoip-$currentCountryCode",
          "geosite-$currentCountryCode",
        ],
        "outbound": "direct"
      });

      KRLogUtil.kr_i('✅ [智能代理模式] 添加路由规则: $currentCountryCode IP/域名直连',
          tag: 'SingBox');
    } else if (kr_connectionType.value == KRConnectionType.global) {
      KRLogUtil.kr_i('🌐 [全局代理模式] 跳过国家路由规则，所有流量走代理', tag: 'SingBox');
    }

    return rules;
  }

  /// 构建规则集配置
  List<Map<String, dynamic>> _kr_buildRuleSets() {
    final currentCountryCode = KRCountryUtil.kr_getCurrentCountryCode();
    final ruleSets = <Map<String, dynamic>>[];

    // 🔧 关键修复：只有在"智能代理"模式下，才加载国家规则集
    // 如果是"全局代理"模式，即使选择了国家也不加载规则集
    if (kr_connectionType.value == KRConnectionType.rule &&
        currentCountryCode != 'other') {
      // 检查本地文件是否存在
      final geoipFile = File(p.join(kr_configDics.workingDir.path, 'geosite',
          'geoip-$currentCountryCode.srs'));
      final geositeFile = File(p.join(kr_configDics.workingDir.path, 'geosite',
          'geosite-$currentCountryCode.srs'));

      if (geoipFile.existsSync() && geositeFile.existsSync()) {
        // ✅ 使用本地文件
        ruleSets.add({
          "type": "local",
          "tag": "geoip-$currentCountryCode",
          "format": "binary",
          "path": "./geosite/geoip-$currentCountryCode.srs" // 相对于 workingDir
        });

        ruleSets.add({
          "type": "local",
          "tag": "geosite-$currentCountryCode",
          "format": "binary",
          "path": "./geosite/geosite-$currentCountryCode.srs"
        });

        KRLogUtil.kr_i('✅ 使用本地规则集: $currentCountryCode', tag: 'SingBox');
        KRLogUtil.kr_i('   - geoip: ./geosite/geoip-$currentCountryCode.srs',
            tag: 'SingBox');
        KRLogUtil.kr_i(
            '   - geosite: ./geosite/geosite-$currentCountryCode.srs',
            tag: 'SingBox');
      } else {
        // ❌ 本地文件不存在,使用远程规则集作为后备
        KRLogUtil.kr_w('⚠️ 本地规则集不存在,使用远程规则集', tag: 'SingBox');
        KRLogUtil.kr_w('   - geoip 文件存在: ${geoipFile.existsSync()}',
            tag: 'SingBox');
        KRLogUtil.kr_w('   - geosite 文件存在: ${geositeFile.existsSync()}',
            tag: 'SingBox');

        ruleSets.add({
          "type": "remote",
          "tag": "geoip-$currentCountryCode",
          "format": "binary",
          "url":
              "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/country/geoip-$currentCountryCode.srs",
          "download_detour": "direct",
          "update_interval": "7d"
        });

        ruleSets.add({
          "type": "remote",
          "tag": "geosite-$currentCountryCode",
          "format": "binary",
          "url":
              "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/country/geosite-$currentCountryCode.srs",
          "download_detour": "direct",
          "update_interval": "7d"
        });
      }
    }

    return ruleSets;
  }

  Future<void> kr_start() async {
    // 不再手动设置状态，libcore 会通过 status stream 自动发送状态更新
    try {
      // 🔧 修复3: 添加登录状态检查 - 只有已登录用户才能连接VPN
      if (!KRAppRunData().kr_isLogin.value) {
        KRLogUtil.kr_e('❌ 未登录用户，禁止启动VPN连接', tag: 'SingBox');
        throw Exception('用户未登录，无法启动VPN服务');
      }

      // ⚠️ 强制编译标记 - v2.0-lazy-load
      KRLogUtil.kr_i('🚀🚀🚀 [v2.0-lazy-load] 开始启动 SingBox...', tag: 'SingBox');

      // 🔧 强制重新生成配置文件（确保最新的路由规则生效）
      if (kr_outbounds.isNotEmpty) {
        KRLogUtil.kr_i('🔄 启动前强制重新生成配置文件...', tag: 'SingBox');
        kr_saveOutbounds(kr_outbounds);
        // 等待配置文件写入完成
        await Future.delayed(const Duration(milliseconds: 100));
      }

      KRLogUtil.kr_i('📁 配置文件路径: $_cutPath', tag: 'SingBox');
      KRLogUtil.kr_i('📝 配置名称: $kr_configName', tag: 'SingBox');

      // 🔑 Windows 平台：仅在首次启动时备份 DNS 设置（优化：避免重复备份）
      if (Platform.isWindows && !_dnsBackedUp) {
        KRLogUtil.kr_i('🪟 Windows 平台，首次启动备份 DNS 设置...', tag: 'SingBox');
        try {
          final backupSuccess =
              await KRWindowsDnsUtil.instance.kr_backupDnsSettings();
          if (backupSuccess) {
            _dnsBackedUp = true; // 标记已备份
            KRLogUtil.kr_i('✅ Windows DNS 备份成功', tag: 'SingBox');
          } else {
            KRLogUtil.kr_w('⚠️ Windows DNS 备份失败，将在停止时使用兜底恢复', tag: 'SingBox');
          }
        } catch (e) {
          KRLogUtil.kr_w('⚠️ Windows DNS 备份异常: $e，将在停止时使用兜底恢复', tag: 'SingBox');
        }
      } else if (Platform.isWindows && _dnsBackedUp) {
        KRLogUtil.kr_i('⏭️ Windows 平台，DNS 已备份，跳过重复备份（节点切换优化）', tag: 'SingBox');
      }

      // 🔑 先尝试停止旧实例，避免 command.sock 冲突
      // 注意：如果没有旧实例，libcore 会报错 "command.sock: no such file"，这是正常的
      try {
        await kr_singBox.stop().run();
        await Future.delayed(const Duration(milliseconds: 500));
        KRLogUtil.kr_i('✅ 已清理旧实例', tag: 'SingBox');
      } catch (e) {
        // 预期行为：没有旧实例时会报错，可以忽略
        KRLogUtil.kr_i('ℹ️ 没有运行中的旧实例（正常）', tag: 'SingBox');
      }

      // 🔑 关键步骤：在 start 之前必须调用 changeOptions 初始化 HiddifyOptions
      // 否则 libcore 的 StartService 会因为 HiddifyOptions == nil 而 panic
      KRLogUtil.kr_i('📡 初始化 HiddifyOptions...', tag: 'SingBox');
      final oOption = SingboxConfigOption.fromJson(_getConfigOption());
      final changeResult = await kr_singBox.changeOptions(oOption).run();
      changeResult.match(
        (error) {
          KRLogUtil.kr_e('❌ changeOptions() 失败: $error', tag: 'SingBox');
          throw Exception('初始化 HiddifyOptions 失败: $error');
        },
        (_) {
          KRLogUtil.kr_i('✅ HiddifyOptions 初始化成功', tag: 'SingBox');
        },
      );

      // 检查配置文件是否存在
      final configFile = File(_cutPath);
      if (await configFile.exists()) {
        final configContent = await configFile.readAsString();
        KRLogUtil.kr_i('📄 配置文件内容长度: ${configContent.length}', tag: 'SingBox');
        // KRLogUtil.kr_i(
        //     '📄 配置文件前500字符: ${configContent.substring(0, configContent.length > 500 ? 500 : configContent.length)}',
        //     tag: 'SingBox');
      } else {
        KRLogUtil.kr_w('⚠️ 配置文件不存在: $_cutPath', tag: 'SingBox');
      }

      // 🔧 修复: 在启动前重新订阅状态流，确保能收到状态更新
      _kr_subscribeToStatus();

      await kr_singBox.start(_cutPath, kr_configName, false).map(
        (r) {
          KRLogUtil.kr_i('✅ SingBox 启动成功', tag: 'SingBox');
        },
      ).mapLeft((err) {
        KRLogUtil.kr_e('❌ SingBox 启动失败: $err', tag: 'SingBox');
        // 不需要手动设置状态，libcore 会通过 status stream 自动发送 Stopped 事件
        throw err;
      }).run();

      // 🔑 macOS 平台：启用 SOCKS5 系统代理
      if (Platform.isMacOS) {
        KRLogUtil.kr_i('🍎 macOS 平台，开启系统 SOCKS5 代理...', tag: 'SingBox');
        try {
          await KRMacosProxyUtil.enableSocks5(
            host: '127.0.0.1',
            port: kr_port,
          );
        } catch (e) {
          KRLogUtil.kr_w('⚠️ macOS 系统代理开启失败: $e', tag: 'SingBox');
        }
      }

      // ⚠️ 关键修复：在启动成功后立即订阅统计流
      // 原因：
      // 1. 统计流需要主动订阅才能接收数据
      // 2. UI 只是读取 kr_stats.value，不会触发订阅
      // 3. command.sock 在 start() 成功后会立即创建

      KRLogUtil.kr_i('✅ SingBox 核心已启动，开始初始化 command client', tag: 'SingBox');

      // 🔑 在后台延迟订阅统计流和分组流，避免阻塞 UI
      Future.delayed(const Duration(milliseconds: 1000), () async {
        try {
          KRLogUtil.kr_i('📊 开始订阅统计数据流...', tag: 'SingBox');
          _kr_subscribeToStats();
          KRLogUtil.kr_i('✅ 统计数据流订阅成功', tag: 'SingBox');
        } catch (e) {
          KRLogUtil.kr_w('⚠️ 统计数据流订阅失败（稍后重试）: $e', tag: 'SingBox');
          // 如果第一次失败，再等待一段时间重试
          Future.delayed(const Duration(milliseconds: 2000), () {
            try {
              _kr_subscribeToStats();
              KRLogUtil.kr_i('✅ 统计数据流重试订阅成功', tag: 'SingBox');
            } catch (e2) {
              KRLogUtil.kr_e('❌ 统计数据流重试订阅失败: $e2', tag: 'SingBox');
            }
          });
        }

        // 🔧 关键修复：订阅分组数据流
        try {
          KRLogUtil.kr_i('📋 开始订阅分组数据流...', tag: 'SingBox');
          _kr_subscribeToGroups();
          KRLogUtil.kr_i('✅ 分组数据流订阅成功', tag: 'SingBox');
        } catch (e) {
          KRLogUtil.kr_w('⚠️ 分组数据流订阅失败（稍后重试）: $e', tag: 'SingBox');
          // 如果第一次失败，再等待一段时间重试
          Future.delayed(const Duration(milliseconds: 2000), () {
            try {
              _kr_subscribeToGroups();
              KRLogUtil.kr_i('✅ 分组数据流重试订阅成功', tag: 'SingBox');
            } catch (e2) {
              KRLogUtil.kr_e('❌ 分组数据流重试订阅失败: $e2', tag: 'SingBox');
            }
          });
        }

        // 🔧 关键修复：恢复用户选择的节点
        try {
          final selectedNode =
              await KRSecureStorage().kr_readData(key: _keySelectedNode);
          if (selectedNode != null && selectedNode.isNotEmpty) {
            KRLogUtil.kr_i('🎯 恢复用户选择的节点: $selectedNode', tag: 'SingBox');
            if (kDebugMode) {
              print('🔵 启动后恢复节点选择: $selectedNode');
            }

            // 延迟500ms确保sing-box完全启动
            await Future.delayed(const Duration(milliseconds: 500));

            // 🔧 关键修复：使用 await 等待节点切换完成
            try {
              await kr_selectOutbound(selectedNode);
              KRLogUtil.kr_i('✅ 节点已切换到用户选择: $selectedNode', tag: 'SingBox');
              if (kDebugMode) {
                print('🔵 节点切换成功: $selectedNode');
              }
            } catch (e) {
              KRLogUtil.kr_e('❌ 节点切换失败: $e', tag: 'SingBox');
              if (kDebugMode) {
                print('🔵 节点切换失败: $e');
              }
            }
          } else {
            KRLogUtil.kr_i('ℹ️ 没有保存的节点选择，使用默认配置', tag: 'SingBox');
            if (kDebugMode) {
              print('🔵 没有保存的节点选择，使用默认');
            }
          }
        } catch (e) {
          KRLogUtil.kr_e('❌ 恢复节点选择失败: $e', tag: 'SingBox');
          if (kDebugMode) {
            print('🔵 恢复节点选择失败: $e');
          }
        }
      });
    } catch (e, stackTrace) {
      KRLogUtil.kr_e('💥 SingBox 启动异常: $e', tag: 'SingBox');
      KRLogUtil.kr_e('📚 错误堆栈: $stackTrace', tag: 'SingBox');
      // 不需要手动设置状态，libcore 会自动处理
      rethrow;
    }
  }

  /// 停止服务
  Future<void> kr_stop() async {
    try {
      KRLogUtil.kr_i('🛑 停止 SingBox 服务...', tag: 'SingBox');

      // 取消节点选择监控定时器
      kr_resetNodeSelectionMonitor();

      await Future.delayed(const Duration(milliseconds: 100));

      // 添加超时保护,防止 stop() 调用阻塞
      // 🔧 延长超时时间到 10 秒，给 Windows DNS 清理足够时间
      try {
        await kr_singBox.stop().run().timeout(
          const Duration(seconds: 10), // ← 从 3 秒延长到 10 秒
          onTimeout: () {
            KRLogUtil.kr_w('⚠️ 停止操作超时(10秒)，强制继续', tag: 'SingBox');
            return const Left('timeout');
          },
        );
      } catch (e) {
        KRLogUtil.kr_w('⚠️ 停止操作失败（可能已经停止）: $e', tag: 'SingBox');
        // 继续执行清理操作
      }

      // 🔑 Windows 平台：仅在有备份时恢复 DNS 设置
      if (Platform.isWindows && _dnsBackedUp) {
        KRLogUtil.kr_i('🪟 Windows 平台，等待 sing-box 完全停止...', tag: 'SingBox');

        // 🔧 P3优化: 监听状态而非固定延迟，确保 sing-box 真正停止后再恢复 DNS
        try {
          // 如果当前已经是停止状态，直接继续
          if (kr_status.value is SingboxStopped) {
            KRLogUtil.kr_i('✅ sing-box 已经是停止状态，立即恢复 DNS', tag: 'SingBox');
          } else {
            // 等待状态变为停止，最多等待3秒
            final completer = Completer<void>();
            late final Worker worker;

            worker = ever(kr_status, (status) {
              if (status is SingboxStopped) {
                if (!completer.isCompleted) {
                  completer.complete();
                  worker.dispose();
                }
              }
            });

            await completer.future.timeout(
              const Duration(seconds: 3),
              onTimeout: () {
                KRLogUtil.kr_w('⏱️ 等待停止状态超时，继续执行 DNS 恢复', tag: 'SingBox');
                worker.dispose();
              },
            );

            KRLogUtil.kr_i('✅ sing-box 已完全停止，开始恢复 DNS...', tag: 'SingBox');
          }
        } catch (e) {
          KRLogUtil.kr_w('⚠️ 状态监听异常: $e，继续执行 DNS 恢复', tag: 'SingBox');
        }

        try {
          // 尝试恢复 DNS
          final restoreSuccess =
              await KRWindowsDnsUtil.instance.kr_restoreDnsSettings();
          if (restoreSuccess) {
            KRLogUtil.kr_i('✅ Windows DNS 恢复成功', tag: 'SingBox');
          } else {
            KRLogUtil.kr_e('❌ Windows DNS 恢复失败', tag: 'SingBox');
          }
        } catch (e) {
          KRLogUtil.kr_e('❌ Windows DNS 恢复异常: $e', tag: 'SingBox');
          // 异常时也会在工具类内部执行兜底恢复
        } finally {
          // 🔧 P0修复2: 使用 finally 确保标志位始终被重置，避免下次启动跳过备份
          _dnsBackedUp = false;
          KRLogUtil.kr_i('🔄 重置 DNS 备份标志位', tag: 'SingBox');
        }
      } else if (Platform.isWindows && !_dnsBackedUp) {
        KRLogUtil.kr_i('⏭️ Windows 平台，DNS 未备份，跳过恢复', tag: 'SingBox');
        await Future.delayed(const Duration(milliseconds: 500));
      } else {
        // 非 Windows 平台正常等待
        await Future.delayed(const Duration(milliseconds: 500));
      }

      // 取消统计和分组订阅，但保留状态订阅以便继续接收状态更新
      final subscriptionsToCancel = _kr_subscriptions.where((sub) {
        final hashStr = sub.hashCode.toString();
        return !hashStr.contains('Status'); // 不取消状态订阅
      }).toList();

      for (var subscription in subscriptionsToCancel) {
        try {
          await subscription.cancel();
          _kr_subscriptions.remove(subscription);
        } catch (e) {
          KRLogUtil.kr_e('取消订阅时出错: $e');
        }
      }

      // 不手动设置状态，由 libcore 通过 status stream 自动发送 Stopped 事件
      KRLogUtil.kr_i('✅ SingBox 停止请求已发送', tag: 'SingBox');

      // 🍎 macOS 平台：关闭系统 SOCKS5 代理
      if (Platform.isMacOS) {
        KRLogUtil.kr_i('🍎 macOS 平台，关闭系统 SOCKS5 代理...', tag: 'SingBox');
        try {
          await KRMacosProxyUtil.disableSocks5();
        } catch (e) {
          KRLogUtil.kr_e('❌ macOS 系统代理关闭失败: $e', tag: 'SingBox');
        }
      }
    } catch (e, stackTrace) {
      KRLogUtil.kr_e('停止服务时出错: $e');
      KRLogUtil.kr_e('错误堆栈: $stackTrace');

      // 🔑 即使出错，也要尝试恢复 Windows DNS
      if (Platform.isWindows && _dnsBackedUp) {
        KRLogUtil.kr_w('⚠️ 停止异常，强制执行 DNS 恢复', tag: 'SingBox');
        try {
          await KRWindowsDnsUtil.instance.kr_restoreDnsSettings();
        } catch (dnsError) {
          KRLogUtil.kr_e('❌ 强制 DNS 恢复失败: $dnsError', tag: 'SingBox');
        } finally {
          // 🔧 P0修复2: 异常路径也要重置标志位
          _dnsBackedUp = false;
          KRLogUtil.kr_i('🔄 异常后重置 DNS 备份标志位', tag: 'SingBox');
        }
      }

      // 不手动设置状态，信任 libcore 的状态管理
      rethrow;
    }
  }

  ///
  void kr_updateAdBlockEnabled(bool bl) async {
    final oOption = _getConfigOption();

    oOption["block-ads"] = bl;
    final op = SingboxConfigOption.fromJson(oOption);

    await kr_singBox.changeOptions(op)
      ..map((r) {}).mapLeft((err) {
        KRLogUtil.kr_e('更新广告拦截失败: $err');
      }).run();
    if (kr_status.value == SingboxStarted()) {
      await kr_restart();
    }
    kr_blockAds.value = bl;
  }

  Future<void> kr_restart() async {
    KRLogUtil.kr_i('🔄 重启 SingBox...', tag: 'SingBox');

    // 🔧 修复：使用 stop + start 而不是 restart
    // 这样可以触发 Windows DNS 恢复和备份逻辑
    try {
      // 1. 先停止（会触发 DNS 恢复）
      await kr_stop();

      // 2. 等待完全停止
      await Future.delayed(const Duration(milliseconds: 500));

      // 3. 重新启动（会触发 DNS 备份）
      await kr_start();

      KRLogUtil.kr_i('✅ SingBox 重启完成', tag: 'SingBox');
    } catch (e) {
      KRLogUtil.kr_e('❌ 重启失败: $e', tag: 'SingBox');
      rethrow;
    }
  }

  //// 设置出站模式
  Future<void> kr_updateConnectionType(KRConnectionType newType) async {
    try {
      KRLogUtil.kr_i('🔄 开始更新连接类型...', tag: 'SingBox');
      KRLogUtil.kr_i('📊 当前类型: ${kr_connectionType.value}', tag: 'SingBox');
      KRLogUtil.kr_i('📊 新类型: $newType', tag: 'SingBox');

      if (kr_connectionType.value == newType) {
        KRLogUtil.kr_i('⚠️ 连接类型相同，无需更新', tag: 'SingBox');
        return;
      }

      kr_connectionType.value = newType;

      final oOption = _getConfigOption();

      var mode = "";
      switch (newType) {
        case KRConnectionType.global:
          mode = "other";
          KRLogUtil.kr_i('🌍 切换到全局代理模式', tag: 'SingBox');
          break;
        case KRConnectionType.rule:
          mode = KRCountryUtil.kr_getCurrentCountryCode();
          KRLogUtil.kr_i('🎯 切换到规则代理模式: $mode', tag: 'SingBox');
          break;
        // case KRConnectionType.direct:
        //   mode = "direct";
        // break;
      }
      oOption["region"] = mode;
      KRLogUtil.kr_i('📝 更新 region 配置: $mode', tag: 'SingBox');

      final op = SingboxConfigOption.fromJson(oOption);
      KRLogUtil.kr_i('📄 配置选项: ${oOption.toString()}', tag: 'SingBox');

      await kr_singBox.changeOptions(op)
        ..map((r) {
          KRLogUtil.kr_i('✅ 连接类型更新成功', tag: 'SingBox');
        }).mapLeft((err) {
          KRLogUtil.kr_e('❌ 更新连接类型失败: $err', tag: 'SingBox');
          throw err;
        }).run();

      if (kr_status.value == SingboxStarted()) {
        KRLogUtil.kr_i('🔄 VPN已启动，准备重启以应用新配置...', tag: 'SingBox');
        await kr_restart();
        KRLogUtil.kr_i('✅ VPN重启完成', tag: 'SingBox');
      } else {
        KRLogUtil.kr_i('ℹ️ VPN未启动，配置已更新', tag: 'SingBox');
      }
    } catch (e, stackTrace) {
      KRLogUtil.kr_e('💥 更新连接类型异常: $e', tag: 'SingBox');
      KRLogUtil.kr_e('📚 错误堆栈: $stackTrace', tag: 'SingBox');
      rethrow;
    }
  }

  /// 更新国家设置
  Future<void> kr_updateCountry(KRCountry kr_country) async {
    // 如果国家相同，直接返回
    if (kr_country.kr_code == KRCountryUtil.kr_getCurrentCountryCode()) {
      return;
    }

    try {
      // 更新工具类中的当前国家
      await KRCountryUtil.kr_setCurrentCountry(kr_country);
      // 更新配置选项
      final oOption = _getConfigOption();
      oOption["region"] = kr_country.kr_code;
      final op = SingboxConfigOption.fromJson(oOption);

      await kr_singBox.changeOptions(op)
        ..map((r) {}).mapLeft((err) {
          KRLogUtil.kr_e('更新国家设置失败: $err');
        }).run();

      // 如果服务正在运行，重启服务
      if (kr_status.value == SingboxStarted()) {
        await kr_restart();
      }
    } catch (err) {
      KRLogUtil.kr_e('更新国家失败: $err');
      rethrow;
    }
  }

  Stream<SingboxStatus> kr_watchStatus() {
    return kr_singBox.watchStatus();
  }

  Stream<List<SingboxOutboundGroup>> kr_watchGroups() {
    return kr_singBox.watchGroups();
  }

  // 节点选择监控定时器
  Timer? _nodeSelectionTimer;

  Future<void> kr_selectOutbound(String tag) async {
    KRLogUtil.kr_i('🎯 [v2.1] 开始选择出站节点: $tag', tag: 'SingBox');
    KRLogUtil.kr_i('📊 当前活动组数量: ${kr_activeGroups.length}', tag: 'SingBox');

    // 如果活动组尚未就绪，等待一段时间；仍为空则仅保存选择，稍后恢复
    if (kr_activeGroups.isEmpty) {
      for (int i = 0; i < 20; i++) {
        await Future.delayed(const Duration(milliseconds: 100));
        if (kr_activeGroups.isNotEmpty) break;
      }
      if (kr_activeGroups.isEmpty) {
        KRLogUtil.kr_w('⚠️ 活动组为空，跳过即时切换，仅保存选择: $tag', tag: 'SingBox');
        try {
          await KRSecureStorage()
              .kr_saveData(key: _keySelectedNode, value: tag);
          KRLogUtil.kr_i('✅ 节点选择已保存: $tag', tag: 'SingBox');
        } catch (e) {
          KRLogUtil.kr_e('❌ 保存节点选择失败: $e', tag: 'SingBox');
        }
        return;
      }
    }

    // 🔧 诊断：打印所有活动组的节点，确保目标节点存在
    KRLogUtil.kr_i('🔍 搜索目标节点 "$tag" 在活动组中...', tag: 'SingBox');
    bool foundNode = false;
    for (var group in kr_activeGroups) {
      for (var item in group.items) {
        if (item.tag == tag) {
          foundNode = true;
          KRLogUtil.kr_i('✅ 在组 "${group.tag}" 中找到目标节点: $tag', tag: 'SingBox');
          break;
        }
      }
      if (foundNode) break;
    }
    if (!foundNode) {
      KRLogUtil.kr_w('⚠️ 未能在任何活动组中找到目标节点: $tag', tag: 'SingBox');
      // 打印所有可用的节点
      for (var group in kr_activeGroups) {
        for (var item in group.items) {
          KRLogUtil.kr_d('  可用节点: ${item.tag}', tag: 'SingBox');
        }
      }
    }

    // 🔧 关键修复：使用 await 确保保存完成
    try {
      await KRSecureStorage().kr_saveData(key: _keySelectedNode, value: tag);
      KRLogUtil.kr_i('✅ 节点选择已保存: $tag', tag: 'SingBox');
    } catch (e) {
      KRLogUtil.kr_e('❌ 保存节点选择失败: $e', tag: 'SingBox');
    }

    // 🔧 关键修复：使用 await 确保 command client 初始化完成
    try {
      await _kr_ensureCommandClientInitialized();
      KRLogUtil.kr_i('✅ Command client 已就绪，执行节点切换', tag: 'SingBox');

      // 🔧 关键修复：使用正确的 group tag
      // libcore 生成的selector组的tag是"proxy"而不是"select"
      final selectorGroupTag =
          kr_activeGroups.any((g) => g.tag == 'select') ? 'select' : 'proxy';
      KRLogUtil.kr_i('⏳ 调用 selectOutbound("$selectorGroupTag", "$tag")...',
          tag: 'SingBox');
      await _kr_selectOutboundWithRetry(selectorGroupTag, tag,
          maxAttempts: 3, initialDelay: 50);
      KRLogUtil.kr_i('✅ 节点切换API调用完成: $tag', tag: 'SingBox');

      // 🔧 新增：验证节点切换是否生效
      await Future.delayed(const Duration(milliseconds: 300)); // 等待活动组更新
      await _kr_verifyNodeSelection(tag);

      KRLogUtil.kr_i('✅ 节点切换验证完成: $tag', tag: 'SingBox');
    } catch (e) {
      KRLogUtil.kr_e('❌ 节点选择失败: $e', tag: 'SingBox');
      rethrow; // 抛出异常，让调用者知道失败了
    }

    // 🔄 如果用户选择了具体节点（不是 auto），启动定期检查和重新选择
    // 这是为了防止 urltest 自动覆盖用户的手动选择
    kr_startNodeSelectionMonitor(tag);
  }

  /// 配合文件地址

  Directory get directory =>
      Directory(p.join(kr_configDics.workingDir.path, "configs"));
  File _file(String fileName) {
    return File(p.join(directory.path, "$fileName.json"));
  }

  File _tempFile(String fileName) => _file("$fileName.tmp");

  /// 启动节点选择监控定时器，防止用户手动选择被自动策略覆盖
  void kr_startNodeSelectionMonitor(String tag) {
    kr_resetNodeSelectionMonitor();
    if (tag != 'auto') {
      KRLogUtil.kr_i('🔁 启动节点选择监控，防止被 auto 覆盖', tag: 'SingBox');
      _nodeSelectionTimer =
          Timer.periodic(const Duration(seconds: 20), (timer) {
        // 每 20 秒重新选择一次，确保用户选择不被覆盖
        // 使用 then/catchError 避免异常导致 UI 阻塞
        kr_singBox.selectOutbound("select", tag).run().then((result) {
          result.match(
            (error) => KRLogUtil.kr_w('🔁 定时器重选节点失败: $error', tag: 'SingBox'),
            (_) => KRLogUtil.kr_d('🔁 定时器重选节点成功', tag: 'SingBox'),
          );
        }).catchError((error) {
          KRLogUtil.kr_w('🔁 定时器重选节点异常: $error', tag: 'SingBox');
        });
        KRLogUtil.kr_d('🔁 重新确认节点选择: $tag', tag: 'SingBox');
      });
    }
  }

  /// 重置并停止节点选择监控定时器
  void kr_resetNodeSelectionMonitor() {
    _nodeSelectionTimer?.cancel();
    _nodeSelectionTimer = null;
    KRLogUtil.kr_i('✅ 节点选择监控已停止', tag: 'SingBox');
  }

  // File tempFile(String fileName) => file("$fileName.tmp");

  Future<void> kr_urlTest(String groupTag) async {
    KRLogUtil.kr_i('🧪 开始 URL 测试: $groupTag', tag: 'SingBox');
    KRLogUtil.kr_i('📊 当前活动组数量: ${kr_activeGroups.length}', tag: 'SingBox');

    // 打印所有活动组信息
    for (int i = 0; i < kr_activeGroups.length; i++) {
      final group = kr_activeGroups[i];
      KRLogUtil.kr_i(
          '📋 活动组[$i]: tag=${group.tag}, type=${group.type}, selected=${group.selected}',
          tag: 'SingBox');
      for (int j = 0; j < group.items.length; j++) {
        final item = group.items[j];
        KRLogUtil.kr_i(
            '  └─ 节点[$j]: tag=${item.tag}, type=${item.type}, delay=${item.urlTestDelay}',
            tag: 'SingBox');
      }
    }

    try {
      KRLogUtil.kr_i('🚀 调用 SingBox URL 测试 API...', tag: 'SingBox');
      final result = await kr_singBox.urlTest(groupTag).run();
      KRLogUtil.kr_i('✅ URL 测试完成: $groupTag, 结果: $result', tag: 'SingBox');

      // 等待一段时间让 SingBox 完成测试
      await Future.delayed(const Duration(seconds: 2));

      // 再次检查活动组状态
      KRLogUtil.kr_i('🔄 测试后活动组状态检查:', tag: 'SingBox');
      for (int i = 0; i < kr_activeGroups.length; i++) {
        final group = kr_activeGroups[i];
        KRLogUtil.kr_i(
            '📋 活动组[$i]: tag=${group.tag}, type=${group.type}, selected=${group.selected}',
            tag: 'SingBox');
        for (int j = 0; j < group.items.length; j++) {
          final item = group.items[j];
          KRLogUtil.kr_i(
              '  └─ 节点[$j]: tag=${item.tag}, type=${item.type}, delay=${item.urlTestDelay}',
              tag: 'SingBox');
        }
      }
    } catch (e) {
      KRLogUtil.kr_e('❌ URL 测试失败: $groupTag, 错误: $e', tag: 'SingBox');
      KRLogUtil.kr_e('📚 错误详情: ${e.toString()}', tag: 'SingBox');
    }
  }
}
