import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:liftmanager/common/common.dart';
import 'package:liftmanager/utils/log_util.dart' as logg;
import 'package:liftmanager/utils/log_utils.dart';
import 'package:liftmanager/utils/url.dart';
import 'package:rxdart/rxdart.dart';

import 'base_entity.dart';
import 'error_handle.dart';
import 'intercept.dart';

/// @weilu https://github.com/simplezhli
class DioUtils {
  static final DioUtils _singleton = DioUtils._internal();

  static DioUtils get instance => DioUtils();

  factory DioUtils() {
    return _singleton;
  }

  static Dio _dio;

  Dio getDio() {
    return _dio;
  }

  DioUtils._internal() {
    var options = BaseOptions(
      connectTimeout: 150000,
      receiveTimeout: 15000,
      responseType: ResponseType.plain,
      validateStatus: (status) {
        // 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
        return true;
      },
      // baseUrl: "http://192.168.31.100:20250",
      // baseUrl: "http://192.168.1.4:20226",
      // baseUrl: "http://192.168.0.110:20250",
      // baseUrl: "http://192.168.31.112:20226",
      // baseUrl: "http://lift.whlhcx.com",
//      baseUrl: "http://111.47.6.224:10227",
      baseUrl: baseUrl,
      // baseUrl: "http://221.234.44.30:10227",
//      baseUrl: "http://192.168.1.16",
//      contentType: ContentType('application', 'x-www-form-urlencoded', charset: 'utf-8'),
    );
    _dio = Dio(options);

    /// Fiddler抓包代理配置 https://www.jianshu.com/p/d831b1f7c45b
    //  (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
    //      (HttpClient client) {
    //    client.findProxy = (uri) {
    //      //proxy all request to localhost:8888
    //      return "PROXY 192.168.31.72:8686";
    //    };
    //    client.badCertificateCallback =
    //        (X509Certificate cert, String host, int port) => true;
    //  };
    /// 统一添加身份验证请求头
    _dio.interceptors.add(AuthInterceptor());

    /// 刷新Token
//    _dio.interceptors.add(TokenInterceptor());
    /// 打印Log(生产模式去除)
    if (!Constant.inProduction) {
      // _dio.interceptors.add(LoggingInterceptor());
      _dio.interceptors.add(
        InterceptorsWrapper(
          onRequest: (RequestOptions options) {
            print(
                "\n================================= 请求数据 =================================");
            print("method = ${options.method.toString()}");
            print("url = ${options.uri.toString()}");
            print("headers = ${options.headers}");
            // print("params = ${options.queryParameters}");
            print("paramsData = ${options.data}");
          },
          onResponse: (Response response) {
            print(
                "\n================================= 响应数据开始 =================================");
            print("StatusCode = ${response.statusCode}");
            logg.LogUtil.d("data = ${response.data}");
          },
          onError: (DioError e) {
            print(
                "\n=================================错误响应数据 =================================");
            print("type = ${e.type}");
            print("message = ${e.message}");
            print("\n");
          },
        ),
      );
    }

    /// 适配数据(根据自己的数据结构，可自行选择添加)
    _dio.interceptors.add(AdapterInterceptor());
  }

  // 数据返回格式统一，统一处理异常
  Future<BaseEntity<T>> _request<T>(String method, String url,
      {T Function(Map<String, dynamic>) objectFromJson,
      dynamic data,
      Map<String, dynamic> queryParameters,
      CancelToken cancelToken,
      Options options}) async {
    var response = await _dio.request(url,
        data: data,
        queryParameters: queryParameters,
        options: _checkOptions(method, options),
        cancelToken: cancelToken);
    try {
      /// 集成测试无法使用 isolate
      Map<String, dynamic> _map = Constant.isTest
          ? parseData(response.data.toString())
          : await compute(parseData, response.data.toString());
      return BaseEntity.fromJson(_map, objectFromJson);
    } catch (e, s) {
      return BaseEntity(ExceptionHandle.parse_error, "数据解析错误${e}\n${s}", null);
    }
  }

  Options _checkOptions(method, options) {
    if (options == null) {
      options = new Options();
    }
    options.method = method;
    return options;
  }

  Future requestNetwork<T>(Method method, String url,
      {T Function(Map<String, dynamic>) objectFromJson,
      Function(T t) onSuccess,
      Function(List<T> list) onSuccessList,
      Function(int code, String msg) onError,
      dynamic params,
      Map<String, dynamic> queryParameters,
      CancelToken cancelToken,
      Options options,
      bool isList: false}) async {
    String m = _getRequestMethod(method);
    return await _request<T>(m, url,
            objectFromJson: objectFromJson,
            data: params,
            queryParameters: queryParameters,
            options: options,
            cancelToken: cancelToken)
        .then((BaseEntity<T> result) {
      // logg.LogUtil.d(params);
      if (result.statusCode == 1 || result.statusCode == 9) {
        if (isList) {
          if (onSuccessList != null) {
            onSuccessList(result.listData);
          }
        } else {
          if (onSuccess != null) {
            onSuccess(result.data);
          }
        }
      } else {
        _onError(result.statusCode, result.message, onError);
      }
    }, onError: (e, _) {
      _cancelLogPrint(e, url);
      NetError error = ExceptionHandle.handleException(e);
      _onError(error.code, error.msg, onError);
    });
  }

  /// 统一处理(onSuccess返回T对象，onSuccessList返回List<T>)
  asyncRequestNetwork<T>(Method method, String url,
      {Function(T t) onSuccess,
      Function(List<T> list) onSuccessList,
      Function(int code, String msg) onError,
      dynamic params,
      Map<String, dynamic> queryParameters,
      CancelToken cancelToken,
      Options options,
      bool isList: false}) {
    String m = _getRequestMethod(method);
    Observable.fromFuture(_request<T>(m, url,
            data: params,
            queryParameters: queryParameters,
            options: options,
            cancelToken: cancelToken))
        .asBroadcastStream()
        .listen((result) {
      if (result.statusCode == 1 || result.statusCode == 9) {
        if (isList) {
          if (onSuccessList != null) {
            onSuccessList(result.listData);
          }
        } else {
          if (onSuccess != null) {
            onSuccess(result.data);
          }
        }
      } else {
        _onError(result.statusCode, result.message, onError);
      }
    }, onError: (e) {
      _cancelLogPrint(e, url);
      NetError error = ExceptionHandle.handleException(e);
      _onError(error.code, error.msg, onError);
    });
  }

  _cancelLogPrint(dynamic e, String url) {
    if (e is DioError && CancelToken.isCancel(e)) {
      Log.e("取消请求接口： $url");
    }
  }

  _onError(int code, String msg, Function(int code, String mag) onError) {
    if (code == null) {
      code = ExceptionHandle.unknown_error;
      msg = "未知异常";
    }
    Log.e("接口请求异常： code: $code, mag: $msg");
    if (onError != null) {
      onError(code, msg);
    }
  }

  String _getRequestMethod(Method method) {
    String m;
    switch (method) {
      case Method.get:
        m = "GET";
        break;
      case Method.post:
        m = "POST";
        break;
      case Method.put:
        m = "PUT";
        break;
      case Method.patch:
        m = "PATCH";
        break;
      case Method.delete:
        m = "DELETE";
        break;
      case Method.head:
        m = "HEAD";
        break;
    }
    return m;
  }
}

Map<String, dynamic> parseData(String data) {
  return json.decode(data);
}

enum Method { get, post, put, patch, delete, head }
