import 'dart:io';
import 'package:get/get.dart' as geta;
import 'package:curl_logger_dio_interceptor/curl_logger_dio_interceptor.dart';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';

import '../../commom/constants/api_constant.dart';
import '../../commom/constants/error_code_constant.dart';
import '../model/base_model.dart';
import 'api_intercepter.dart';


class NetworkUtil {
  final Dio _dio = Dio();

  NetworkUtil() {
    ///Create Dio Object using baseOptions set receiveTimeout,connectTimeout
    BaseOptions options = BaseOptions(
        receiveTimeout: ApiConstants.RECIEVE_TIMEOUT,
        connectTimeout: ApiConstants.RECIEVE_TIMEOUT);
    // options.baseUrl = ApiConstants.BASE_URL;
    // options.headers["Authorization"] = AppCache().token;
    _dio.options = options;
    _dio.interceptors
        .add(LogInterceptor(requestBody: true, responseBody: true));
    _dio.interceptors.add(ApiIntercepter());
    _dio.interceptors.add(CurlLoggerDioInterceptor(printOnSuccess: true));
    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (HttpClient client) {
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) => true;
      return client;
    };
  }

  ///used for calling Get Request
  Future<Response> get(String url, Map<String, dynamic> params,
      {Map<String, dynamic>? headers, CancelToken? cancelToken}) async {
    try {
      Response response;
      if (cancelToken != null) {
        response = await _dio.get(url,
            queryParameters: params,
            cancelToken: cancelToken,
            options:
                Options(responseType: ResponseType.json, headers: headers));
      } else {
        response = await _dio.get(url,
            queryParameters: params,
            options:
                Options(responseType: ResponseType.json, headers: headers));
      }
      return response;
    } on DioError catch (e) {
      return response(e, url);
    }
  }

  // Map<String, dynamic> header = {"Authorization": AppCache().token};

  ///used for calling post Request
  Future<Response> post(
    String url, {
    Map<String, dynamic>? headers,
    dynamic mapData,
    FormData? formData,
    Map<String, dynamic>? params,
    CancelToken? cancelToken,
  }) async {
    try {
      Response response;
      if ((formData == null)) {
        response = await _dio.post(url,
            data: mapData,
            cancelToken: cancelToken,
            queryParameters: params,
            options: Options(
              responseType: ResponseType.json,
              headers: headers,
            ));
      } else {
        response = await _dio.post(url,
            data: formData,
            queryParameters: params,
            cancelToken: cancelToken,
            options: Options(
              responseType: ResponseType.json,
              headers: headers,
            ));
      }

      return response;
    } on DioError catch (e) {
      Response response;
      if (DioErrorType.receiveTimeout == e.type ||
          DioErrorType.connectTimeout == e.type) {
        response = Response(
            data: BaseModel(code: e.response?.data["code"], message: ErrorCodeConstant.TIMEOUT),
            requestOptions: RequestOptions(path: url));
      } else {
        final dioRes = e.response;
        if (dioRes != null) {
          response = Response(
              data: BaseModel(
                  code: dioRes.data["code"], message: dioRes.data["message"]),
              requestOptions: RequestOptions(path: url));
        } else {
          response = Response(
              data:
                  BaseModel(code: dioRes?.data["code"], message: ErrorCodeConstant.SERVER_ERROR),
              requestOptions: RequestOptions(path: url));
        }
      }

      return response;
    }
  }

  Future<Response> put(String url,
      {Map<String, dynamic>? headers,
      Map<String, dynamic>? mapData,
      FormData? formData}) async {
    try {
      Response response = await _dio.put(url,
          data: (mapData == null) ? formData : mapData,
          options: Options(responseType: ResponseType.json, headers: headers));
      return response;
    } on DioError catch (e) {
      Response response;
      if (DioErrorType.receiveTimeout == e.type ||
          DioErrorType.connectTimeout == e.type) {
        response = Response(
            data: BaseModel(code: e.response?.statusCode, message: e.response?.data["message"]),
            requestOptions: RequestOptions(path: url));
      } else {
        final dioRes = e.response;
        if (dioRes != null) {
          response = Response(
              data: BaseModel(
                  code: dioRes.data["code"], message: dioRes.data["message"]),
              requestOptions: RequestOptions(path: url));
        } else {
          response = Response(
              data:
              BaseModel(code: dioRes?.data["code"], message:e.response?.data["message"]),
              requestOptions: RequestOptions(path: url));
        }
      }
      return response;
    }
  }

  Future<Response> delete(String url, Map<String, dynamic> data,
      {Map<String, dynamic>? headers}) async {
    try {
      Response response = await _dio.delete(url,
          data: data,
          options: Options(responseType: ResponseType.json, headers: headers));
      return response;
    } on DioError catch (e) {
      return response(e, url);
    }
  }

  Response response(DioError e, url) {
    Response response;
    if (DioErrorType.receiveTimeout == e.type ||
        DioErrorType.connectTimeout == e.type) {
      response = Response(
          data: BaseModel(code: e.response?.data["code"], message: ErrorCodeConstant.TIMEOUT),
          requestOptions: RequestOptions(path: url));
    } else {
      response = Response(
          data: BaseModel(code: e.response?.data["code"], message: e.response?.data["message"]),
          requestOptions: RequestOptions(path: url));
    }
    return response;
  }
}

final networkUtil = NetworkUtil();
