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

import 'package:anchor_collect_flutter/api/ApiException.dart';
import 'package:anchor_collect_flutter/api/NetWorkConfig.dart';
import 'package:anchor_collect_flutter/api/TokenInterceptor.dart';
import 'package:anchor_collect_flutter/api/api_response.dart';
import 'package:anchor_collect_flutter/utils/loading.dart';
import 'package:dio/dio.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';

import 'package:pretty_dio_logger/pretty_dio_logger.dart';

class RequestClient {
  late Dio _dio;
  static final RequestClient _singletonRequestClient =
      RequestClient._internal();

  factory RequestClient() {
    return _singletonRequestClient;
  }

  RequestClient._internal() {
    ///初始化 dio 配置
    var options = BaseOptions(
        baseUrl: NetWorkConfig.baseUrl,
        connectTimeout: Duration(milliseconds: NetWorkConfig.connectTimeOut),
        receiveTimeout: Duration(milliseconds: NetWorkConfig.readTimeOut),
        sendTimeout: Duration(milliseconds: NetWorkConfig.writeTimeOut));
    _dio = Dio(options);
    _dio.interceptors.add(TokenInterceptor());
    _dio.interceptors.add(PrettyDioLogger(
        requestHeader: true,
        requestBody: true,
        responseHeader: true,
        responseBody: true));
  }

  /// dio 本身提供了get 、post 、put 、delete 等一系列 http 请求方法,最终都是调用request,直接封装request就行
  Future<T?> request<T>(
    String url, {
    required String method,
    Map<String, dynamic>? queryParameters,
    dynamic data,
    Map<String, dynamic>? headers,
    bool isshowLoading = false,
    bool Function(ApiException)? onError, //用于错误信息处理的回调
    Function(T)? onResponse,
  }) async {
    try {
      if (isshowLoading) {
        showLoading();
      }
      Options options = Options()
        ..method = method
        ..headers = headers;

      data = _convertRequestData(data);
      Response response = await _dio.request(url,
          queryParameters: queryParameters, data: data, options: options);
          dismissLoading();
      T? mdata = _handleResponse<T>(response) as T;

      if (onResponse == null) {
      } else {
        onResponse(mdata as T);
      }
      return mdata;
    } catch (e) {
      print('errcode  e-->${e.toString()}');
      var exception = ApiException.from(e);
      dismissLoading();
      if (onError?.call(exception) != true) {
        EasyLoading.showError(exception.message ?? '服务器异常');
        throw exception;
      }
    }
    dismissLoading();
    return null;
  }

  ///获取游客令牌
  ///




  ///将请求 data 数据先使用 jsonEncode 转换为字符串，再使用 jsonDecode 方法将字符串转换为 Map。
  _convertRequestData(data) {
    if (data != null) {
      data = jsonDecode(jsonEncode(data));
    }
    return data;
  }

  ///请求响应内容处理e
  T? _handleResponse<T>(Response response) {
    if (response.statusCode == 200) {
      ApiResponse<T> apiResponse = ApiResponse<T>.fromJson(response.data);
      return _handleBusinessResponse<T>(apiResponse);
    } else {
      dismissLoading();
      var exception =
          ApiException(response.statusCode, ApiException.unknownException);
      throw exception;
    }
  }

  Future<T?> get<T>(String url,
      {Map<String, dynamic>? queryParameters,
      Map<String, dynamic>? headers,
      bool showLoading = false,
      bool Function(ApiException)? onError,
      Function(T)? onResponse}) {
    return request(
      url,
      method: "Get",
      queryParameters: queryParameters,
      headers: headers,
      onError: onError,
      onResponse: onResponse,
      isshowLoading: showLoading,
    );
  }

  Future<T?> post<T>(String url,
      {Map<String, dynamic>? queryParameters,
      data,
      Map<String, dynamic>? headers,
      bool showLoading = false,
      bool Function(ApiException)? onError,
      Function(T)? onResponse}) {
    return request(url,
        method: "POST",
        queryParameters: queryParameters,
        data: data,
        headers: headers,
        isshowLoading: showLoading,
        onError: onError,
        onResponse: onResponse);
  }

  Future<T?> delete<T>(
    String url, {
    Map<String, dynamic>? queryParameters,
    data,
    Map<String, dynamic>? headers,
    bool showLoading = false,
    bool Function(ApiException)? onError,
  }) {
    return request(url,
        method: "DELETE",
        queryParameters: queryParameters,
        data: data,
        isshowLoading: showLoading,
        headers: headers,
        onError: onError);
  }

  Future<T?> put<T>(
    String url, {
    Map<String, dynamic>? queryParameters,
    data,
    Map<String, dynamic>? headers,
    bool showLoading = false,
    bool Function(ApiException)? onError,
    Function(T)? onResponse,
  }) {
    return request(url,
        method: "PUT",
        queryParameters: queryParameters,
        data: data,
        isshowLoading: showLoading,
        headers: headers,
        onError: onError,
        onResponse: onResponse);
  }

  ///业务内容处理
  T? _handleBusinessResponse<T>(ApiResponse<T> response) {
    if (response.code == NetWorkConfig.successCode) {
      print("errcode errcode:  200200200");
      return response.data;
    } else {
      var exception = ApiException(response.code, response.msg);
      // if (response.code == 403) {
      //   // mGet.Get.toNamed(RouterPath.bsiDetailsPage);
      //   print("errcode errcode:  403403403");
      //   return null;
      // }
      throw exception;
    }
  }
}
