import 'dart:io';
import 'package:dio/io.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart' as getx;
import 'package:dio/dio.dart';
import 'package:wgshare/common/api/retrofit_client.dart';
import 'package:wgshare/common/config/request_config.dart';
import 'package:wgshare/common/store/user_store.dart';
import 'package:wgshare/utils/anti_shake_throttling.dart';
import 'package:wgshare/utils/routeUtil.dart';
import 'package:wgshare/utils/storage.dart';
import 'package:wgshare/utils/toast_utils.dart';
import 'package:wgshare/routes/app_routes.dart';
import 'package:package_info_plus/package_info_plus.dart';

class RequestTool {
  static late Dio _dio;
  // 初始化请求配置
  static _init() {
    // 自定义 HttpClient
    final httpClient = HttpClient()..maxConnectionsPerHost = 12; // 设置每个主机的最大连接数

    BaseOptions options = BaseOptions(
      baseUrl: RequestConfig().baseUrl,
      connectTimeout: const Duration(milliseconds: RequestConfig.connectTimeout),
      receiveTimeout: const Duration(milliseconds: RequestConfig.receiveTimeout),
    );
    _dio = Dio(options)..httpClientAdapter = IOHttpClientAdapter(createHttpClient: () => httpClient);
    _dio.interceptors.add(AuthInterceptor()); // 添加 token
    _dio.interceptors.add(ResponseHandle()); // 添加 数据返回拦截
    _dio.interceptors.add(TheError()); // 添加 数据返回拦截
    const isProd = bool.fromEnvironment('dart.vm.product');
    if (!isProd && RequestConfig.requestDataPrinting) {
      _dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true)); //添加日志
    }

    return RetrofitClient(_dio, baseUrl: RequestConfig().baseUrl);
  }

  final RetrofitClient _client;
  static RequestTool? _instance;

  RequestTool._internal(this._client);

  static get instance {
    if (_instance == null) {
      RetrofitClient client = _init();
      _instance = RequestTool._internal(client);
    }
    return _instance!;
  }

  // DIO
  Dio getDio() => _dio;

  RetrofitClient getClient() => _client;
}

/*
*
*AuthInterceptor
*添加header认证
* */
class AuthInterceptor extends Interceptor {
  @override
  onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    //获取app版本
    PackageInfo packageInfo = await PackageInfo.fromPlatform();

    String version = packageInfo.version;
    // ignore: non_constant_identifier_names
    String PLATFORM = "android"; //可根据代码进行判断
    if (Platform.isIOS) {
      PLATFORM = "ios";
    } else if (Platform.isAndroid) {
      PLATFORM = "android";
    } else if (Platform.isWindows) {
      PLATFORM = "Windows";
    } else if (Platform.isMacOS) {
      PLATFORM = "macos";
    } else if (Platform.isLinux) {
      PLATFORM = "Linux";
    }

    Map<String, String> headers = {};
    headers["Accept-Charset"] = "utf-8";
    headers["Connection"] = "keep-alive";
    headers["Accept"] = "*/*";
    headers["x-version"] = version; //自己更改配置
    headers["x-platform"] = PLATFORM;
    headers["Content-Type"] = "application/json";
    //获取存储数据 保存header token
    String? token = UserStore.to.token;
    if (token?.isNotEmpty ?? false) {
      headers["Authorization"] = 'Bearer $token'; //添加自己项目中的请求头 进行保存
    }
    options.headers = headers;
    return super.onRequest(options, handler);
  }
}

/*
 * ResponseHandle
 * 监听返回响应
 **/
class ResponseHandle extends Interceptor {
  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    int? statusCode = response.statusCode;
    var data = response.data;

    var flag = data != null &&
        ((data['code'] != null && (data['code'] == 401 || data['code'] == '401')) ||
            (data['Code'] != null && (data['Code'] == 401 || data['Code'] == '401')));

    if ((statusCode == 401 || flag) && RouteUtil.getRoute() != Routes.loginPage) {
      easyThrottle("toLogin",(){
        UserStore.to.erase();
        getx.Get.offAllNamed(Routes.loginPage);
      });
    }

    if(data['code'] != 200){
      ToastUtils.showError(data['message']);
    }

    super.onResponse(response, handler);
  }
}

class TheError extends Interceptor {
  // late getx.Rx<UserInfoDetail?> userInfo = UserStore.to.userDetailInfo;

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    var message = '请求错误，请重试';

    switch (err.type) {
      case DioExceptionType.connectionTimeout:
        message = '请求链接超时';
        break;
      case DioExceptionType.badCertificate:
        message = '证书错误，清联系管理员';
        break;
      case DioExceptionType.sendTimeout:
        message = '请求发送超时';
        break;
      case DioExceptionType.receiveTimeout:
        message = '接收超时时发生';
        break;
      case DioExceptionType.badResponse:
        if (err.response == null) {
          debugPrint('wgs输出===：请求进入异常但是请求response');
        } else {
          Response? response = err.response;
          if (response != null) {
            int? statusCode = response.statusCode;

            var errorMap = response.data;
            // var runtimeType = errorMap.runtimeType;
            if (errorMap is Map && errorMap['error'] != null) {
              message = errorMap['error']?['message'] ?? '请求错误，请重试';
            } else {
              if (statusCode != null) {
                switch (statusCode) {
                  case 401:
                    message = '用户登录失效，请重新登录';
                    if(RouteUtil.getRoute() != Routes.loginPage){
                      easyThrottle("toLogin",(){
                        UserStore.to.erase();
                        getx.Get.offAllNamed(Routes.loginPage);
                      });
                    }
                    break;
                  case 404:
                    message = '无效地址';

                    break;
                  default:
                }
              }
            }
          }
        }
        break;
      case DioExceptionType.cancel:
        message = '请求已取消';
        break;
      case DioExceptionType.connectionError:
        message = '当前无网络，请重试';
        break;
      default:
        message = '请求错误';
    }
    /* if (message == '用户登录失效，请重新登录' && userInfo.value?.id == null) {
      return handler.next(error);
    }*/

    ToastUtils.showError(message);
    return handler.next(err);
  }
}
