import 'dart:io';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
import 'package:kaer_with_panels/app/utils/kr_windows_process_util.dart';

/// Windows DNS 管理工具类
///
/// 用于在 Windows 平台上管理系统 DNS 设置
/// 主要功能：
/// 1. 备份原始 DNS 设置
/// 2. 恢复 DNS 设置
/// 3. 兜底设置为国内公共 DNS (223.5.5.5 和 114.114.114.114)
class KRWindowsDnsUtil {
  /// 私有构造函数
  KRWindowsDnsUtil._();

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

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

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

  /// 原始 DNS 服务器地址（连接前备份）
  List<String>? _originalDnsServers;

  /// 主网络接口名称
  String? _primaryInterfaceName;

  /// 备份当前 DNS 设置
  ///
  /// 在连接 VPN 之前调用，保存原始 DNS 配置
  /// 返回：true-成功，false-失败
  Future<bool> kr_backupDnsSettings() async {
    if (!Platform.isWindows) {
      KRLogUtil.kr_w('❌ 非 Windows 平台，跳过 DNS 备份', tag: 'WindowsDNS');
      return false;
    }

    try {
      // 🔒 添加5秒超时保护
      return await Future.value(() async {
        KRLogUtil.kr_i('📦 开始备份 Windows DNS 设置...', tag: 'WindowsDNS');

        // 1. 获取主网络接口
        final interfaceName = await _kr_getPrimaryNetworkInterface();
        if (interfaceName == null) {
          KRLogUtil.kr_e('❌ 无法获取主网络接口', tag: 'WindowsDNS');
          return false;
        }
        _primaryInterfaceName = interfaceName;
        KRLogUtil.kr_i('🔍 主网络接口: $_primaryInterfaceName', tag: 'WindowsDNS');

        // 2. 获取当前 DNS 服务器
        final dnsServers = await _kr_getCurrentDnsServers(interfaceName);

        // 🔧 P0修复1: 过滤掉 127.0.0.1 (sing-box 的本地 DNS)
        // 原因：如果备份了 127.0.0.1，关闭 VPN 后恢复为 127.0.0.1，但 sing-box 已停止，导致 DNS 无法解析
        final validDnsServers = dnsServers.where((dns) => !dns.startsWith('127.')).toList();

        if (validDnsServers.isEmpty) {
          KRLogUtil.kr_w('⚠️ 当前 DNS 为空或全是本地地址，设为 DHCP 自动获取', tag: 'WindowsDNS');
          if (dnsServers.isNotEmpty) {
            KRLogUtil.kr_i('   (已过滤的本地DNS: ${dnsServers.join(", ")})', tag: 'WindowsDNS');
          }
          _originalDnsServers = []; // 空列表表示 DHCP 自动获取
        } else {
          _originalDnsServers = validDnsServers;
          KRLogUtil.kr_i('✅ 已备份有效 DNS: ${validDnsServers.join(", ")}', tag: 'WindowsDNS');
          if (dnsServers.length != validDnsServers.length) {
            KRLogUtil.kr_i('   (已过滤掉 ${dnsServers.length - validDnsServers.length} 个本地地址)', tag: 'WindowsDNS');
          }
        }

        return true;
      }()).timeout(
        const Duration(seconds: 5),
        onTimeout: () {
          KRLogUtil.kr_w('⏱️ DNS 备份操作超时（5秒），跳过备份', tag: 'WindowsDNS');
          return false;
        },
      );
    } catch (e) {
      KRLogUtil.kr_e('❌ 备份 DNS 设置失败: $e', tag: 'WindowsDNS');
      return false;
    }
  }

  /// 恢复原始 DNS 设置
  ///
  /// 在断开 VPN 后调用，恢复备份的 DNS 配置
  /// 如果恢复失败，会自动调用兜底机制设置为公共DNS
  /// 返回：true-成功，false-失败
  Future<bool> kr_restoreDnsSettings() async {
    if (!Platform.isWindows) {
      KRLogUtil.kr_w('❌ 非 Windows 平台，跳过 DNS 恢复', tag: 'WindowsDNS');
      return false;
    }

    try {
      KRLogUtil.kr_i('🔄 开始恢复 Windows DNS 设置...', tag: 'WindowsDNS');

      // 🔧 P1修复: 恢复时重新检测主接口，防止网络切换导致恢复错误接口
      final currentInterface = await _kr_getPrimaryNetworkInterface();
      if (currentInterface == null) {
        KRLogUtil.kr_e('❌ 无法检测当前网络接口，执行兜底恢复', tag: 'WindowsDNS');
        return await _kr_fallbackRestoreDns();
      }

      // 检查接口是否变化
      if (_primaryInterfaceName != null && _primaryInterfaceName != currentInterface) {
        KRLogUtil.kr_w('⚠️ 网络接口已变化: $_primaryInterfaceName → $currentInterface', tag: 'WindowsDNS');
        KRLogUtil.kr_w('   执行兜底恢复以确保当前接口DNS正常', tag: 'WindowsDNS');
        _primaryInterfaceName = currentInterface; // 更新为当前接口
        return await _kr_fallbackRestoreDns();
      }

      // 使用当前检测到的接口
      _primaryInterfaceName = currentInterface;
      KRLogUtil.kr_i('🔍 当前网络接口: $_primaryInterfaceName', tag: 'WindowsDNS');

      // 1. 检查是否有备份的DNS
      if (_originalDnsServers == null) {
        KRLogUtil.kr_w('⚠️ 没有备份的 DNS，执行兜底恢复', tag: 'WindowsDNS');
        return await _kr_fallbackRestoreDns();
      }

      // 2. 恢复原始 DNS

      if (_originalDnsServers!.isEmpty) {
        // 原本是 DHCP 自动获取
        KRLogUtil.kr_i('🔄 恢复为 DHCP 自动获取 DNS', tag: 'WindowsDNS');
        final success = await _kr_setDnsToAuto(_primaryInterfaceName!);
        if (!success) {
          KRLogUtil.kr_w('⚠️ 恢复 DHCP 失败，执行兜底恢复', tag: 'WindowsDNS');
          return await _kr_fallbackRestoreDns();
        }
      } else {
        // 恢复指定的 DNS 服务器
        KRLogUtil.kr_i('🔄 恢复原始 DNS: ${_originalDnsServers!.join(", ")}', tag: 'WindowsDNS');
        final success = await _kr_setDnsServers(
          _primaryInterfaceName!,
          _originalDnsServers!,
        );
        if (!success) {
          KRLogUtil.kr_w('⚠️ 恢复原始 DNS 失败，执行兜底恢复', tag: 'WindowsDNS');
          return await _kr_fallbackRestoreDns();
        }
      }

      // 3. 验证 DNS 是否恢复成功
      await Future.delayed(const Duration(milliseconds: 500));
      final currentDns = await _kr_getCurrentDnsServers(_primaryInterfaceName!);
      KRLogUtil.kr_i('✅ 当前 DNS: ${currentDns.join(", ")}', tag: 'WindowsDNS');

      // 4. 额外验证：确认 DNS 不再指向 127.0.0.1（sing-box 的本地 DNS）
      final hasLocalhost = currentDns.any((dns) => dns.startsWith('127.'));
      if (hasLocalhost) {
        KRLogUtil.kr_w('⚠️ DNS 仍包含 127.0.0.1，可能未完全恢复', tag: 'WindowsDNS');
        KRLogUtil.kr_w('⚠️ 执行兜底恢复', tag: 'WindowsDNS');
        return await _kr_fallbackRestoreDns();
      }

      // 🔧 P2优化: 测试 DNS 解析是否真正可用
      KRLogUtil.kr_i('🧪 测试 DNS 解析功能...', tag: 'WindowsDNS');
      final canResolve = await _kr_testDnsResolution();
      if (!canResolve) {
        KRLogUtil.kr_w('⚠️ DNS 解析测试失败，执行兜底恢复', tag: 'WindowsDNS');
        return await _kr_fallbackRestoreDns();
      }
      KRLogUtil.kr_i('✅ DNS 解析测试通过', tag: 'WindowsDNS');

      return true;
    } catch (e) {
      KRLogUtil.kr_e('❌ 恢复 DNS 设置失败: $e', tag: 'WindowsDNS');
      KRLogUtil.kr_w('⚠️ 执行兜底恢复', tag: 'WindowsDNS');
      return await _kr_fallbackRestoreDns();
    }
  }

  /// 兜底恢复：强制设置为国内公共 DNS
  ///
  /// 当正常恢复失败时，设置为安全的公共 DNS 服务器
  /// - 主 DNS: 223.5.5.5 (阿里云)
  /// - 备用 DNS: 114.114.114.114 (114DNS)
  Future<bool> _kr_fallbackRestoreDns() async {
    try {
      KRLogUtil.kr_w('🆘 执行 DNS 兜底恢复机制', tag: 'WindowsDNS');
      KRLogUtil.kr_i('🔧 设置为国内公共 DNS: 223.5.5.5, 114.114.114.114', tag: 'WindowsDNS');

      // 1. 获取主网络接口（如果还没有）
      if (_primaryInterfaceName == null) {
        _primaryInterfaceName = await _kr_getPrimaryNetworkInterface();
        if (_primaryInterfaceName == null) {
          KRLogUtil.kr_e('❌ 无法检测网络接口，兜底恢复失败', tag: 'WindowsDNS');
          return false;
        }
      }

      // 2. 设置为公共 DNS
      final fallbackDns = ['223.5.5.5', '114.114.114.114'];
      final success = await _kr_setDnsServers(_primaryInterfaceName!, fallbackDns);

      if (success) {
        KRLogUtil.kr_i('✅ 兜底 DNS 设置成功', tag: 'WindowsDNS');

        // 3. 验证设置
        await Future.delayed(const Duration(milliseconds: 500));
        final currentDns = await _kr_getCurrentDnsServers(_primaryInterfaceName!);
        KRLogUtil.kr_i('✅ 验证当前 DNS: ${currentDns.join(", ")}', tag: 'WindowsDNS');

        return true;
      } else {
        KRLogUtil.kr_e('❌ 兜底 DNS 设置失败', tag: 'WindowsDNS');
        return false;
      }
    } catch (e) {
      KRLogUtil.kr_e('❌ 兜底恢复失败: $e', tag: 'WindowsDNS');
      return false;
    }
  }

  /// 获取主网络接口名称
  ///
  /// 通过 netsh 命令查找处于"已连接"状态的主网络接口
  /// 返回：接口名称，失败返回 null
  Future<String?> _kr_getPrimaryNetworkInterface() async {
    try {
      // 使用 netsh 获取接口列表
      final result = await KRWindowsProcessUtil.runHidden('netsh', ['interface', 'show', 'interface']);

      if (result.exitCode != 0) {
        KRLogUtil.kr_e('❌ 获取网络接口失败: ${result.stderr}', tag: 'WindowsDNS');
        return null;
      }

      final output = result.stdout.toString();
      final lines = output.split('\n');

      // 收集所有已连接的接口
      final connectedInterfaces = <String>[];

      // 查找所有"已连接"的接口
      // 支持中文和英文 Windows 系统
      for (var line in lines) {
        // 中文: "已连接", 英文: "Connected", "Enabled"
        if (line.contains('已连接') ||
            line.contains('Connected') ||
            line.toLowerCase().contains('enabled')) {
          // 跳过表头行
          if (line.contains('Admin') ||
              line.contains('管理') ||
              line.contains('State') ||
              line.contains('状态')) {
            continue;
          }

          // 解析接口名称（最后一列）
          final parts = line.trim().split(RegExp(r'\s{2,}'));
          if (parts.length >= 4) {
            final interfaceName = parts.last.trim();
            // 排除空接口名
            if (interfaceName.isNotEmpty && interfaceName.length > 1) {
              connectedInterfaces.add(interfaceName);
            }
          }
        }
      }

      if (connectedInterfaces.isEmpty) {
        KRLogUtil.kr_w('⚠️ 未找到已连接的网络接口', tag: 'WindowsDNS');
        return null;
      }

      // 🔧 优化：优先选择有线网络（以太网），然后才是 Wi-Fi
      // 有线网络通常更稳定
      String? selectedInterface;
      for (var interface in connectedInterfaces) {
        final lowerName = interface.toLowerCase();
        // 优先选择以太网
        if (lowerName.contains('ethernet') ||
            lowerName.contains('以太网') ||
            lowerName.contains('lan') ||
            lowerName.contains('local')) {
          selectedInterface = interface;
          KRLogUtil.kr_i('🔍 选择有线网络接口: $interface', tag: 'WindowsDNS');
          break;
        }
      }

      // 如果没有有线网络，选择第一个（通常是 Wi-Fi）
      selectedInterface ??= connectedInterfaces.first;
      if (selectedInterface != connectedInterfaces.first) {
        KRLogUtil.kr_d('🔍 选择网络接口: $selectedInterface', tag: 'WindowsDNS');
      } else {
        KRLogUtil.kr_i('🔍 选择网络接口: $selectedInterface', tag: 'WindowsDNS');
      }

      return selectedInterface;
    } catch (e) {
      KRLogUtil.kr_e('❌ 获取网络接口异常: $e', tag: 'WindowsDNS');
      return null;
    }
  }

  /// 获取指定接口的当前 DNS 服务器
  ///
  /// 参数：
  /// - interfaceName: 网络接口名称
  ///
  /// 返回：DNS 服务器列表
  Future<List<String>> _kr_getCurrentDnsServers(String interfaceName) async {
    try {
      final result = await KRWindowsProcessUtil.runHidden('netsh', [
        'interface',
        'ipv4',
        'show',
        'dnsservers',
        'name="$interfaceName"',
      ]);

      if (result.exitCode != 0) {
        KRLogUtil.kr_e('❌ 获取 DNS 失败: ${result.stderr}', tag: 'WindowsDNS');
        return [];
      }

      final output = result.stdout.toString();
      final dnsServers = <String>[];

      // 解析 DNS 服务器地址
      final lines = output.split('\n');
      for (var line in lines) {
        // 查找 IP 地址格式的行
        final ipMatch = RegExp(r'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b').firstMatch(line);
        if (ipMatch != null) {
          final ip = ipMatch.group(0)!;
          // 🔧 关键修复：不过滤127.0.0.1，以便正确检测DNS是否还在使用sing-box的本地DNS
          // 这样在恢复DNS时，第126行的验证才能正确检测到127.0.0.1并触发兜底恢复
          dnsServers.add(ip);
        }
      }

      KRLogUtil.kr_d('🔍 当前 DNS: ${dnsServers.join(", ")}', tag: 'WindowsDNS');
      return dnsServers;
    } catch (e) {
      KRLogUtil.kr_e('❌ 获取 DNS 异常: $e', tag: 'WindowsDNS');
      return [];
    }
  }

  /// 设置指定接口的 DNS 服务器
  ///
  /// 参数：
  /// - interfaceName: 网络接口名称
  /// - dnsServers: DNS 服务器列表
  ///
  /// 返回：true-成功，false-失败
  Future<bool> _kr_setDnsServers(String interfaceName, List<String> dnsServers) async {
    try {
      if (dnsServers.isEmpty) {
        KRLogUtil.kr_w('⚠️ DNS 列表为空，无法设置', tag: 'WindowsDNS');
        return false;
      }

      // 1. 设置主 DNS
      KRLogUtil.kr_i('🔧 设置主 DNS: ${dnsServers[0]}', tag: 'WindowsDNS');
      var result = await KRWindowsProcessUtil.runHidden('netsh', [
        'interface',
        'ipv4',
        'set',
        'dnsservers',
        'name="$interfaceName"',
        'source=static',
        'address=${dnsServers[0]}',
        'validate=no',
      ]);

      if (result.exitCode != 0) {
        KRLogUtil.kr_e('❌ 设置主 DNS 失败: ${result.stderr}', tag: 'WindowsDNS');
        return false;
      }

      // 2. 设置备用 DNS（如果有）
      if (dnsServers.length > 1) {
        for (int i = 1; i < dnsServers.length; i++) {
          KRLogUtil.kr_i('🔧 设置备用 DNS ${i}: ${dnsServers[i]}', tag: 'WindowsDNS');
          result = await KRWindowsProcessUtil.runHidden('netsh', [
            'interface',
            'ipv4',
            'add',
            'dnsservers',
            'name="$interfaceName"',
            'address=${dnsServers[i]}',
            'index=${i + 1}',
            'validate=no',
          ]);

          if (result.exitCode != 0) {
            KRLogUtil.kr_w('⚠️ 设置备用 DNS $i 失败: ${result.stderr}', tag: 'WindowsDNS');
            // 继续设置下一个，不中断
          }
        }
      }

      // 3. 刷新 DNS 缓存
      await _kr_flushDnsCache();

      KRLogUtil.kr_i('✅ DNS 服务器设置完成', tag: 'WindowsDNS');
      return true;
    } catch (e) {
      KRLogUtil.kr_e('❌ 设置 DNS 异常: $e', tag: 'WindowsDNS');
      return false;
    }
  }

  /// 设置 DNS 为自动获取（DHCP）
  ///
  /// 参数：
  /// - interfaceName: 网络接口名称
  ///
  /// 返回：true-成功，false-失败
  Future<bool> _kr_setDnsToAuto(String interfaceName) async {
    try {
      KRLogUtil.kr_i('🔧 设置 DNS 为自动获取 (DHCP)', tag: 'WindowsDNS');

      final result = await KRWindowsProcessUtil.runHidden('netsh', [
        'interface',
        'ipv4',
        'set',
        'dnsservers',
        'name="$interfaceName"',
        'source=dhcp',
      ]);

      if (result.exitCode != 0) {
        KRLogUtil.kr_e('❌ 设置 DHCP 失败: ${result.stderr}', tag: 'WindowsDNS');
        return false;
      }

      // 刷新 DNS 缓存
      await _kr_flushDnsCache();

      KRLogUtil.kr_i('✅ DNS 已设置为自动获取', tag: 'WindowsDNS');
      return true;
    } catch (e) {
      KRLogUtil.kr_e('❌ 设置 DHCP 异常: $e', tag: 'WindowsDNS');
      return false;
    }
  }

  /// 刷新 DNS 缓存
  ///
  /// 执行 ipconfig /flushdns 命令清空 DNS 解析缓存
  Future<void> _kr_flushDnsCache() async {
    try {
      KRLogUtil.kr_i('🔄 刷新 DNS 缓存...', tag: 'WindowsDNS');

      final result = await KRWindowsProcessUtil.runHidden('ipconfig', ['/flushdns']);

      if (result.exitCode == 0) {
        KRLogUtil.kr_i('✅ DNS 缓存已刷新', tag: 'WindowsDNS');
      } else {
        KRLogUtil.kr_w('⚠️ 刷新 DNS 缓存失败: ${result.stderr}', tag: 'WindowsDNS');
      }
    } catch (e) {
      KRLogUtil.kr_w('⚠️ 刷新 DNS 缓存异常: $e', tag: 'WindowsDNS');
    }
  }

  /// 🔧 P2优化: 测试 DNS 解析是否真正可用
  ///
  /// 通过 nslookup 测试常见域名解析
  /// 返回：true 表示 DNS 可用，false 表示 DNS 不可用
  Future<bool> _kr_testDnsResolution() async {
    try {
      // 测试多个常见域名，提高成功率
      final testDomains = ['www.baidu.com', 'www.qq.com', 'dns.alidns.com'];

      for (var domain in testDomains) {
        try {
          // 使用 nslookup 测试 DNS 解析，设置 2 秒超时
          final result = await KRWindowsProcessUtil.runHidden(
            'nslookup',
            [domain],
          ).timeout(
            const Duration(seconds: 2),
            onTimeout: () {
              return ProcessResult(0, 1, '', 'Timeout');
            },
          );

          if (result.exitCode == 0) {
            final output = result.stdout.toString();
            // 检查输出是否包含 IP 地址（简单验证）
            if (output.contains('Address:') || output.contains('地址:')) {
              KRLogUtil.kr_i('✅ DNS 解析测试通过: $domain', tag: 'WindowsDNS');
              return true;
            }
          }
        } catch (e) {
          // 单个域名失败，继续测试下一个
          continue;
        }
      }

      // 所有域名都解析失败
      KRLogUtil.kr_w('⚠️ 所有测试域名解析均失败', tag: 'WindowsDNS');
      return false;
    } catch (e) {
      KRLogUtil.kr_e('❌ DNS 解析测试异常: $e', tag: 'WindowsDNS');
      return false;
    }
  }

  /// 清除备份数据
  ///
  /// 在应用退出或不需要时调用
  void kr_clearBackup() {
    _originalDnsServers = null;
    _primaryInterfaceName = null;
    KRLogUtil.kr_d('🗑️ 已清除 DNS 备份数据', tag: 'WindowsDNS');
  }
}
