import '../model/response/kr_config_data.dart';
import '../services/api_service/kr_api.user.dart';
import '../utils/kr_update_util.dart';
import '../utils/kr_secure_storage.dart';
import '../utils/kr_log_util.dart';
import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:dio/dio.dart';

/// 协议配置
class KRProtocol {
  static const String kr_https = "https";
  static const String kr_http = "http";
  static const String kr_ws = "ws";
}

/// 域名配置
class KRDomain {


  static const String kr_domainKey = "kr_base_domain";
  static const String kr_domainsKey = "kr_domains_list";
  
  static List<String> kr_baseDomains = ["apicn.bearvpn.top","apibear.nsdsox.com"];
  static String kr_currentDomain = "apicn.bearvpn.top";

  // static List<String> kr_baseDomains = ["api.kkmen.cc"];
  // static String kr_currentDomain = "api.kkmen.cc";
  
  // 备用域名获取地址列表
  static List<String> kr_backupDomainUrls = [
    "https://bear-1347601445.cos.ap-guangzhou.myqcloud.com/bear.txt",
    "https://getbr.oss-cn-shanghai.aliyuncs.com/bear.txt",
    "https://gitee.com/karelink/getbr/raw/master/README.en.md",
    "https://configfortrans.oss-cn-guangzhou.aliyuncs.com/bear/bear.txt",
  ];
  
  // 本地备用域名列表（当服务器获取的域名都不可用时使用）
  static List<String> kr_localBackupDomains = [
    "api.omntech.com",
    "api6.omntech.com", 
    "api7.omntech.com",
    "apicn.bearvpn.top",
    "apibear.nsdsox.com",
  ];
  
  static final _storage = KRSecureStorage();
  static Timer? _retryTimer;
  static const int kr_retryInterval = 2; // 基础重试间隔（秒）
  static const int kr_maxRetryCount = 2; // 最大重试次数
  static const int kr_domainTimeout = 3; // 域名检测超时时间（秒）
  static const int kr_totalTimeout = 6; // 总体超时时间（秒）
  static Set<String> _triedDomains = {}; // 已尝试过的域名集合
  static Map<String, int> _domainResponseTimes = {}; // 域名响应时间记录
  static Map<String, DateTime> _domainLastCheck = {}; // 域名最后检测时间
  static const int _domainCacheDuration = 300; // 域名缓存时间（秒）
  static final Dio _dio = Dio(); // Dio 实例

  /// API 域名
  static String get kr_api => kr_currentDomain;

  /// WebSocket 域名
  static String get kr_ws => "$kr_currentDomain/v1/app";

  /// 从URL中提取域名
  static String kr_extractDomain(String url) {
    try {
      KRLogUtil.kr_i('🔍 提取域名，原始数据: $url', tag: 'KRDomain');
      
      if (url.isEmpty) {
        KRLogUtil.kr_w('⚠️ 输入为空', tag: 'KRDomain');
        return '';
      }
      
      // 移除协议前缀
      String domain = url.replaceAll(RegExp(r'^https?://'), '');
      
      // 移除路径部分
      domain = domain.split('/')[0];
      
      // 移除查询参数
      domain = domain.split('?')[0];
      
      // 移除锚点
      domain = domain.split('#')[0];
      
      // 清理空白字符
      domain = domain.trim();
      
      // 验证域名格式
      if (domain.isEmpty) {
        KRLogUtil.kr_w('⚠️ 提取后域名为空', tag: 'KRDomain');
        return '';
      }
      
      // 检查是否包含有效的域名字符
      // 支持域名格式：example.com, example.com:8080, 192.168.1.1, 192.168.1.1:8080
      if (!RegExp(r'^[a-zA-Z0-9.-]+(:\d+)?$').hasMatch(domain)) {
        KRLogUtil.kr_w('⚠️ 域名格式无效: $domain', tag: 'KRDomain');
        return '';
      }
      
      KRLogUtil.kr_i('✅ 成功提取域名: $domain', tag: 'KRDomain');
      return domain;
    } catch (e) {
      KRLogUtil.kr_e('❌ 提取域名异常: $e', tag: 'KRDomain');
      return '';
    }
  }

  /// 快速检查域名可用性（用于预检测）
  static Future<bool> kr_fastCheckDomainAvailability(String domain) async {
    try {
      KRLogUtil.kr_i('⚡ 快速检测域名: $domain', tag: 'KRDomain');
      final startTime = DateTime.now();
      
      final response = await _dio.get(
        '${KRProtocol.kr_https}://$domain',
        options: Options(
          sendTimeout: Duration(seconds: 2), // 2秒超时
          receiveTimeout: Duration(seconds: 2),
          // 允许所有状态码，只要能够连接就认为域名可用
          validateStatus: (status) => status != null && status >= 200 && status < 600,
        ),
      );
      final endTime = DateTime.now();
      
      // 记录响应时间
      final responseTime = endTime.difference(startTime).inMilliseconds;
      _domainResponseTimes[domain] = responseTime;
      
      // 只要能够连接就认为域名可用（包括404、403等状态码）
      if (response.statusCode != null) {
        KRLogUtil.kr_i('✅ 快速检测成功，域名 $domain 可用，状态码: ${response.statusCode}，响应时间: ${responseTime}ms', tag: 'KRDomain');
        return true;
      } else {
        KRLogUtil.kr_w('❌ 快速检测失败，域名 $domain 响应异常，状态码: ${response.statusCode}', tag: 'KRDomain');
        return false;
      }
    } on DioException catch (e) {
      // 检查是否是连接超时或网络错误
      if (e.type == DioExceptionType.connectionTimeout ||
          e.type == DioExceptionType.receiveTimeout ||
          e.type == DioExceptionType.sendTimeout ||
          e.type == DioExceptionType.connectionError) {
        KRLogUtil.kr_w('❌ 快速检测失败，域名 $domain 连接超时或网络错误: ${e.message}', tag: 'KRDomain');
        return false;
      } else {
        // 其他错误（如404、403等）认为域名可用
        KRLogUtil.kr_i('✅ 快速检测成功，域名 $domain 可用（有响应但状态码异常）: ${e.message}', tag: 'KRDomain');
        return true;
      }
    } catch (e) {
      KRLogUtil.kr_e('❌ 快速检测异常，域名 $domain 检查异常: $e', tag: 'KRDomain');
      return false;
    }
  }

  /// 检查域名可用性
  static Future<bool> kr_checkDomainAvailability(String domain) async {
    // 清理过期缓存
    _kr_clearExpiredCache();
    
    // 检查缓存
    final lastCheck = _domainLastCheck[domain];
    if (lastCheck != null) {
      final timeSinceLastCheck = DateTime.now().difference(lastCheck).inSeconds;
      if (timeSinceLastCheck < _domainCacheDuration) {
        // 使用缓存的响应时间判断域名是否可用
        final responseTime = _domainResponseTimes[domain];
        if (responseTime != null && responseTime < 5000) { // 5秒内响应认为可用
          KRLogUtil.kr_i('📋 使用缓存结果，域名 $domain 可用（缓存时间: ${timeSinceLastCheck}s）', tag: 'KRDomain');
          return true;
        }
      }
    }
    
    try {
      KRLogUtil.kr_i('🔍 开始检测域名: $domain', tag: 'KRDomain');
      final startTime = DateTime.now();
      
      final response = await _dio.get(
        '${KRProtocol.kr_https}://$domain',
        options: Options(
          sendTimeout: Duration(seconds: kr_domainTimeout),
          receiveTimeout: Duration(seconds: kr_domainTimeout),
          // 允许所有状态码，只要能够连接就认为域名可用
          validateStatus: (status) => status != null && status >= 200 && status < 600,
        ),
      );
      final endTime = DateTime.now();
      
      // 记录响应时间和检测时间
      final responseTime = endTime.difference(startTime).inMilliseconds;
      _domainResponseTimes[domain] = responseTime;
      _domainLastCheck[domain] = DateTime.now();
      
      // 只要能够连接就认为域名可用（包括404、403等状态码）
      if (response.statusCode != null) {
        KRLogUtil.kr_i('✅ 域名 $domain 可用，状态码: ${response.statusCode}，响应时间: ${responseTime}ms', tag: 'KRDomain');
        return true;
      } else {
        KRLogUtil.kr_w('❌ 域名 $domain 响应异常，状态码: ${response.statusCode}', tag: 'KRDomain');
        return false;
      }
    } on DioException catch (e) {
      // 检查是否是连接超时或网络错误
      if (e.type == DioExceptionType.connectionTimeout ||
          e.type == DioExceptionType.receiveTimeout ||
          e.type == DioExceptionType.sendTimeout ||
          e.type == DioExceptionType.connectionError) {
        KRLogUtil.kr_w('❌ 域名 $domain 连接超时或网络错误: ${e.message}', tag: 'KRDomain');
        return false;
      } else {
        // 其他错误（如404、403等）认为域名可用
        KRLogUtil.kr_i('✅ 域名 $domain 可用（有响应但状态码异常）: ${e.message}', tag: 'KRDomain');
        return true;
      }
    } catch (e) {
      KRLogUtil.kr_e('❌ 域名 $domain 检查异常: $e', tag: 'KRDomain');
      return false;
    }
  }

  /// 获取最快的可用域名
  static Future<String?> kr_getFastestAvailableDomain() async {
    if (kr_baseDomains.isEmpty) return null;
    
    // 按响应时间排序域名
    final sortedDomains = kr_baseDomains.toList()
      ..sort((a, b) => (_domainResponseTimes[a] ?? double.infinity)
          .compareTo(_domainResponseTimes[b] ?? double.infinity));
    
    // 检查最快的域名是否可用
    for (String domain in sortedDomains) {
      if (await kr_checkDomainAvailability(domain)) {
        return domain;
      }
    }
    
    return null;
  }

    /// 快速域名切换 - 并发检测所有域名
  static Future<String?> kr_fastDomainSwitch() async {
    if (kr_baseDomains.isEmpty) return null;
    
    KRLogUtil.kr_i('🚀 开始快速域名切换，检测 ${kr_baseDomains.length} 个主域名: $kr_baseDomains', tag: 'KRDomain');
    final startTime = DateTime.now();
    
    // 先检查缓存，如果有可用的域名直接返回
    for (String domain in kr_baseDomains) {
      final lastCheck = _domainLastCheck[domain];
      if (lastCheck != null) {
        final timeSinceLastCheck = DateTime.now().difference(lastCheck).inSeconds;
        if (timeSinceLastCheck < _domainCacheDuration) {
          final responseTime = _domainResponseTimes[domain];
          if (responseTime != null && responseTime < 2000) { // 降低缓存阈值
            KRLogUtil.kr_i('🎯 使用缓存结果快速切换，域名: $domain', tag: 'KRDomain');
            return domain;
          }
        }
      }
    }
    
    // 创建并发任务列表
    List<Future<MapEntry<String, bool>>> tasks = kr_baseDomains.map((domain) async {
      bool isAvailable = await kr_checkDomainAvailability(domain);
      return MapEntry(domain, isAvailable);
    }).toList();
    
    // 等待所有任务完成，但设置总体超时
    try {
      KRLogUtil.kr_i('⏱️ 等待并发检测结果，超时时间: ${kr_totalTimeout}秒', tag: 'KRDomain');
      List<MapEntry<String, bool>> results = await Future.wait(
        tasks,
      ).timeout(Duration(seconds: kr_totalTimeout));
      
      final endTime = DateTime.now();
      final duration = endTime.difference(startTime).inMilliseconds;
      KRLogUtil.kr_i('📊 主域名检测完成，耗时: ${duration}ms', tag: 'KRDomain');
      
      // 统计结果
      int availableCount = 0;
      for (MapEntry<String, bool> result in results) {
        if (result.value) {
          availableCount++;
          KRLogUtil.kr_i('✅ 主域名可用: ${result.key}', tag: 'KRDomain');
        } else {
          KRLogUtil.kr_w('❌ 主域名不可用: ${result.key}', tag: 'KRDomain');
        }
      }
      
      KRLogUtil.kr_i('📈 主域名检测结果: $availableCount/${results.length} 可用', tag: 'KRDomain');
      
      // 找到第一个可用的域名
      for (MapEntry<String, bool> result in results) {
        if (result.value) {
          KRLogUtil.kr_i('🎯 快速切换选择域名: ${result.key}', tag: 'KRDomain');
          return result.key;
        }
      }
      
      KRLogUtil.kr_w('⚠️ 所有主域名都不可用，开始尝试备用域名', tag: 'KRDomain');
      
      // 如果主域名都不可用，快速尝试备用域名
      String? backupDomain = await kr_fastBackupDomainSwitch();
      if (backupDomain != null) {
        KRLogUtil.kr_i('✅ 备用域名切换成功: $backupDomain', tag: 'KRDomain');
        return backupDomain;
      }
      
      // 如果备用域名也失败，尝试使用本地配置的备用域名
      KRLogUtil.kr_w('⚠️ 备用域名也失败，尝试使用本地配置的备用域名', tag: 'KRDomain');
      String? localBackupDomain = await kr_tryLocalBackupDomains();
      if (localBackupDomain != null) {
        KRLogUtil.kr_i('✅ 本地备用域名切换成功: $localBackupDomain', tag: 'KRDomain');
        return localBackupDomain;
      }
      
      // 最后兜底方案
      KRLogUtil.kr_w('⚠️ 所有域名都失败，使用兜底域名', tag: 'KRDomain');
      return "api.omntech.com";
      
    } catch (e) {
      final endTime = DateTime.now();
      final duration = endTime.difference(startTime).inMilliseconds;
      KRLogUtil.kr_e('⏰ 快速域名切换超时或异常 (${duration}ms): $e', tag: 'KRDomain');
      
      // 超时或异常时，尝试使用本地配置的备用域名
      KRLogUtil.kr_w('⚠️ 快速切换超时，尝试使用本地备用域名', tag: 'KRDomain');
      String? localBackupDomain = await kr_tryLocalBackupDomains();
      if (localBackupDomain != null) {
        KRLogUtil.kr_i('✅ 本地备用域名切换成功: $localBackupDomain', tag: 'KRDomain');
        return localBackupDomain;
      }
      
      return null;
    }
  }

  /// 预检测域名可用性（在应用启动时调用）
  static Future<void> kr_preCheckDomains() async {
    KRLogUtil.kr_i('🚀 开始预检测域名可用性', tag: 'KRDomain');
    
    // 异步预检测，不阻塞应用启动
    Future.microtask(() async {
      try {
        // 如果当前域名已经在主域名列表中，先检查它是否可用
        if (kr_baseDomains.contains(kr_currentDomain)) {
          bool isCurrentAvailable = await kr_fastCheckDomainAvailability(kr_currentDomain);
          if (isCurrentAvailable) {
            KRLogUtil.kr_i('✅ 当前域名可用，无需切换: $kr_currentDomain', tag: 'KRDomain');
            return; // 当前域名可用，不需要切换
          }
        }
        
        // 快速检测第一个域名
        if (kr_baseDomains.isNotEmpty) {
          String firstDomain = kr_baseDomains.first;
          bool isAvailable = await kr_fastCheckDomainAvailability(firstDomain);
          
          if (isAvailable) {
            KRLogUtil.kr_i('✅ 预检测成功，主域名可用: $firstDomain', tag: 'KRDomain');
            // 预设置可用域名，避免后续切换
            kr_currentDomain = firstDomain;
            await kr_saveCurrentDomain();
          } else {
            KRLogUtil.kr_i('⚠️ 预检测失败，主域名不可用: $firstDomain', tag: 'KRDomain');
            // 如果主域名不可用，立即尝试备用域名，不等待
            kr_fastDomainSwitch().then((newDomain) {
              if (newDomain != null) {
                KRLogUtil.kr_i('✅ 预检测备用域名成功: $newDomain', tag: 'KRDomain');
              }
            });
          }
        }
      } catch (e) {
        KRLogUtil.kr_w('⚠️ 预检测异常: $e', tag: 'KRDomain');
      }
    });
  }

  /// 快速备用域名切换 - 直接从备用地址获取域名，不请求/v1/app/auth/config
  static Future<String?> kr_fastBackupDomainSwitch() async {
    KRLogUtil.kr_i('🔄 开始快速备用域名切换，备用地址: $kr_backupDomainUrls', tag: 'KRDomain');
    final startTime = DateTime.now();
    
    // 并发获取所有备用地址的域名
    List<Future<List<String>>> backupTasks = kr_backupDomainUrls.map((url) async {
      try {
        KRLogUtil.kr_i('📡 从备用地址获取域名: $url', tag: 'KRDomain');
        final response = await _dio.get(
          url,
          options: Options(
            sendTimeout: Duration(seconds: kr_domainTimeout),
            receiveTimeout: Duration(seconds: kr_domainTimeout),
          ),
        );
        
        if (response.statusCode == 200 && response.data != null) {
          String responseData = response.data.toString();
          KRLogUtil.kr_i('📥 备用地址 $url 返回数据: $responseData', tag: 'KRDomain');
          List<String> domains = kr_parseBackupDomains(responseData);
          KRLogUtil.kr_i('🔍 解析到备用域名: $domains', tag: 'KRDomain');
          return domains;
        } else {
          KRLogUtil.kr_w('❌ 备用地址 $url 响应异常，状态码: ${response.statusCode}', tag: 'KRDomain');
        }
      } catch (e) {
        KRLogUtil.kr_w('❌ 备用地址 $url 获取失败: $e', tag: 'KRDomain');
      }
      return <String>[];
    }).toList();
    
    try {
      KRLogUtil.kr_i('⏱️ 等待备用地址响应，超时时间: ${kr_totalTimeout - 1}秒', tag: 'KRDomain');
      List<List<String>> backupResults = await Future.wait(
        backupTasks,
      ).timeout(Duration(seconds: kr_totalTimeout - 1)); // 留1秒给域名测试
      
      // 合并所有备用域名并去重
      Set<String> uniqueBackupDomains = {};
      for (List<String> domains in backupResults) {
        uniqueBackupDomains.addAll(domains);
      }
      List<String> allBackupDomains = uniqueBackupDomains.toList();
      
      KRLogUtil.kr_i('📋 合并并去重后的备用域名: $allBackupDomains', tag: 'KRDomain');
      
      if (allBackupDomains.isEmpty) {
        KRLogUtil.kr_w('⚠️ 没有获取到备用域名', tag: 'KRDomain');
        return null;
      }
      
      KRLogUtil.kr_i('🧪 开始测试 ${allBackupDomains.length} 个备用域名', tag: 'KRDomain');
      
      // 并发测试所有备用域名
      List<Future<MapEntry<String, bool>>> testTasks = allBackupDomains.map((domain) async {
        bool isAvailable = await kr_checkDomainAvailability(domain);
        return MapEntry(domain, isAvailable);
      }).toList();
      
      List<MapEntry<String, bool>> testResults = await Future.wait(
        testTasks,
      ).timeout(Duration(seconds: 2)); // 增加到2秒内完成测试
      
      final endTime = DateTime.now();
      final duration = endTime.difference(startTime).inMilliseconds;
      KRLogUtil.kr_i('📊 备用域名检测完成，总耗时: ${duration}ms', tag: 'KRDomain');
      
      // 统计备用域名结果
      int availableBackupCount = 0;
      for (MapEntry<String, bool> result in testResults) {
        if (result.value) {
          availableBackupCount++;
          KRLogUtil.kr_i('✅ 备用域名可用: ${result.key}', tag: 'KRDomain');
        } else {
          KRLogUtil.kr_w('❌ 备用域名不可用: ${result.key}', tag: 'KRDomain');
        }
      }
      
      KRLogUtil.kr_i('📈 备用域名检测结果: $availableBackupCount/${testResults.length} 可用', tag: 'KRDomain');
      
      // 找到第一个可用的备用域名
      for (MapEntry<String, bool> result in testResults) {
        if (result.value) {
          KRLogUtil.kr_i('🎯 快速切换选择备用域名: ${result.key}', tag: 'KRDomain');
          
          // 更新当前域名并保存
          kr_currentDomain = result.key;
          await kr_saveCurrentDomain();
          KRLogUtil.kr_i('💾 已保存新域名: $kr_currentDomain', tag: 'KRDomain');
          
          // 将备用域名添加到主域名列表
          if (!kr_baseDomains.contains(result.key)) {
            kr_baseDomains.add(result.key);
            await kr_saveDomains(kr_baseDomains);
            KRLogUtil.kr_i('📝 已将备用域名添加到主域名列表', tag: 'KRDomain');
          }
          
          // 重要：直接返回可用域名，不再请求/v1/app/auth/config
          KRLogUtil.kr_i('✅ 备用域名切换成功，直接使用: ${result.key}', tag: 'KRDomain');
          return result.key;
        }
      }
      
      KRLogUtil.kr_w('⚠️ 所有备用域名都不可用', tag: 'KRDomain');
      return null;
      
    } catch (e) {
      final endTime = DateTime.now();
      final duration = endTime.difference(startTime).inMilliseconds;
      KRLogUtil.kr_e('⏰ 快速备用域名切换异常 (${duration}ms): $e', tag: 'KRDomain');
      return null;
    }
  }

  /// 从备用地址获取域名列表
  static Future<List<String>> kr_getBackupDomains() async {
    List<String> backupDomains = [];
    
    for (String backupUrl in kr_backupDomainUrls) {
      try {
        KRLogUtil.kr_i('尝试从备用地址获取域名: $backupUrl', tag: 'KRDomain');
        
        final response = await _dio.get(
          backupUrl,
          options: Options(
            sendTimeout: const Duration(seconds: 10),
            receiveTimeout: const Duration(seconds: 10),
          ),
        );
        
        if (response.statusCode == 200 && response.data != null) {
          String responseData = response.data.toString();
          KRLogUtil.kr_i('备用地址返回数据: $responseData', tag: 'KRDomain');
          
          // 处理返回的JSON数据
          List<String> domains = kr_parseBackupDomains(responseData);
          backupDomains.addAll(domains);
          
          KRLogUtil.kr_i('解析到备用域名: $domains', tag: 'KRDomain');
        }
      } catch (e) {
        KRLogUtil.kr_w('从备用地址 $backupUrl 获取域名失败: $e', tag: 'KRDomain');
      }
    }
    
    return backupDomains;
  }

  /// 解析备用域名JSON数据
  static List<String> kr_parseBackupDomains(String jsonData) {
    List<String> domains = [];
    
    try {
      KRLogUtil.kr_i('🔍 开始解析备用域名数据: $jsonData', tag: 'KRDomain');
      
      // 尝试解析为JSON数组
      if (jsonData.startsWith('[') && jsonData.endsWith(']')) {
        List<dynamic> jsonList = json.decode(jsonData);
        KRLogUtil.kr_i('📋 解析为JSON数组，长度: ${jsonList.length}', tag: 'KRDomain');
        
        for (int i = 0; i < jsonList.length; i++) {
          dynamic item = jsonList[i];
          KRLogUtil.kr_i('🔍 处理第 $i 项: $item (类型: ${item.runtimeType})', tag: 'KRDomain');
          
          if (item is String) {
            // 字符串格式
            String domain = kr_extractDomain(item);
            if (domain.isNotEmpty) {
              domains.add(domain);
              KRLogUtil.kr_i('✅ 从字符串提取域名: $domain', tag: 'KRDomain');
            }
          } else if (item is Map) {
            // 对象格式，如 {https:, 158.247.232.203:8080}
            KRLogUtil.kr_i('🔍 处理对象格式: $item', tag: 'KRDomain');
            
            // 遍历对象的键值对
            item.forEach((key, value) {
              KRLogUtil.kr_i('🔍 键: $key, 值: $value', tag: 'KRDomain');
              
              if (value is String && value.isNotEmpty) {
                // 如果值是字符串，直接作为域名
                String domain = kr_extractDomain(value);
                if (domain.isNotEmpty) {
                  domains.add(domain);
                  KRLogUtil.kr_i('✅ 从对象值提取域名: $domain', tag: 'KRDomain');
                }
              } else if (key is String && key.isNotEmpty) {
                // 如果键是字符串，也尝试提取域名
                String domain = kr_extractDomain(key);
                if (domain.isNotEmpty) {
                  domains.add(domain);
                  KRLogUtil.kr_i('✅ 从对象键提取域名: $domain', tag: 'KRDomain');
                }
              }
            });
          } else {
            KRLogUtil.kr_w('⚠️ 未知的数据类型: ${item.runtimeType}', tag: 'KRDomain');
          }
        }
      } else if (jsonData.startsWith('{') && jsonData.endsWith('}')) {
        // 处理类似 { "url1", "url2" } 的格式
        KRLogUtil.kr_i('🔍 尝试解析为对象格式', tag: 'KRDomain');
        
        try {
          // 尝试解析为JSON对象
          Map<String, dynamic> jsonMap = json.decode(jsonData);
          KRLogUtil.kr_i('📋 解析为JSON对象，键数量: ${jsonMap.length}', tag: 'KRDomain');
          
          jsonMap.forEach((key, value) {
            KRLogUtil.kr_i('🔍 键: $key, 值: $value', tag: 'KRDomain');
            
            if (value is String && value.isNotEmpty) {
              String domain = kr_extractDomain(value);
              if (domain.isNotEmpty) {
                domains.add(domain);
                KRLogUtil.kr_i('✅ 从对象值提取域名: $domain', tag: 'KRDomain');
              }
            } else if (key.isNotEmpty) {
              String domain = kr_extractDomain(key);
              if (domain.isNotEmpty) {
                domains.add(domain);
                KRLogUtil.kr_i('✅ 从对象键提取域名: $domain', tag: 'KRDomain');
              }
            }
          });
        } catch (e) {
          KRLogUtil.kr_w('⚠️ JSON对象解析失败，尝试字符串解析: $e', tag: 'KRDomain');
          
          // 如果不是标准JSON，尝试字符串解析
          String cleanData = jsonData
              .replaceAll('{', '')
              .replaceAll('}', '')
              .replaceAll('"', '')
              .replaceAll("'", '');
          
          KRLogUtil.kr_i('🧹 清理后的数据: $cleanData', tag: 'KRDomain');
          
          // 按逗号分割
          List<String> parts = cleanData.split(',');
          for (String part in parts) {
            String trimmed = part.trim();
            if (trimmed.isNotEmpty) {
              String domain = kr_extractDomain(trimmed);
              if (domain.isNotEmpty) {
                domains.add(domain);
                KRLogUtil.kr_i('✅ 从字符串提取域名: $domain', tag: 'KRDomain');
              }
            }
          }
        }
      } else {
        // 尝试解析为字符串数组格式
        KRLogUtil.kr_i('🔍 尝试解析为字符串格式', tag: 'KRDomain');
        
        // 移除可能的引号和方括号
        String cleanData = jsonData
            .replaceAll('[', '')
            .replaceAll(']', '')
            .replaceAll('{', '')
            .replaceAll('}', '')
            .replaceAll('"', '')
            .replaceAll("'", '');
        
        KRLogUtil.kr_i('🧹 清理后的数据: $cleanData', tag: 'KRDomain');
        
        // 按逗号分割
        List<String> parts = cleanData.split(',');
        for (String part in parts) {
          String trimmed = part.trim();
          if (trimmed.isNotEmpty) {
            String domain = kr_extractDomain(trimmed);
            if (domain.isNotEmpty) {
              domains.add(domain);
              KRLogUtil.kr_i('✅ 从字符串提取域名: $domain', tag: 'KRDomain');
            }
          }
        }
      }
      
      KRLogUtil.kr_i('📊 解析完成，总共提取到 ${domains.length} 个域名: $domains', tag: 'KRDomain');
      
    } catch (e) {
      KRLogUtil.kr_e('❌ 解析备用域名数据失败: $e', tag: 'KRDomain');
    }
    
    return domains;
  }

  /// 测试并切换到备用域名
  static Future<bool> kr_tryBackupDomains() async {
    KRLogUtil.kr_i('开始尝试备用域名', tag: 'KRDomain');
    
    // 获取备用域名列表
    List<String> backupDomains = await kr_getBackupDomains();
    
    if (backupDomains.isEmpty) {
      KRLogUtil.kr_w('没有获取到备用域名', tag: 'KRDomain');
      return false;
    }
    
    KRLogUtil.kr_i('获取到备用域名: $backupDomains', tag: 'KRDomain');
    
    // 测试备用域名的可用性
    for (String domain in backupDomains) {
      if (await kr_checkDomainAvailability(domain)) {
        KRLogUtil.kr_i('找到可用的备用域名: $domain', tag: 'KRDomain');
        
        // 更新当前域名
        kr_currentDomain = domain;
        await kr_saveCurrentDomain();
        
        // 将备用域名添加到主域名列表
        if (!kr_baseDomains.contains(domain)) {
          kr_baseDomains.add(domain);
          await kr_saveDomains(kr_baseDomains);
        }
        
        return true;
      }
    }
    
    KRLogUtil.kr_w('所有备用域名都不可用', tag: 'KRDomain');
    return false;
  }

  /// 处理域名列表
  static Future<void> kr_handleDomains(List<String> domains) async {
    // 提取所有域名
    List<String> extractedDomains = domains.map((url) => kr_extractDomain(url)).toList();
    
    // 如果提取的域名为空，使用默认域名
    if (extractedDomains.isEmpty) {
      extractedDomains = ["kkmen.cc"];
    }
    
    // 保存域名列表
    await kr_saveDomains(extractedDomains);
    
    // 更新当前域名列表
    kr_baseDomains = extractedDomains;
    
    // 如果当前域名不在新列表中，使用第一个域名
    if (!kr_baseDomains.contains(kr_currentDomain)) {
      kr_currentDomain = kr_baseDomains[0];
      await kr_saveCurrentDomain();
    }
  }

  /// 切换到下一个域名
  static Future<bool> kr_switchToNextDomain() async {
    if (kr_baseDomains.isEmpty) return false;
    
    KRLogUtil.kr_i('🔄 开始域名切换，当前域名: $kr_currentDomain', tag: 'KRDomain');
    _triedDomains.add(kr_currentDomain);
    KRLogUtil.kr_i('📝 已尝试域名: $_triedDomains', tag: 'KRDomain');
    
    // 检查是否有预检测成功的域名可以直接使用
    if (kr_baseDomains.contains(kr_currentDomain) && 
        !_triedDomains.contains(kr_currentDomain)) {
      KRLogUtil.kr_i('✅ 使用预检测成功的域名: $kr_currentDomain', tag: 'KRDomain');
      return true;
    }
    
    // 如果已经尝试过所有主域名，使用快速切换
    if (_triedDomains.length >= kr_baseDomains.length) {
      KRLogUtil.kr_i('⚠️ 所有主域名都尝试过，切换到快速模式', tag: 'KRDomain');
      String? newDomain = await kr_fastDomainSwitch();
      if (newDomain != null) {
        kr_currentDomain = newDomain;
        await kr_saveCurrentDomain();
        _triedDomains.clear(); // 清空已尝试列表
        KRLogUtil.kr_i('✅ 快速切换成功，新域名: $kr_currentDomain', tag: 'KRDomain');
        return true;
      }
      KRLogUtil.kr_w('❌ 快速切换失败', tag: 'KRDomain');
      return false;
    }
    
    // 尝试使用最快的可用域名
    KRLogUtil.kr_i('🏃 尝试使用最快的可用域名', tag: 'KRDomain');
    String? fastestDomain = await kr_getFastestAvailableDomain();
    if (fastestDomain != null && !_triedDomains.contains(fastestDomain)) {
      kr_currentDomain = fastestDomain;
      await kr_saveCurrentDomain();
      KRLogUtil.kr_i('✅ 切换到最快域名: $kr_currentDomain', tag: 'KRDomain');
      return true;
    }
    
    // 如果最快的域名不可用，尝试其他域名
    KRLogUtil.kr_i('🔍 逐个尝试其他域名', tag: 'KRDomain');
    for (String domain in kr_baseDomains) {
      if (!_triedDomains.contains(domain)) {
        KRLogUtil.kr_i('🧪 测试域名: $domain', tag: 'KRDomain');
        if (await kr_checkDomainAvailability(domain)) {
          kr_currentDomain = domain;
          await kr_saveCurrentDomain();
          KRLogUtil.kr_i('✅ 切换到可用域名: $kr_currentDomain', tag: 'KRDomain');
          return true;
        }
      }
    }
    
    KRLogUtil.kr_w('❌ 没有找到可用的域名', tag: 'KRDomain');
    return false;
  }

  /// 开始重试请求
  static void kr_startRetry(Future<void> Function() requestFunction) {
    // 取消之前的重试定时器
    _retryTimer?.cancel();
    _triedDomains.clear();

    // 创建新的重试定时器
    _retryTimer = Timer.periodic(Duration(seconds: kr_retryInterval), (timer) async {
      // 切换到下一个域名
      bool hasNextDomain = await kr_switchToNextDomain();
      if (!hasNextDomain) {
        timer.cancel();
        return;
      }

      // 执行请求
      try {
        await requestFunction();
        // 请求成功，取消重试
        timer.cancel();
      } catch (e) {
        KRLogUtil.kr_e('重试请求失败: $e', tag: 'KRDomain');
      }
    });
  }

  /// 停止重试
  static void kr_stopRetry() {
    _retryTimer?.cancel();
    _triedDomains.clear();
  }

  /// 手动测试备用域名功能
  static Future<void> kr_testBackupDomains() async {
    KRLogUtil.kr_i('开始手动测试备用域名功能', tag: 'KRDomain');
    
    // 清空当前域名列表，模拟所有主域名失效
    List<String> originalDomains = List.from(kr_baseDomains);
    kr_baseDomains.clear();
    
    try {
      // 尝试备用域名
      bool success = await kr_tryBackupDomains();
      
      if (success) {
        KRLogUtil.kr_i('备用域名测试成功，当前域名: $kr_currentDomain', tag: 'KRDomain');
      } else {
        KRLogUtil.kr_i('备用域名测试失败', tag: 'KRDomain');
      }
    } finally {
      // 恢复原始域名列表
      kr_baseDomains = originalDomains;
    }
  }

  /// 手动触发快速域名切换
  static Future<bool> kr_triggerFastSwitch() async {
    KRLogUtil.kr_i('🎯 手动触发快速域名切换', tag: 'KRDomain');
    KRLogUtil.kr_i('📋 当前域名: $kr_currentDomain', tag: 'KRDomain');
    KRLogUtil.kr_i('📋 主域名列表: $kr_baseDomains', tag: 'KRDomain');
    KRLogUtil.kr_i('📋 备用地址列表: $kr_backupDomainUrls', tag: 'KRDomain');
    
    final startTime = DateTime.now();
    String? newDomain = await kr_fastDomainSwitch();
    final endTime = DateTime.now();
    
    final duration = endTime.difference(startTime).inMilliseconds;
    KRLogUtil.kr_i('⏱️ 快速切换总耗时: ${duration}ms', tag: 'KRDomain');
    
    if (newDomain != null) {
      kr_currentDomain = newDomain;
      await kr_saveCurrentDomain();
      KRLogUtil.kr_i('🎉 快速切换成功！新域名: $newDomain', tag: 'KRDomain');
      return true;
    } else {
      KRLogUtil.kr_w('💥 快速切换失败，没有找到可用域名', tag: 'KRDomain');
      return false;
    }
  }

  /// 尝试本地备用域名
  static Future<String?> kr_tryLocalBackupDomains() async {
    KRLogUtil.kr_i('🔄 开始尝试本地备用域名: $kr_localBackupDomains', tag: 'KRDomain');
    final startTime = DateTime.now();
    
    // 并发检测所有本地备用域名
    List<Future<MapEntry<String, bool>>> tasks = kr_localBackupDomains.map((domain) async {
      bool isAvailable = await kr_checkDomainAvailability(domain);
      return MapEntry(domain, isAvailable);
    }).toList();
    
    try {
      KRLogUtil.kr_i('⏱️ 等待本地备用域名检测结果，超时时间: ${kr_totalTimeout}秒', tag: 'KRDomain');
      List<MapEntry<String, bool>> results = await Future.wait(
        tasks,
      ).timeout(Duration(seconds: kr_totalTimeout));
      
      final endTime = DateTime.now();
      final duration = endTime.difference(startTime).inMilliseconds;
      KRLogUtil.kr_i('📊 本地备用域名检测完成，耗时: ${duration}ms', tag: 'KRDomain');
      
      // 统计结果
      int availableCount = 0;
      for (MapEntry<String, bool> result in results) {
        if (result.value) {
          availableCount++;
          KRLogUtil.kr_i('✅ 本地备用域名可用: ${result.key}', tag: 'KRDomain');
        } else {
          KRLogUtil.kr_w('❌ 本地备用域名不可用: ${result.key}', tag: 'KRDomain');
        }
      }
      
      KRLogUtil.kr_i('📈 本地备用域名检测结果: $availableCount/${results.length} 可用', tag: 'KRDomain');
      
      // 找到第一个可用的本地备用域名
      for (MapEntry<String, bool> result in results) {
        if (result.value) {
          KRLogUtil.kr_i('🎯 选择本地备用域名: ${result.key}', tag: 'KRDomain');
          
          // 更新当前域名并保存
          kr_currentDomain = result.key;
          await kr_saveCurrentDomain();
          KRLogUtil.kr_i('💾 已保存本地备用域名: $kr_currentDomain', tag: 'KRDomain');
          
          // 将本地备用域名添加到主域名列表
          if (!kr_baseDomains.contains(result.key)) {
            kr_baseDomains.add(result.key);
            await kr_saveDomains(kr_baseDomains);
            KRLogUtil.kr_i('📝 已将本地备用域名添加到主域名列表', tag: 'KRDomain');
          }
          
          return result.key;
        }
      }
      
      KRLogUtil.kr_w('⚠️ 所有本地备用域名都不可用', tag: 'KRDomain');
      return null;
      
    } catch (e) {
      final endTime = DateTime.now();
      final duration = endTime.difference(startTime).inMilliseconds;
      KRLogUtil.kr_e('⏰ 本地备用域名检测异常 (${duration}ms): $e', tag: 'KRDomain');
      return null;
    }
  }

  /// 测试备用域名解析
  static void kr_testBackupDomainParsing() {
    KRLogUtil.kr_i('🧪 开始测试备用域名解析', tag: 'KRDomain');
    
    // 测试数据
    List<String> testData = [
      '["https://apicn.bearvpn.top", "http://158.247.232.203:8080"]',
      '[{"https": "apicn.bearvpn.top"}, {"http": "158.247.232.203:8080"}]',
      '[{https:, 158.247.232.203:8080}, {https:, 158.247.232.203:8080}]',
      'https://apicn.bearvpn.top,http://158.247.232.203:8080',
      'apicn.bearvpn.top,158.247.232.203:8080',
      // 你遇到的实际数据格式
      '{\n"https://apicn.bearvpn.top",\n"http://158.247.232.203:8080"\n}'
    ];
    
    for (int i = 0; i < testData.length; i++) {
      KRLogUtil.kr_i('🧪 测试数据 $i: ${testData[i]}', tag: 'KRDomain');
      List<String> domains = kr_parseBackupDomains(testData[i]);
      KRLogUtil.kr_i('📊 解析结果 $i: $domains', tag: 'KRDomain');
    }
  }

  /// 保存域名列表到本地
  static Future<void> kr_saveDomains(List<String> domains) async {
    await _storage.kr_saveData(
      key: kr_domainsKey,
      value: domains.join(','),
    );
  }

  /// 保存当前域名到本地
  static Future<void> kr_saveCurrentDomain() async {
    await _storage.kr_saveData(
      key: kr_domainKey,
      value: kr_currentDomain,
    );
  }

  /// 从本地加载域名
  static Future<void> kr_loadBaseDomain() async {
    // 加载域名列表
    String? savedDomains = await _storage.kr_readData(key: kr_domainsKey);
    if (savedDomains != null) {
      kr_baseDomains = savedDomains.split(',');
    }

    // 加载当前域名
    String? savedDomain = await _storage.kr_readData(key: kr_domainKey);
    if (savedDomain != null && kr_baseDomains.contains(savedDomain)) {
      kr_currentDomain = savedDomain;
    } else {
      kr_currentDomain = kr_baseDomains[0];
      await kr_saveCurrentDomain();
    }
  }

  /// 清理过期的域名缓存
  static void _kr_clearExpiredCache() {
    final now = DateTime.now();
    final expiredDomains = <String>[];
    
    for (MapEntry<String, DateTime> entry in _domainLastCheck.entries) {
      final timeSinceLastCheck = now.difference(entry.value).inSeconds;
      if (timeSinceLastCheck >= _domainCacheDuration) {
        expiredDomains.add(entry.key);
      }
    }
    
    for (String domain in expiredDomains) {
      _domainLastCheck.remove(domain);
      _domainResponseTimes.remove(domain);
    }
    
    if (expiredDomains.isNotEmpty) {
      KRLogUtil.kr_i('🧹 清理过期缓存域名: $expiredDomains', tag: 'KRDomain');
    }
  }
}

class AppConfig {
  /// 请求域名地址
  /// 基础url
  // static String baseUrl = "http://103.112.98.72:8088";

  /// 请求域名地址
  String get baseUrl => "${KRProtocol.kr_https}://${KRDomain.kr_api}";
  String get wsBaseUrl => "${KRProtocol.kr_ws}://${KRDomain.kr_ws}";

  static final AppConfig _instance = AppConfig._internal();

  /// 官方邮箱
  String kr_official_email = "";

  /// 官方网站
  String kr_official_website = "";

  /// 官方电报群
  String kr_official_telegram = "";

  /// 官方电话
  String kr_official_telephone = "";

  /// 邀请链接
  String kr_invitation_link = "";

  /// 网站ID
  String kr_website_id = "";


  /// 是否为白天模式
  bool kr_is_daytime = true;

  /// 重连定时器
  Timer? _retryTimer;

  /// User API 实例
  final KRUserApi _kr_userApi = KRUserApi();
  
  /// 防重复调用标志
  bool _isInitializing = false;

  static const double kr_backoffFactor = 1.0; // 指数退避因子 - 不增加延迟
  static const int kr_retryInterval = 0; // 基础重试间隔（秒）- 立即重试
  static const int kr_maxRetryCount = 2; // 最大重试次数 - 重试两次

  AppConfig._internal() {
    // 初始化时加载保存的域名
    KRDomain.kr_loadBaseDomain();
  }

  factory AppConfig() => _instance;

  static AppConfig getInstance() {
    return _instance;
  }

  KRUpdateApplication? kr_update_application;

  Future<void> initConfig({
    Future<void> Function()? onSuccess,
  }) async {
    if (_isInitializing) {
      KRLogUtil.kr_w('配置初始化已在进行中，跳过重复调用', tag: 'AppConfig');
      return;
    }
    
    _isInitializing = true;
    try {
      await _startAutoRetry(onSuccess);
    } finally {
      _isInitializing = false;
    }
  }

  Future<void> _startAutoRetry(Future<void> Function()? onSuccess) async {
    _retryTimer?.cancel();
    int currentRetryCount = 0;
    
    Future<void> executeConfigRequest() async {
      try {
        // 检查是否超过最大重试次数
        if (currentRetryCount >= kr_maxRetryCount) {
          KRLogUtil.kr_w('达到最大重试次数，尝试使用备用域名', tag: 'AppConfig');
          // 最后一次尝试使用备用域名
          String? newDomain = await KRDomain.kr_fastDomainSwitch();
          if (newDomain != null) {
            KRDomain.kr_currentDomain = newDomain;
            await KRDomain.kr_saveCurrentDomain();
            KRLogUtil.kr_i('✅ 最终切换到备用域名: $newDomain', tag: 'AppConfig');
            // 继续重试配置请求
            await executeConfigRequest();
          }
          return;
        }

        final result = await _kr_userApi.kr_config();
        result.fold(
          (error) async {
            KRLogUtil.kr_e('配置初始化失败: $error', tag: 'AppConfig');
            currentRetryCount++;
            
            // 计算重试延迟时间
            final retryDelay = (kr_retryInterval * pow(kr_backoffFactor, currentRetryCount)).toInt();
            
            // 尝试切换域名
            await KRDomain.kr_switchToNextDomain();
            
            // 等待后重试，至少延迟100ms避免立即重试
            final actualDelay = max(retryDelay, 100);
            await Future.delayed(Duration(milliseconds: actualDelay));
            await executeConfigRequest();
          },
          (config) async {
            _retryTimer?.cancel();
            currentRetryCount = 0;
            
            kr_official_email = config.kr_official_email;
            kr_official_website = config.kr_official_website;
            kr_official_telegram = config.kr_official_telegram;
            kr_official_telephone = config.kr_official_telephone;
            kr_invitation_link = config.kr_invitation_link;
            kr_website_id = config.kr_website_id;
            if (config.kr_domains.isNotEmpty) {
              KRDomain.kr_handleDomains(config.kr_domains);
            }

            /// 判断当前是白天
            kr_is_daytime = await config.kr_update_application.kr_is_daytime() ;

            KRUpdateUtil().kr_initUpdateInfo(config.kr_update_application);

            if (onSuccess != null) {
              onSuccess();
            }
          },
        );
      } catch (e) {
        KRLogUtil.kr_e('配置初始化异常: $e', tag: 'AppConfig');
        currentRetryCount++;
        
        // 检查是否超过最大重试次数
        if (currentRetryCount >= kr_maxRetryCount) {
          KRLogUtil.kr_w('达到最大重试次数，尝试使用备用域名', tag: 'AppConfig');
          // 最后一次尝试使用备用域名
          String? newDomain = await KRDomain.kr_fastDomainSwitch();
          if (newDomain != null) {
            KRDomain.kr_currentDomain = newDomain;
            await KRDomain.kr_saveCurrentDomain();
            KRLogUtil.kr_i('✅ 最终切换到备用域名: $newDomain', tag: 'AppConfig');
            // 继续重试配置请求
            await executeConfigRequest();
          }
          return;
        }
        
        // 计算重试延迟时间
        final retryDelay = (kr_retryInterval * pow(kr_backoffFactor, currentRetryCount)).toInt();
        
        // 尝试切换域名
        await KRDomain.kr_switchToNextDomain();
        
        // 等待后重试，至少延迟100ms避免立即重试
        final actualDelay = max(retryDelay, 100);
        await Future.delayed(Duration(milliseconds: actualDelay));
        await executeConfigRequest();
      }
    }

    // 开始第一次请求
    await executeConfigRequest();
  }

  /// 停止自动重连
  void kr_stopAutoRetry() {
    _retryTimer?.cancel();
  }
}
