import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';

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

import 'BaseEntity.dart';
import 'DioLogInterceptor.dart';
import 'NetworkConfig.dart';

enum RequestMethod {
  Post,
  Get,
}

const RequestMethodValues = {
  RequestMethod.Get: "GET",
  RequestMethod.Post: "POST",
};

class RequestCenter {
  factory RequestCenter() => _getInstance();

  static RequestCenter get instance => _getInstance();
  static RequestCenter? _instance;

  static String signKey = "5159d59637fe1b79ba789e87443e8282";

  Dio? _dio, _dioLog;

  final dio = Dio();

  void setupDio() {
    dio.options.baseUrl = 'https://api.gptsapi.net/v1';
    dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) {
        // 可以在这里添加其他请求配置
        return handler.next(options);
      },
      onResponse: (response, handler) {
        // 处理响应
        return handler.next(response);
      },
      onError: (DioError e, handler) {
        // 处理错误
        return handler.next(e);
      },
    ));
  }

  RequestCenter._internal() {
    setup();
    setupDio();
  }

  static RequestCenter _getInstance() {
    _instance ??= RequestCenter._internal();
    //域名不一致，重新初始化
    if (_instance!._dio != null &&
        NetworkConfig.ServerDomain_Online != _instance!._dio!.options.baseUrl) {
      _instance!._dio!.options.baseUrl = NetworkConfig.ServerDomain_Online;
    }
    return _instance!;
  }

  void setup() {
    // 初始化
    if (null == _dio) {
      _dio = Dio(BaseOptions(
          baseUrl: NetworkConfig.ServerDomain_Online,
          sendTimeout: const Duration(seconds: 10),
          receiveTimeout: const Duration(seconds: 20),
          connectTimeout: const Duration(seconds: 20),
          contentType: Headers.jsonContentType,
          responseType: ResponseType.json));
      //_dio!.interceptors.add(DioLogInterceptor());
      /* _dio.interceptors.add(new ResponseInterceptors());*/
      _dioLog = Dio(BaseOptions(
          sendTimeout: const Duration(seconds: 10),
          receiveTimeout: const Duration(seconds: 20),
          connectTimeout: const Duration(seconds: 20),
          contentType: Headers.jsonContentType,
          responseType: ResponseType.json));
      //_dioLog!.interceptors.add(DioLogInterceptor());
    }
  }

  // 网络请求默认为post
  Future<BaseEntity?> request(
      path,
      Map<Object, dynamic> parmeters,
      Function(BaseEntity dataEntity) success,
      Function(ErrorEntity errorEntity) error,
      {RequestMethod? method}) async {
    try {
      //FormData formData = FormData.fromMap(parmeters);
      Response response = await _dio!.post(path, data: parmeters);
      BaseEntity entity = BaseEntity.fromJson(response.data);
      success(entity);
      return entity;
    } catch (e) {
      error(ErrorEntity(code: -1, message: "Network Anomaly"));
      return null;
    }
  }

  Future<BaseEntity?> sendRequest(
      Map<Object, dynamic> parmeters,
      Function(BaseEntity dataEntity) success,
      Function(ErrorEntity errorEntity) error,
      ) async {
    try {
      print('Request: $parmeters');
      final response = await dio.post('/messages',
          data: parmeters,
          options: Options(
            contentType: Headers.jsonContentType,
            responseType: ResponseType.json,
            headers: {
              'x-api-key':
                  'sk-V6d51cc6aa28906caecb7f22803d92ae3f18cfeb799nh4mc',
              'anthropic-version': "2023-06-01"
            },
          ));
      print('Response: ${response.data}');
      BaseEntity entity = BaseEntity.fromJson(response.data);
      success(entity);
      return entity;
    } on DioError catch (e) {
      print('Error: ${e.response?.data}');
    }
  }



  //特殊处理网络请求默认为post
  Future<BaseEntity?> request1(
      path,
      Map<String, dynamic> parmeters,
      Function(BaseEntity dataEntity) success,
      Function(ErrorEntity errorEntity) error,
      {RequestMethod? method}) async {
    Map<String, dynamic> headers = {
      "AppId": NetworkConfig.AppId,
      "userId": NetworkConfig.userId,
      "Version": NetworkConfig.Version,
      "Language": NetworkConfig.Language
    };
    parmeters.addAll(headers);
    Map<String, dynamic> parmetersSign = sign(parmeters);
    try {
      /*由于服务器是表单结构*/
      FormData formData = FormData.fromMap(parmetersSign);
      Response response = await _dio!.post(path, data: formData);
      if (response != null && response.statusCode == 200) {
        BaseEntity entity = BaseEntity.fromJson(response.data);
        success(entity);
        return entity;
      } else {
        error(ErrorEntity(code: -1, message: "Network Anomaly"));
        return null;
      }
    } catch (e) {
      error(ErrorEntity(code: -1, message: "Network Anomaly"));
      return null;
    }
  }

  Future<BaseEntity?> requestLog(
      path,
      Map<String, dynamic> parmeters,
      Function(BaseEntity dataEntity) success,
      Function(ErrorEntity errorEntity) error,
      {RequestMethod? method}) async {
    Map<String, dynamic> headers = {
      "AppId": NetworkConfig.AppId,
      /*"BossId": NetworkConfig.BossId,*/
      "userId": NetworkConfig.userId,
      "Version": NetworkConfig.Version,
      "Language": NetworkConfig.Language
    };
    parmeters.addAll(headers);
    Map<String, dynamic> parmetersSign = sign(parmeters);
    try {
      /*由于服务器是表单结构*/
      FormData formData = FormData.fromMap(parmetersSign);
      Response response = await _dioLog!.post(path, data: formData);
      if (response != null && response.statusCode == 200) {
        BaseEntity entity = BaseEntity.fromJson(response.data);
        success(entity);
        return entity;
      } else {
        error(ErrorEntity(code: -1, message: "Network Anomaly"));
        return null;
      }
    } catch (e) {
      error(ErrorEntity(code: -1, message: "Network Anomaly"));
      return null;
    }
  }

  // 网络请求默认为post
  Future<BaseEntity?> requestPay(
      path,
      Map<String, dynamic> parmeters,
      Function(BaseEntity dataEntity) success,
      Function(ErrorEntity errorEntity) error,
      {RequestMethod? method}) async {
    Map<String, dynamic> headers = {
      "AppId": NetworkConfig.AppId,
      /*"BossId": NetworkConfig.BossId,*/
      "userId": NetworkConfig.userId,
      "Version": NetworkConfig.Version,
      "Language": NetworkConfig.Language
    };
    parmeters.addAll(headers);
    Map<String, dynamic> parmetersSign = sign(parmeters);
    try {
      FormData formData = FormData.fromMap(parmetersSign);
      Response response = await _dio!.post(path, data: formData);
      if (response != null && response.statusCode == 200) {
        BaseEntity entity = BaseEntity.fromJson(response.data);
        success(entity);
        return entity;
      } else {
        error(ErrorEntity(code: -1, message: "未知错误"));
        return null;
      }
    } catch (e) {
      ErrorEntity(code: -1, message: "未知错误");
      return null;
    }
  }

  // 网络请求默认为post
  Future<BaseEntity?> requestComfyUI1(
      formData,
      Function(BaseEntity dataEntity) success,
      Function(ErrorEntity errorEntity) error,
      {RequestMethod? method}) async {
    try {
      var response = await _dio!.post(
        "http://192.168.1.103:8188${NetworkConfig.uploadImg}",
        data: formData,
        options: Options(
          contentType: Headers.jsonContentType,
          responseType: ResponseType.json,
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        ),
      );
      if (response.statusCode == 200) {
        BaseEntity entity = BaseEntity.PlayfromComfyUi(response.data);
        success(entity);
        return entity;
      }
    } catch (e) {
      print("e" + e.toString());
      //error(ErrorEntity(code: -1, message: "Network Anomaly"));
      return null;
    }
  }

  Future<BaseEntity?> requestComfyUI2(
      formData,
      Function(BaseEntity dataEntity) success,
      Function(ErrorEntity errorEntity) error,
      {RequestMethod? method}) async {
    try {
      var response = await _dio!.post(
        "http://192.168.1.103:8188${NetworkConfig.prompt}",
        data: formData,
        options: Options(
          contentType: Headers.jsonContentType,
          responseType: ResponseType.json,
        ),
      );
      if (response.statusCode == 200) {
        BaseEntity entity = BaseEntity.PlayfromComfyUi(response.data);
        success(entity);
        return entity;
      }
    } catch (e) {
      print("e" + e.toString());
      //error(ErrorEntity(code: -1, message: "Network Anomaly"));
      return null;
    }
  }

  // 网络请求默认为post (网页)
  Future<BaseEntity?> requestWeb(
      path,
      Map<String, dynamic> parmeters,
      Function(BaseEntity dataEntity) success,
      Function(ErrorEntity errorEntity) error,
      {RequestMethod? method}) async {
    Map<String, dynamic> headers = {
      "AppId": NetworkConfig.AppId,
      /*"BossId": NetworkConfig.BossId,*/
      "UserId": NetworkConfig.userId,
      "Version": NetworkConfig.Version,
      "Language": NetworkConfig.Language
    };
    parmeters.addAll(headers);
    //签名加密
    Map<String, dynamic> parmetersSign = sign(parmeters);
    try {
      /*由于服务器是表单结构*/
      FormData formData = FormData.fromMap(parmetersSign);
      Response response = await _dio!.post(path, data: formData);
      if (response != null && response.statusCode == 200) {
        BaseEntity entity = BaseEntity.fromJson(response.data);
        Map<String, dynamic> parmeters = {
          "AppId": NetworkConfig.AppId,
          /*"BossId": NetworkConfig.BossId,*/
          "UserId": NetworkConfig.userId,
          "Token": entity.message
        };
        Map<String, dynamic> p1 = sign(parmeters);
        parmeters.addAll(p1);
        //data 信息添加用户信息
        entity.data = gettoken(parmeters);
        success(entity);

        return entity;
      } else {
        error(ErrorEntity(code: -1, message: "Network Anomaly"));
        return null;
      }
    } catch (e) {
      ErrorEntity(code: -1, message: "Network Anomaly");
      return null;
    }
  }

  // 捕获异常的错误信息
  ErrorEntity _getErrorMsg(DioError error) {
    switch (error.type) {
      case DioErrorType.cancel:
        {
          return ErrorEntity(code: -1, message: "请求取消");
        }
        break;
      case DioErrorType.connectionTimeout:
        {
          return ErrorEntity(code: -1, message: "连接超时");
        }
        break;
      case DioErrorType.sendTimeout:
        {
          return ErrorEntity(code: -1, message: "请求超时");
        }
        break;
      case DioErrorType.receiveTimeout:
        {
          return ErrorEntity(code: -1, message: "响应超时");
        }
        break;
      case DioErrorType.badResponse:
        {
          try {
            int errCode = error.response!.statusCode!;
            String errorMsg = error.response!.statusMessage!;
            return ErrorEntity(code: errCode, message: errorMsg);
          } on Exception catch (_) {
            return ErrorEntity(code: -1, message: "Network Anomaly");
          }
        }
        break;
      default:
        {
          return ErrorEntity(code: -1, message: "Network Anomaly");
        }
    }
  }

  Map<String, dynamic> sign(Map<String, dynamic> parmeters) {
    List<String> keys = parmeters.keys.toList();
    // key排序
    keys.sort((a, b) {
      List<int> al = a.codeUnits;
      List<int> bl = b.codeUnits;
      for (int i = 0; i < al.length; i++) {
        if (bl.length <= i) return 1;
        if (al[i] > bl[i]) {
          return 1;
        } else if (al[i] < bl[i]) return -1;
      }
      return 0;
    });
    Map<String, dynamic> treeMap = Map();
    keys.forEach((element) {
      treeMap[element] = parmeters[element];
    });
    String data = "";
    for (dynamic str in treeMap.values) {
      if (str != null) {
        data = data + str.toString();
      }
    }
    treeMap["sign"] = generateMd5(data + NetworkConfig.userToken);
    return treeMap;
  }

  String gettoken(Map<String, dynamic> parmeters) {
    List<String> keys = parmeters.keys.toList();
    // key排序
    keys.sort((a, b) {
      List<int> al = a.codeUnits;
      List<int> bl = b.codeUnits;
      for (int i = 0; i < al.length; i++) {
        if (bl.length <= i) return 1;
        if (al[i] > bl[i]) {
          return 1;
        } else if (al[i] < bl[i]) return -1;
      }
      return 0;
    });
    Map<String, dynamic> treeMap = Map();
    keys.forEach((element) {
      treeMap[element] = parmeters[element];
    });
    String data = "";
    treeMap.forEach((key, value) {
      if (data == "") {
        data = key + "=" + value.toString();
      } else {
        data = data + "&" + key + "=" + value.toString();
      }
    });
    return data;
  }

  String generateMd5(String data) {
    return md5.convert(utf8.encode(data)).toString();
  }
}
