import 'dart:convert';

import 'package:anchor_collect_flutter/utils/dialog_utils.dart';
import 'package:dio/dio.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';

import '../utils/loading.dart' as loading;

import 'ApiException.dart';
import 'NetWorkConfig.dart';
import 'TokenInterceptor.dart';
import 'api_response.dart';

class HttpUtils<T> {
  late Dio _dio;
  String? url;
  String method = 'POST';
  String contentType = '';
  FormData? formData;
  bool isList = false;
  Map<dynamic, dynamic> params = {};
  Map<String, dynamic> queryParameters = {};
  Map<String, dynamic>? headers = {};
  bool isShow = false;
  Function(String, int)? errorCallback;
  Function(T?)? responseCallback;
  Function(List<T?>)? responseListCallback;
  List<dynamic>? mList;

  HttpUtils._internal() {
    var options = BaseOptions(
        baseUrl: NetWorkConfig.baseUrl,
        connectTimeout:
            const Duration(milliseconds: NetWorkConfig.connectTimeOut),
        receiveTimeout: const Duration(milliseconds: NetWorkConfig.readTimeOut),
        sendTimeout: const Duration(milliseconds: NetWorkConfig.writeTimeOut));
    _dio = Dio(options);
    _dio.interceptors.add(TokenInterceptor());
    _dio.interceptors.add(PrettyDioLogger(
        requestHeader: true,
        requestBody: true,
        responseHeader: true,
        responseBody: true));
  }

  factory HttpUtils() {
    return HttpUtils._internal();
  }

  void post() {
    method = 'POST';
    url = '';
    isShow = false;
    params = {};
    queryParameters = {};
    contentType = 'application/json';
  }

  void get() {
    method = 'Get';
    url = '';
    isShow = false;
    params = {};
    queryParameters = {};
    contentType = '';
  }

  void setContentType(String contentType) {
    this.contentType = contentType;
  }

  void showLoading() {
    isShow = true;
  }

  void setUrl(String url) {
    this.url = url;
  }

  void setMethod(String method) {
    this.method = method;
  }

  void setmListParam(List<dynamic> mList) {
    this.mList = mList;
  }

  void setIsList() {
    this.isList = true;
  }

  void addParam(String key, dynamic value) {
    params[key] = value;
  }

  void setParams(Map<dynamic, dynamic> params) {
    this.params = params;
  }

  void addQueryParameters(String key, dynamic value) {
    queryParameters[key] = value;
  }

  void setQueryParameters(Map<String, dynamic> queryParameters) {
    this.queryParameters = queryParameters;
  }

  void setFormData(FormData formData) {
    this.formData = formData;
  }

  void setHeaders(Map<String, dynamic> headers) {
    this.headers = headers;
  }

  void addHeader(String key, String value) {
    headers?.putIfAbsent(key, () => value);
  }

  void onError(void Function(String msg, int code) errorCallback) {
    this.errorCallback = errorCallback;
  }

  void onResponse(void Function(T? response) onResponseCallback) {
    this.responseCallback = onResponseCallback;
  }

  void onResponseList(void Function(List<T?> list) onResponseListCallback) {
    this.responseListCallback = onResponseListCallback;
  }

  Future<void> build() async {
    if (isShow) {
      loading.showLoading();
    }

    Options options = Options(
      method: method,
      headers: headers,
    );
    if (contentType != '') {
      options.contentType = contentType;
    }

    try {
      Response response = await _dio.request(url!,
          data: mList != null
              ? _convertRequestData(mList)
              : formData ?? _convertRequestData(params),
          queryParameters: queryParameters,
          options: options);

      _handleResponse(response);
    } catch (e) {
      var exception = ApiException.from(e);
      // DialogUtils.dismissDialog();
      loading.dismissLoading();
      if (errorCallback != null) {
        errorCallback!(e.toString(), exception.code ?? -1);
      }
      // EasyLoading.showError(exception.message ?? '服务器异常');
      DialogUtils.showWarningDialog(exception.message ?? '服务器异常');
    }
  }

  void _handleResponse(Response response) {
        loading.dismissLoading();
    if (response.statusCode == 200) {
      ApiResponse<T> apiResponse;
      if (isList) {
        apiResponse = ApiResponse<T>.fromJsonList(response.data);
      } else {
        apiResponse = ApiResponse<T>.fromJson(response.data);
      }
      if (apiResponse.code == NetWorkConfig.successCode) {
        if (isList) {
          responseListCallback?.call(apiResponse.list);
        } else {
          if (apiResponse.data != null) {
            responseCallback?.call(apiResponse.data);
          }
        }
      } else {
        interceptToken(apiResponse.msg, apiResponse.code);
        // EasyLoading.showError(apiResponse.message);
      }
    } else {
      var exception =
          ApiException(response.statusCode, ApiException.unknownException);
      errorCallback!(exception.message ?? '服务器异常', exception.code ?? -1);
      EasyLoading.showError(exception.message ?? '服务器异常');
    }
  }

  interceptToken(String msg, int code) {
    print('code:$code  -- msg:$msg');
    switch (code) {
      case 403:
        // print('网络请求  拦截到400');
        // NetWorkUtils.getVisitorToken();
        break;
      default:
        // EasyLoading.showError(msg);
        errorCallback!(msg, code ?? -1);
        break;
    }
  }

  _convertRequestData(data) {
    if (data != null) {
      data = jsonDecode(jsonEncode(data));
    }
    return data;
  }
}
