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

import 'package:dio/dio.dart';
import 'package:dio/io.dart';

// import 'package:flutter_easyloading/flutter_easyloading.dart';  // 已替换为自定义组件
import 'package:flutter_loggy_dio/flutter_loggy_dio.dart';

import 'package:kaer_with_panels/app/common/app_config.dart';
import 'package:kaer_with_panels/app/common/app_run_data.dart';
import 'package:kaer_with_panels/app/network/base_response.dart';
import 'package:kaer_with_panels/app/localization/kr_language_utils.dart';
import 'package:kaer_with_panels/app/utils/kr_common_util.dart';
import 'package:kaer_with_panels/app/services/singbox_imp/kr_sing_box_imp.dart';
import 'package:kaer_with_panels/app/services/kr_site_config_service.dart';
import 'package:kaer_with_panels/app/utils/kr_http_adapter_util.dart';
import 'package:kaer_with_panels/singbox/model/singbox_status.dart';

// import 'package:crypto/crypto.dart';
// import 'package:encrypt/encrypt.dart';

import 'package:loggy/loggy.dart';

import '../utils/kr_aes_util.dart';
import '../utils/kr_log_util.dart';

// import 'package:video/app/utils/common_util.dart';
// import 'package:video/app/utils/log_util.dart';

/// 定义请求方法的枚举
enum HttpMethod { GET, POST, DELETE, PUT }

/// 封装请求
class HttpUtil {
  final Dio _dio = Dio();
  static final HttpUtil _instance = HttpUtil._internal();

  HttpUtil._internal() {
    initDio();
  }

  factory HttpUtil() => _instance;

  static HttpUtil getInstance() {
    return _instance;
  }

  /// 对dio进行配置
  void initDio() {
    KRLogUtil.kr_i('🚀 HttpUtil.initDio() 开始初始化', tag: 'HttpUtil');
    // 不使用 Loggy，改用自定义简洁拦截器
    _dio.interceptors.add(_KRSimpleHttpInterceptor(_dio));
    _dio.options.baseUrl = AppConfig.getInstance().baseUrl;

    // 设置连接超时时间
    _dio.options.connectTimeout = const Duration(seconds: 60);
    _dio.options.receiveTimeout = const Duration(seconds: 60);
    _dio.options.sendTimeout = const Duration(seconds: 60);

    // 设置请求头
    _dio.options.headers = {
      'Accept': 'application/json',
      'Content-Type': 'application/json; charset=UTF-8',
      // 移除固定的UserAgent，使用动态的
    };

    // 设置响应类型
    _dio.options.responseType = ResponseType.json;

    // 设置验证状态
    _dio.options.validateStatus = (status) {
      return status != null && status >= 200 && status < 500;
    };

    // 🔧 配置HttpClientAdapter 优先走本地 sing-box mixed 端口，
    // 若代理不可用则回推到直连
    KRLogUtil.kr_i('🔧 配置 HttpClientAdapter...', tag: 'HttpUtil');
    _dio.httpClientAdapter = KRHttpAdapterUtil.createAdapter(
      useSingBoxProxy: true,
      timeout: const Duration(seconds: 10),
    );
    KRLogUtil.kr_i('✅ HttpUtil.initDio() 初始化完成', tag: 'HttpUtil');
  }

  /// 更新baseUrl
  void updateBaseUrl() {
    String newBaseUrl = AppConfig.getInstance().baseUrl;
    if (_dio.options.baseUrl != newBaseUrl) {
      KRLogUtil.kr_i('🔄 更新baseUrl: ${_dio.options.baseUrl} -> $newBaseUrl',
          tag: 'HttpUtil');
      _dio.options.baseUrl = newBaseUrl;
    }
  }

  /// 初始化请求头 ：signature签名字符串
  Map<String, dynamic> _initHeader(
      String signature, String? userId, String? token) {
    Map<String, dynamic> map = <String, dynamic>{};

    if (KRAppRunData().kr_isLogin.value == true) {
      map["Authorization"] = KRAppRunData().kr_token;
    }

    // 添加语言请求头
    map["lang"] = KRLanguageUtils.getCurrentLanguageCode();
    map['Login-Type'] = 'device';

    // 添加动态UserAgent头
    map["User-Agent"] = _kr_getUserAgent();

    return map;
  }

  /// 获取当前系统的 user_agent
  String _kr_getUserAgent() {
    if (Platform.isAndroid) {
      return 'android';
    } else if (Platform.isIOS) {
      return 'ios';
    } else if (Platform.isMacOS) {
      return 'mac';
    } else if (Platform.isWindows) {
      return 'windows';
    } else if (Platform.isLinux) {
      return 'linux';
    } else if (Platform.isFuchsia) {
      return 'harmony';
    } else {
      return 'unknown';
    }
  }

  /// request请求:T为转换的实体类， path：请求地址，query：请求参数, method: 请求方法, isShowLoading(可选): 是否显示加载中的状态,默认true显示, false为不显示, silentInvite: 是否为静默邀请
  Future<BaseResponse<T>> request<T>(String path, Map<String, dynamic> params,
      {HttpMethod method = HttpMethod.POST,
      bool isShowLoading = true,
      bool isSilentInvite = false}) async {
    try {
      // 每次请求前更新baseUrl，确保使用最新的域名
      updateBaseUrl();

      if (isShowLoading) {
        KRCommonUtil.kr_showLoading();
      }

      var map = <String, dynamic>{};
      final plainText = jsonEncode(params);
      map = KRAesUtil.encryptData(plainText, AppConfig.kr_encryptionKey);

      // 初始化请求头
      final headers = _initHeader('signature', 'userId', 'token');
      if (isSilentInvite) {
        headers['X-Client-Mode'] = 'invite_silent';
      }

      final options = Options(
        contentType: "application/json",
        headers: headers,
        extra: {'silentInvite': isSilentInvite},
      );

      Response<Map<String, dynamic>> responseTemp;
      if (method == HttpMethod.GET) {
        responseTemp = await _dio.get<Map<String, dynamic>>(
          path,
          queryParameters: map,
          options: options,
        );
      } else if (method == HttpMethod.DELETE) {
        responseTemp = await _dio.delete<Map<String, dynamic>>(
          path,
          data: map,
          options: options,
        );
      } else if (method == HttpMethod.PUT) {
        responseTemp = await _dio.put<Map<String, dynamic>>(
          path,
          data: map,
          options: options,
        );
      } else {
        responseTemp = await _dio.post<Map<String, dynamic>>(
          path,
          data: map,
          options: options,
        );
      }

      if (isShowLoading) {
        KRCommonUtil.kr_hideLoading();
      }

      return BaseResponse<T>.fromJson(responseTemp.data!);
    } on DioException catch (err) {
      if (isShowLoading) {
        KRCommonUtil.kr_hideLoading();
      }

      int code = -90000;
      String msg = "";
      msg = err.message ?? err.type.toString();
      switch (err.type) {
        case DioExceptionType.connectionTimeout:
          code = -90001;
          break;
        case DioExceptionType.sendTimeout:
          code = -90002;
          break;
        case DioExceptionType.receiveTimeout:
          code = -90003;
          break;
        case DioExceptionType.badResponse:
          code = err.response?.statusCode ?? -90004;
          break;
        case DioExceptionType.cancel:
          break;
        case DioExceptionType.connectionError:
          code = -90006;
          break;
        case DioExceptionType.badCertificate:
          code = -90007;
          break;
        default:
          if (err.error != null) {
            if (err.error.toString().contains("Connection reset by peer")) {
              code = -90008;
            }
          }
      }
      print('err.type ${err.type}');
      if (err.type == DioExceptionType.unknown) {
        final _pathOnly = (err.requestOptions.path.isNotEmpty)
            ? err.requestOptions.path
            : err.requestOptions.uri.path;
        msg = '${msg.isNotEmpty ? msg : 'unknown'} ($_pathOnly)';
        final _ua =
            (err.requestOptions.extra['__unknown_attempts'] as int?) ?? 0;
        final bool isSilent = err.requestOptions.extra['silentInvite'] ?? false;
        if (_ua >= 2 && !isSilent) {
          KRCommonUtil.kr_showToast('请求失败（$_pathOnly）', timeout: 3500);
        }
      }
      return BaseResponse<T>.fromJson(
          {'code': code, 'msg': msg, 'data': <String, dynamic>{}});
    } catch (e) {
      if (isShowLoading) {
        KRCommonUtil.kr_hideLoading();
      }
      return BaseResponse<T>.fromJson({
        'code': -90000,
        'msg': '${e.toString()} (${path})',
        'data': <String, dynamic>{}
      });
    }
  }
}

/// 自定义简洁 HTTP 拦截器（无边框符号）
class _KRSimpleHttpInterceptor extends Interceptor {
  /// 常量：手动控制是否打印拦截器日志与解密结果
  static const bool KR_HTTP_PRINT = true;
  final Dio _dio;
  _KRSimpleHttpInterceptor(this._dio);
  static String? _lastPath;
  static int _lastTsMs = 0;
  @override

  /// 请求拦截器
  ///
  /// 功能：在调试模式下优先打印请求的解密明文；若解密失败则打印原始数据并标识失败。
  /// 参数：
  /// - options: 请求选项（包含 data 与 queryParameters）
  /// - handler: 拦截器处理器
  /// 返回：void
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    if (KR_HTTP_PRINT) {
      print('>>> Request │ ${options.method} │ ${options.uri}');
    }
    if (KR_HTTP_PRINT) {
      Map<String, dynamic>? m;
      if (options.data is Map<String, dynamic>) {
        m = options.data as Map<String, dynamic>;
      } else if (options.queryParameters.isNotEmpty) {
        m = options.queryParameters;
      }
      if (m != null) {
        final decrypted = _tryDecryptFromMap(m);
        _printDecryptedOrFallback(
            phase: 'Request', raw: m, decrypted: decrypted);
      }
    }
    handler.next(options);
  }

  @override

  /// 响应拦截器
  ///
  /// 功能：在调试模式下优先打印响应的解密明文；若解密失败则打印原始数据并标识失败。
  /// 参数：
  /// - response: 响应对象（优先识别 Map 格式）
  /// - handler: 拦截器处理器
  /// 返回：void
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    if (KR_HTTP_PRINT) {
      print(
          '<<< Response │ ${response.requestOptions.method} │ ${response.statusCode} ${response.statusMessage} │ ${response.requestOptions.uri}');
    }
    if (KR_HTTP_PRINT && response.data is Map<String, dynamic>) {
      final dataMap = response.data as Map<String, dynamic>;
      String? decrypted = _tryDecryptFromMap(dataMap);
      if (decrypted == null && dataMap['data'] is Map<String, dynamic>) {
        decrypted = _tryDecryptFromMap(dataMap['data'] as Map<String, dynamic>);
      }
      _printDecryptedOrFallback(
          phase: 'Response', raw: dataMap, decrypted: decrypted);
    }
    handler.next(response);
  }

  @override

  /// 错误拦截器
  ///
  /// 功能：打印错误信息并保持原有的 Unknown 错误重试与失败提示去重逻辑。
  /// 参数：
  /// - err: Dio 错误对象
  /// - handler: 拦截器处理器
  /// 返回：void
  void onError(DioException err, ErrorInterceptorHandler handler) {
    if (KR_HTTP_PRINT) {
      print(
          '<<< Error │ ${err.requestOptions.method} │ ${err.requestOptions.uri}');
    }
    if (KR_HTTP_PRINT) {
      print('Error Type: ${err.type}');
    }
    if (err.message != null) {
      if (KR_HTTP_PRINT) {
        print('Error Message: ${err.message}');
      }
    }
    if (err.response?.data != null) {
      if (KR_HTTP_PRINT) {
        print('Response Data: ${err.response?.data}');
      }
    }
    if (err.type == DioExceptionType.unknown) {
      final path = (err.requestOptions.path.isNotEmpty)
          ? err.requestOptions.path
          : err.requestOptions.uri.path;
      int unknownAttempts =
          (err.requestOptions.extra['__unknown_attempts'] as int?) ?? 0;
      if (unknownAttempts < 2) {
        err.requestOptions.extra['__unknown_attempts'] = unknownAttempts + 1;
        final delayMs = unknownAttempts == 0 ? 300 : 700;
        Future.delayed(Duration(milliseconds: delayMs)).then((_) async {
          final start = DateTime.now();
          while (!KRSingBoxImp.instance.kr_isProxyReady &&
              DateTime.now().difference(start) < const Duration(seconds: 1)) {
            await Future.delayed(const Duration(milliseconds: 100));
          }
          try {
            final Response<dynamic> r =
                await _dio.fetch<dynamic>(err.requestOptions);
            handler.resolve(r);
          } catch (e) {
            handler.next(e is DioException
                ? e
                : DioException(requestOptions: err.requestOptions, error: e));
          }
        });
        return;
      } else {
        final now = DateTime.now().millisecondsSinceEpoch;
        final bool isSilent = err.requestOptions.extra['silentInvite'] ?? false;
        if (!(_lastPath == path && (now - _lastTsMs) < 2000) && !isSilent) {
          _lastPath = path;
          _lastTsMs = now;
          KRCommonUtil.kr_showToast('请求失败（$path）', timeout: 3500);
        }
        KRLogUtil.kr_e('请求失败（$path）',
            tag: 'HttpUtil', error: err, stackTrace: err.stackTrace);
      }
    }
    handler.next(err);
  }

  /// 尝试从 Map 中解密，若存在 data/time 字段则返回明文，否则返回 null
  String? _tryDecryptFromMap(Map<String, dynamic> m) {
    final data = m['data'];
    final time = m['time'];
    if (data is String && time is String) {
      try {
        return KRAesUtil.decryptData(data, time, AppConfig.kr_encryptionKey);
      } catch (_) {
        return null;
      }
    }
    return null;
  }

  /// 将字符串尽量按 JSON 缩进格式化，失败时返回原文
  String _prettyPrintJson(String s) {
    try {
      final jsonData = jsonDecode(s);
      return JsonEncoder.withIndent('  ').convert(jsonData);
    } catch (_) {
      return s;
    }
  }

  /// 统一输出逻辑：成功仅打印解密明文；失败打印失败标识与原文
  void _printDecryptedOrFallback({
    required String phase,
    required Object? raw,
    required String? decrypted,
  }) {
    if (!KR_HTTP_PRINT) return;
    if (decrypted != null) {
      print('🔓 $phase 明文:');
      print(_prettyPrintJson(decrypted));
    } else {
      print('⚠️ $phase 解密失败');
      print('原文:');
      if (raw is Map<String, dynamic>) {
        try {
          print(JsonEncoder.withIndent('  ').convert(raw));
        } catch (_) {
          print(raw.toString());
        }
      } else {
        print(raw?.toString() ?? 'null');
      }
    }
  }
}
