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

import 'package:dio/dio.dart';
import 'package:get/get.dart' as getx;
import 'package:making_school_asignment_app/common/api/retrofit_client.dart';
import 'package:making_school_asignment_app/common/config/request_config.dart';
import 'package:making_school_asignment_app/common/job/user_info.dart';
import 'package:making_school_asignment_app/common/store/user_store.dart';
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
import 'package:making_school_asignment_app/common/utils/utils.dart';
import 'package:making_school_asignment_app/routes/app_pages.dart';
import 'package:package_info_plus/package_info_plus.dart';

import '../job/user_info_detail.dart';
import '../utils/storage.dart';

class RequestTool {
  static late Dio _dio;
  // 初始化请求配置
  static _init() {
    BaseOptions options = BaseOptions(
      baseUrl: RequestConfig().baseUrl,
      connectTimeout: const Duration(milliseconds: RequestConfig.connectTimeout),
      receiveTimeout: const Duration(milliseconds: RequestConfig.receiveTimeout),
    );
    _dio = Dio(options);
    _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 RequestTool 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;
    //获取存储数据 保存header token
    String? token = UserStore.to.token;
    String? xToken = UserStore.to.xToken;
    UserInfo? userInfo = UserStore.to.userInfo.value;

    if (null != token && token.isNotEmpty) {
      headers["Authorization"] = token; //添加自己项目中的请求头 进行保存
    }

    if ((userInfo?.isExpired() ?? false) && (xToken?.isNotEmpty ?? false)) {
      headers["x-Authorization"] = xToken!;
    }

    /*  if ((userInfo?.isExpired() ?? false) && userInfo?.termYear != '') {
      headers["term-year"] = userInfo!.termYear;
    }*/

    options.headers = headers;
    return super.onRequest(options, handler);
  }
}

/*
 * ResponseHandle
 * 监听返回响应
 **/
class ResponseHandle extends Interceptor {
  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    const isProd = bool.fromEnvironment('dart.vm.product');
    if (!isProd && RequestConfig.requestDataPrinting) {
      toPrint(val: response.data, toPrintJson: true);
    }
    if (RequestConfig.successCode.contains(response.statusCode)) {
      //
      String? token = response.headers.value('access-token');
      String? xtoken = response.headers.value('x-access-token');
      if (token?.isNotEmpty ?? false) {
        UserStore.to.setToken(token!);
        var payloadBase64 = token.split('.')[1];
        final normalizedPayload = base64.normalize(payloadBase64);
        final payloadString = utf8.decode(base64.decode(normalizedPayload));
        UserStore.to.setUserInfo(UserInfo.fromJson(jsonDecode(payloadString)));
      }
      if (xtoken?.isNotEmpty ?? false) UserStore.to.setXToken(xtoken!);
    }

    super.onResponse(response, handler);
  }
}

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

  @override
  void onError(DioException error, ErrorInterceptorHandler handler) {
    var message = '请求错误，请重试';
    switch (error.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 (error.response == null) {
          print('请求进入异常但是请求response');
        } else {
          Response? response = error.response;
          if (response != null) {
            int? statusCode = response.statusCode;

            var errorMap = response.data;

            if (errorMap is String && errorMap.isNotEmpty) {
              try {
                var errorModel = jsonDecode(errorMap);
                var error = errorModel['error'];
                if (error != null && error["message"] != null) {
                  message = error["message"];
                }
              } catch (e) {}
            }
            // var runtimeType = errorMap.runtimeType;
            if (errorMap is Map && errorMap['error'] != null) {
              message = errorMap['error']?['message'] ?? '请求错误，请重试';
            } else {
              if (statusCode != null) {
                switch (statusCode) {
                  case 401:
                    message = '用户登录失效，请重新登录';

                    Future.delayed(const Duration(seconds: 2), () {
                      if (getx.Get.currentRoute != Routes.login) {
                        UserStore.to.erase();
                        StorageService.to.erase();
                        getx.Get.offAllNamed(Routes.login);
                      }
                    });
                    break;
                  case 404:
                    // message = '用户登录失效，请重新登录';
                    // Future.delayed(const Duration(seconds: 2), () => getx.Get.offAllNamed(Routes.login));
                    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);
    }
    Future.delayed(const Duration(milliseconds: 600), () => ToastUtils.showError(message));
    return handler.next(error);
  }
}
