import 'dart:convert';
import 'package:archive/archive.dart';
import 'package:dio/dio.dart';
import 'package:get/get.dart' as getx;
import '../../data/sp/ix_sp.dart';
import '../../../utils/developer/ix_developer_tools.dart';

import '../../../utils/log/logger.dart';
import '../../../utils/crypto.dart';
import '../../components/country_restricted_overlay.dart';
import '../../constants/errors.dart';
import '../../constants/keys.dart';
import '../../data/models/api_exception.dart';
import '../../data/models/api_result.dart';
import '../../data/models/disconnect_domain.dart';
import '../../data/models/launch/user.dart';
import '../../routes/app_pages.dart';
import '../base/base_api.dart';

import 'api_core_paths.dart';

/// 核心API
class ApiCore extends BaseApi {
  static final _instance = ApiCore._internal();

  factory ApiCore() => _instance;

  ApiCore._internal() {
    _initDio();
  }

  /// 初始化Dio
  void _initDio() {
    // 此处可以设置默认的DIO参数
    final options = BaseOptions();
    options.connectTimeout = const Duration(seconds: 15);
    options.receiveTimeout = const Duration(seconds: 15);
    options.responseType = ResponseType.bytes;
    options.headers['content-type'] = 'application/json';
    options.followRedirects = true;
    options.maxRedirects = 5;
    dio = Dio(options);
    // 添加拦截器
    _setupInterceptors();

    dio.interceptors.add(SimpleApiMonitorInterceptor());

    // 添加重试拦截器
    // dio.interceptors.add(RetryInterceptor());
  }

  bool _isRefreshing = false;

  void _setupInterceptors() {
    dio.interceptors.add(
      InterceptorsWrapper(
        onRequest: (options, handler) {
          // 在请求发送前添加token
          final user = IXSP.getUser();
          if (user != null) {
            options.headers['Authorization'] = user.accessToken;
          }
          return handler.next(options);
        },
        onError: (DioException error, handler) async {
          IXSP.addDisconnectDomain(
            DisconnectDomain(
              domain: error.requestOptions.baseUrl,
              status: error.response?.statusCode ?? -1,
              msg: error.message ?? '',
              startTime: DateTime.now().millisecondsSinceEpoch,
              endTime: DateTime.now().millisecondsSinceEpoch,
              count: 1,
            ),
          );
          if (error.response?.statusCode == Errors.eRegionNotAvailable) {
            // 403 eRegionNotAvailable 当前区域不可用
            // 这里可以发送事件通知UI层处理
            IXSP.setLastIsRegionDisabled(true);
            getx.Get.offAll(
              () => const CountryRestrictedOverlay(type: RestrictedType.region),
              transition: getx.Transition.fadeIn,
            );
            return handler.reject(error);
          } else if (error.response?.statusCode == Errors.eDeviceRestricted) {
            // 423 eDeviceRestricted 当前设备被禁用
            // 这里可以发送事件通知UI层处理
            IXSP.setLastIsDeviceDisabled(true);
            getx.Get.offAll(
              () => const CountryRestrictedOverlay(type: RestrictedType.device),
              transition: getx.Transition.fadeIn,
            );
            return handler.reject(error);
          } else if (error.response?.statusCode == Errors.eUserDisabled) {
            // 424 eUserDisabled 当前用户被禁用
            // 这里可以发送事件通知UI层处理
            IXSP.setLastIsUserDisabled(true);
            getx.Get.offAll(
              () => CountryRestrictedOverlay(
                type: RestrictedType.user,
                onPressed: () async {
                  await IXSP.clearLaunchData();
                  getx.Get.offAllNamed(Routes.SPLASH);
                },
              ),
              transition: getx.Transition.fadeIn,
            );
            return handler.reject(error);
          } else if (error.response?.statusCode == Errors.eTokenExpired) {
            // 401 eTokenExpired token实效
            // token实效，刷新token
            RequestOptions originalRequest = error.requestOptions;

            try {
              final token = await _refreshToken(originalRequest);
              if (token != null) {
                // 使用新token重试原始请求
                final response = await _retryRequest(originalRequest, token);
                return handler.resolve(response);
              }
            } catch (e) {
              // Token刷新失败，可能需要重新登录
              // 这里可以发送事件通知UI层处理登录过期
              /// 退出跳转到登录页
              await IXSP.clearLaunchData();
              getx.Get.offAllNamed(Routes.SPLASH);
              return handler.reject(error);
            }
          }
          return handler.next(error);
        },
      ),
    );
  }

  Future<String?> _refreshToken(RequestOptions originalRequest) async {
    if (_isRefreshing) {
      return await Future.delayed(const Duration(seconds: 1), () async {
        return _refreshToken(originalRequest);
      });
    }

    _isRefreshing = true;

    try {
      final user = IXSP.getUser();
      if (user == null) return null;

      final tokenDio = Dio(dio.options);
      final response = await tokenDio.post(
        ApiCorePaths.refreshToken,
        options: Options(
          headers: {
            'Authorization': user.refreshToken,
            'X-NL-Product-Code': 'nomo',
            'X-NL-Content-Encoding': 'gzip',
          },
        ),
        data: originalRequest.data,
      );

      if (response.statusCode == 200) {
        final result = getApiResult(decrypt(response.data));
        if (result.success) {
          final accessToken = result.data['accessToken'];
          final refreshToken = result.data['refreshToken'];
          final newUser = User(
            country: user.country,
            userIp: user.userIp,
            accessToken: accessToken,
            refreshToken: refreshToken,
            accountKey: user.accountKey,
            accountPassword: user.accountPassword,
            createTime: user.createTime,
            geographyEea: user.geographyEea,
            activated: user.activated,
            memberLevel: user.memberLevel,
            account: user.account,
          );
          await IXSP.saveUser(newUser);
          _isRefreshing = false;
          return accessToken;
        }
      }
    } catch (e) {
      _isRefreshing = false;
      rethrow;
    }

    _isRefreshing = false;
    return null;
  }

  Future<Response> _retryRequest(
    RequestOptions requestOptions,
    String newToken,
  ) async {
    final options = Options(
      method: requestOptions.method,
      headers: {...requestOptions.headers, 'Authorization': newToken},
    );

    return dio.request(
      requestOptions.path,
      data: requestOptions.data,
      queryParameters: requestOptions.queryParameters,
      options: options,
    );
  }

  @override
  Map<String, dynamic>? getDefaultHeader() {
    // 可以设置自定义Header
    final headers = {
      'X-NL-Product-Code': 'nomo',
      'X-NL-Content-Encoding': 'gzip',
    };
    return headers;
  }

  @override
  Map<String, dynamic>? getDefaultQuery() {
    // 可以设置自定义Query
    return null;
  }

  @override
  dynamic encrypt(dynamic input) {
    try {
      final data = jsonEncode(input);
      final bytes = utf8.encode(data);
      final gzipEncoder = GZipEncoder();
      final compressedBytes = gzipEncoder.encode(bytes);
      log('ApiCore', '>>: $data');
      return Crypto.encryptBytesUint8(compressedBytes, Keys.aesKey, Keys.aesIv);
    } catch (error) {
      throw ApiException("-2", "encrypt error: $error");
    }
  }

  @override
  dynamic decrypt(dynamic input) {
    try {
      final decryptedBytes = Crypto.decryptBytes(
        base64Encode(input),
        Keys.aesKey,
        Keys.aesIv,
      );
      // 使用GZip解压
      final gzipDecoder = GZipDecoder();
      final decodeBytes = gzipDecoder.decodeBytes(decryptedBytes);
      final data = utf8.decode(decodeBytes);
      log('ApiCore', '<<:$data');
      return jsonDecode(data);
    } catch (error) {
      throw ApiException("-2", "decrypt error: $error");
    }
  }

  /// 返回所有信息接口
  Future<ApiResult> launch(dynamic data) async {
    return post(ApiCorePaths.launch, data: data);
  }

  /// 注册
  Future<ApiResult> register(dynamic data) async {
    return post(ApiCorePaths.register, data: data);
  }

  /// 登录
  Future<ApiResult> login(dynamic data) async {
    return post(ApiCorePaths.login, data: data);
  }

  /// 退出登录
  Future<ApiResult> logout(dynamic data) async {
    return post(ApiCorePaths.logout, data: data);
  }

  /// 修改密码
  Future<ApiResult> changePassword(dynamic data) async {
    return post(ApiCorePaths.changePassword, data: data);
  }

  /// 忘记密码
  Future<ApiResult> forgetPassword(dynamic data) async {
    return post(ApiCorePaths.forgetPassword, data: data);
  }

  /// 忘记密码
  Future<ApiResult> forgetSendVerificationCode(dynamic data) async {
    return post(ApiCorePaths.forgetSendVerificationCode, data: data);
  }

  /// 发送验证码
  Future<ApiResult> sendVerificationCode(dynamic data) async {
    return post(ApiCorePaths.sendVerificationCode, data: data);
  }

  /// 验证验证码
  Future<ApiResult> verifyVerificationCode(dynamic data) async {
    return post(ApiCorePaths.verifyVerificationCode, data: data);
  }

  /// 激活发送验证码
  Future<ApiResult> activateSendVerificationCode(dynamic data) async {
    return post(ApiCorePaths.activateSendVerificationCode, data: data);
  }

  /// 激活账号
  Future<ApiResult> activateAccount(dynamic data) async {
    return post(ApiCorePaths.activateAccount, data: data);
  }

  /// 获取用户信息
  Future<ApiResult> getUserConfig(dynamic data) async {
    return post(ApiCorePaths.getUserConfig, data: data);
  }

  /// 获取banner
  Future<ApiResult> getBanner(dynamic data) async {
    return post(ApiCorePaths.banner, data: data);
  }

  /// 获取支持的第三方登录
  Future<ApiResult> providerList(dynamic data) async {
    return post(ApiCorePaths.providerList, data: data);
  }

  /// 第三方登录前获取登录url
  Future<ApiResult> providerLogin(dynamic data) async {
    return post(ApiCorePaths.providerLogin, data: data);
  }

  /// 第三方登录检测回调
  Future<ApiResult> providerLoginCheck(dynamic data) async {
    return post(ApiCorePaths.providerLoginCheck, data: data);
  }
}
