import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:road24_mobile/data/http/ApiException.dart';
import 'package:road24_mobile/my_app.dart';

class CustomDioInterceptor extends Interceptor {
  CustomDioInterceptor({
    this.request = false,
    this.requestHeader = false,
    this.requestBody = false,
    this.responseHeader = true,
    this.responseBody = true,
    this.error = true,
    this.logPrint = print,
  });

  /// Print request [Options]
  bool request;

  /// Print request header [Options.headers]
  bool requestHeader;

  /// Print request data [Options.data]
  bool requestBody;

  /// Print [Response.data]
  bool responseBody;

  /// Print [Response.headers]
  bool responseHeader;

  /// Print error message
  bool error;

  void Function(Object object) logPrint;

  @override
  Future onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    MyApp.hasInternet.value = true;
    if (!kReleaseMode)
      print('REQUEST[${options.method}] => PATH: ${options.path}');
    // super.onRequest(options, handler);
    logPrint('*** Request ***');
    var token = MyApp.preferences?.getToken();
    if (token != null && token != "")
      options.headers['Authorization'] = "JWT " + token;
    printKV('uri', options.uri);

    if (request) {
      printKV('method', options.method);
    }
    if (requestHeader) {
      StringBuffer stringBuffer = StringBuffer();
      options.headers.forEach((key, v) => stringBuffer.write('\n  $key:$v'));
      printKV('headers', stringBuffer.toString());
      stringBuffer.clear();
    }
    if (requestBody) {
      logPrint("data:");
      printAll(options.data);
    }
    logPrint("");
    return super.onRequest(options, handler);
  }

  @override
  Future onError(DioError err, ErrorInterceptorHandler handler) async {
    if (error) {
      logPrint('*** DioError ***:');
      logPrint("uri: ${err.requestOptions.uri}");
      logPrint("$err");
      if (err.toString().startsWith("DioError [DioErrorType.DEFAULT]: SocketException: Failed host lookup: 'api.road24.uz'") ||
          err.toString().startsWith(
              "DioError [DioErrorType.RESPONSE]: Http status error [500]") ||
          err.toString().startsWith(
              "DioError [DioErrorType.DEFAULT]: SocketException: Connection failed") ||
          err.toString().startsWith(
              "DioError [DioErrorType.DEFAULT]: SocketException: OS Error:") ||
          err
              .toString()
              .startsWith("DioError [DioErrorType.CONNECT_TIMEOUT]:")) {}
      if (err.response != null) {
        ApiException.errorMessage.value =
            "${err.response!.data}\n${err.response!.statusCode}"
                .replaceAll("api.road24.uz", "url");
        print(ApiException.errorMessage.value);
      } else
        ApiException.errorMessage.value =
            "${err.message}".replaceAll("api.road24.uz", "url");
    } else {
      if (err.response != null) {
        ApiException.errorMessage.value =
            "${err.response!.data}\n${err.response!.statusCode}"
                .replaceAll("api.road24.uz", "url");
        print(ApiException.errorMessage.value);
      } else
        ApiException.errorMessage.value =
            "${err.message}".replaceAll("api.road24.uz", "url");
    }
    if (err.toString().contains("SocketException") ||
        err.toString().contains("Connecting timed out")) {
      MyApp.hasInternet.value = false;
    }
    return super.onError(err, handler);
  }

  @override
  Future onResponse(
      Response response, ResponseInterceptorHandler hanlder) async {
    if (!kReleaseMode)
      print(
        'RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}',
      );
    logPrint("*** Response ***");
    _printResponse(response);
    return super.onResponse(response, hanlder);
  }

  void _printResponse(Response response) {
    if (responseHeader) {
      printKV('statusCode', response.statusCode);
    }
    if (responseBody) {
      logPrint("Response Text:");
      printAll(response.toString());
    }
    logPrint("");
  }

  printKV(String key, dynamic v) {
    if (!kReleaseMode) logPrint('$key: $v');
  }

  printAll(msg) {
    if (!kReleaseMode) msg.toString().split("\n").forEach(logPrint);
  }
}
