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

import 'package:flutter/services.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';

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 = "BearVPN";

  /// 通道方法
  final _kr_methodChannel = const MethodChannel("com.baer.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 = true.obs;

  /// 是否自动自动选择线路
  final kr_isAutoOutbound = true.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;

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

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

  /// 初始化
  Future<void> init() async {
    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();
        kr_configDics = (
          baseDir: baseDir,
          workingDir: workingDir!,
          tempDir: tempDir,
        );
        KRLogUtil.kr_i('其他平台路径初始化完成');
      }

      KRLogUtil.kr_i('开始创建目录');
      if (!kr_configDics.baseDir.existsSync()) {
        await kr_configDics.baseDir.create(recursive: true);
      }
      if (!kr_configDics.workingDir.existsSync()) {
        await kr_configDics.workingDir.create(recursive: true);
      }
      if (!kr_configDics.tempDir.existsSync()) {
        await kr_configDics.tempDir.create(recursive: true);
      }
      if (!directory.existsSync()) {
        await directory.create(recursive: true);
      }
      KRLogUtil.kr_i('目录创建完成');

      KRLogUtil.kr_i('开始设置 SingBox');
      await kr_singBox.setup(kr_configDics, false).map((r) {
        KRLogUtil.kr_i('SingBox 设置成功');
      }).mapLeft((err) {
        KRLogUtil.kr_e('SingBox 设置失败: $err');
        throw err;
      }).run();

      KRLogUtil.kr_i('开始更新 SingBox 选项');
      KRLogUtil.kr_i('📋 SingBox 配置选项: ${oOption.toJson()}', tag: 'SingBox');
      await kr_singBox.changeOptions(oOption)
        ..map((r) {
          KRLogUtil.kr_i('✅ SingBox 选项更新成功', tag: 'SingBox');
        }).mapLeft((err) {
          KRLogUtil.kr_e('❌ SingBox 选项更新失败: $err', tag: 'SingBox');
          throw err;
        }).run();

      KRLogUtil.kr_i('开始监听状态');
      // 初始订阅状态流
      kr_singBox.watchStatus().listen((status) {
        KRLogUtil.kr_i('🔄 SingBox 状态变化: $status', tag: 'SingBox');
        KRLogUtil.kr_i('📊 状态类型: ${status.runtimeType}', tag: 'SingBox');
        
        // 确保状态更新
        kr_status.value = status;
        
        switch (status) {
          case SingboxStopped():
            KRLogUtil.kr_i('🔴 SingBox 已停止', tag: 'SingBox');
            break;
          case SingboxStarting():
            KRLogUtil.kr_i('🟡 SingBox 正在启动', tag: 'SingBox');
            break;
          case SingboxStarted():
            KRLogUtil.kr_i('🟢 SingBox 已启动', tag: 'SingBox');
            kr_isFristStart.value = true;
            // 使用 GetX 的方式处理 Stream 订阅
            _kr_subscribeToStats();
            _kr_subscribeToGroups();
            // 强制触发状态更新
            kr_status.refresh();
            break;
          case SingboxStopping():
            KRLogUtil.kr_i('🟠 SingBox 正在停止', tag: 'SingBox');
            break;
        }
      });

      KRLogUtil.kr_i('SingBox 初始化完成');
    } catch (e, stackTrace) {
      KRLogUtil.kr_e('SingBox 初始化失败: $e');
      KRLogUtil.kr_e('错误堆栈: $stackTrace');
      rethrow;
    }
  }

  Map<String, dynamic> _getConfigOption() {
    if (kr_configOption.isNotEmpty) {
      return kr_configOption;
    }
    final op = {
      "region": KRCountryUtil.kr_getCurrentCountryCode(),
      "block-ads": kr_blockAds.value,
      "use-xray-core-when-possible": false,
      "execute-config-as-is": false,
      "log-level": "warn",
      "resolve-destination": false,
      "ipv6-mode": "ipv4_only",
      // "remote-dns-address": "https://cloudflare-dns.com/dns-query",
      "remote-dns-address": "udp://1.1.1.1",
      "remote-dns-domain-strategy": "",
      "direct-dns-address": "223.5.5.5",
      "direct-dns-domain-strategy": "",
      "mixed-port": kr_port,
      "tproxy-port": kr_port,
      "local-dns-port": 36450,
      "tun-implementation": "gvisor",
      "mtu": 9000,
      "strict-route": true,
      // "connection-test-url": "http://www.cloudflare.com",
       "connection-test-url": "http://www.gstatic.com/generate_204",
      "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": [],
      "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;
    return op;
  }

  /// 订阅统计数据流
  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'));

    _kr_subscriptions.add(
      kr_singBox.watchStats().listen(
        (stats) {
          kr_stats.value = stats;
        },
        onError: (error) {
          KRLogUtil.kr_e('统计数据监听错误: $error');
        },
        cancelOnError: false,
      ),
    );
  }

  /// 订阅分组数据流
  void _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) {
          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) {
          KRLogUtil.kr_e('❌ 活动分组监听错误: $error', tag: 'SingBox');
        },
        cancelOnError: false,
      ),
    );

    _kr_subscriptions.add(
      kr_singBox.watchGroups().listen(
        (groups) {
          kr_allGroups.value = groups;
        },
        onError: (error) {
          KRLogUtil.kr_e('所有分组监听错误: $error');
        },
        cancelOnError: false,
      ),
    );
  }

  /// 监听活动组的详细实现
  // 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');
    
    kr_outbounds = outbounds;

    final map = {};
    map["outbounds"] = kr_outbounds;

    final file = _file(kr_configName);
    final temp = _tempFile(kr_configName);
    final mapStr = jsonEncode(map);
    
    KRLogUtil.kr_i('📄 配置文件内容长度: ${mapStr.length}', tag: 'SingBox');
    KRLogUtil.kr_i('📄 配置文件前500字符: ${mapStr.substring(0, mapStr.length > 500 ? 500 : 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');
  }

  Future<void> kr_start() async {
    kr_status.value = SingboxStarting();
    try {
      KRLogUtil.kr_i('🚀 开始启动 SingBox...', tag: 'SingBox');
      KRLogUtil.kr_i('📁 配置文件路径: $_cutPath', tag: 'SingBox');
      KRLogUtil.kr_i('📝 配置名称: $kr_configName', 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');
      }

      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');
        // 确保状态重置为Stopped，触发UI更新
        kr_status.value = SingboxStopped();
        // 强制刷新状态以触发观察者
        kr_status.refresh();
        throw err;
      }).run();
    } catch (e, stackTrace) {
      KRLogUtil.kr_e('💥 SingBox 启动异常: $e', tag: 'SingBox');
      KRLogUtil.kr_e('📚 错误堆栈: $stackTrace', tag: 'SingBox');
      // 确保状态重置为Stopped，触发UI更新
      kr_status.value = SingboxStopped();
      // 强制刷新状态以触发观察者
      kr_status.refresh();
      rethrow;
    }
  }

  /// 停止服务
  Future<void> kr_stop() async {
    try {
      // 不主动赋值 kr_status
      await Future.delayed(const Duration(milliseconds: 100));
      await kr_singBox.stop().run();
      await Future.delayed(const Duration(milliseconds: 1000));
      // 取消订阅
      final subscriptions = List<StreamSubscription<dynamic>>.from(_kr_subscriptions);
      _kr_subscriptions.clear();
      for (var subscription in subscriptions) {
        try {
          await subscription.cancel();
        } catch (e) {
          KRLogUtil.kr_e('取消订阅时出错: $e');
        }
      }
      // 不主动赋值 kr_status
    } catch (e, stackTrace) {
      KRLogUtil.kr_e('停止服务时出错: $e');
      KRLogUtil.kr_e('错误堆栈: $stackTrace');
      // 兜底，防止状态卡死
      kr_status.value = SingboxStopped();
      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("restart");
    kr_singBox.restart(_cutPath, kr_configName, false).mapLeft((err) {
      KRLogUtil.kr_e('重启失败: $err');
    }).run();
  }

  //// 设置出站模式
  Future<void> kr_updateConnectionType(KRConnectionType newType) async {
    if (kr_connectionType.value == newType) {
      return;
    }

    kr_connectionType.value = newType;

    final oOption = _getConfigOption();

    var mode = "";
    switch (newType) {
      case KRConnectionType.global:
         mode = "other";
        break;
      case KRConnectionType.rule:
        mode = KRCountryUtil.kr_getCurrentCountryCode();
        break;
      // case KRConnectionType.direct:
      //   mode = "direct";
      // break;
    }
    oOption["region"] = mode;
    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();
    }
  }

  /// 更新国家设置
  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();
  }

  void kr_selectOutbound(String tag) {
    KRLogUtil.kr_i('🎯 开始选择出站节点: $tag', 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');
      }
    }
    kr_singBox.selectOutbound("select", tag).run();
  }

  /// 配合文件地址

  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");

  // 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');
    }
  }
}
