import 'package:chat/utils/network/http_interceptor.dart';
import 'package:chat/utils/network/http_options.dart';
import 'package:dio/dio.dart';

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

class HttpRequest {
  static HttpRequest? _instance;
  static Dio _dio = Dio();
  Dio get dio => _dio;

  HttpRequest._internal() {
    _instance = this;
    _instance!._init();
  }

  factory HttpRequest() => _instance ?? HttpRequest._internal();

  static HttpRequest? getInstance() {
    return _instance ?? HttpRequest._internal();
  }

  /// 取消请求token
  final CancelToken _cancelToken = CancelToken();

  _init() {
    BaseOptions options = BaseOptions(
      baseUrl: HttpOptions.baseUrl,
      connectTimeout: HttpOptions.connectTimeout,
      receiveTimeout: HttpOptions.receiveTimeout,
    );
    _dio = Dio(options);

    /// 添加拦截器
    _dio.interceptors.add(HttpInterceptor());
  }

  /// 请求
  Future request(
    String path, {
    HttpMethod method = HttpMethod.get,
    Map<String, dynamic>? params,
    dynamic data,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    const methodValues = {
      HttpMethod.get: 'get',
      HttpMethod.post: 'post',
      HttpMethod.put: 'put',
      HttpMethod.delete: 'delete',
      HttpMethod.patch: 'patch',
      HttpMethod.head: 'head'
    };

    options ??= Options(method: methodValues[method]);

    try {
      Response response = await _dio.request(
        path,
        data: data,
        queryParameters: params,
        cancelToken: cancelToken ?? _cancelToken,
        options: options,
        onSendProgress: onSendProgress,
        onReceiveProgress: onReceiveProgress,
      );
      // ignore: avoid_print
      print('请求地址：${response.requestOptions.uri}');
      // ignore: avoid_print
      print('响应数据：${response.data}');
      return response.data;
    } on DioError catch (e) {
      throw Exception(e.message);
    }
  }

  /// 取消网络请求
  void cancelRequests({CancelToken? token}) {
    token ?? _cancelToken.cancel('CANCELED');
  }
}
