import 'package:boilerplate/core/utils/network_util.dart';
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';

import '../../../core/exceptions/internet_not_connect_exception.dart';
import '../../../core/utils/print_utils.dart';
import '../../../core/utils/shared_preferences_util.dart';
import '../../../domain/entities/flavor/flavor_data.dart';

@injectable
class ApiInterceptors implements InterceptorsWrapper {
  @factoryParam
  final NetworkUtil _networkUtil;
  @factoryParam
  final SharedPreferencesUtil? _sharedPreferencesUtil;
  @factoryParam
  final AppFlavorData _appFlavorData;

  ApiInterceptors(
      this._sharedPreferencesUtil, this._appFlavorData, this._networkUtil);

  @override
  Future<void> onError(DioError err, ErrorInterceptorHandler handler) async {
    _printErrorData(err);

    if (err.response?.statusCode == 401) {
    } else {
      handler.reject(err);
    }
  }

  @override
  Future<void> onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    if (!(await _networkUtil.isConnected)) {
      throw InternetNotConnect();
    }

    final String? accessToken = _sharedPreferencesUtil
            ?.getString(SharedPreferencesUtil.keyAccessToken) ??
        '';

    if (!options.path.contains("http://") &&
        !options.path.contains("https://")) {
      options.baseUrl = Uri.encodeFull(_appFlavorData.baseUrl);
    }

    options.headers['Authorization'] = 'Bearer $accessToken';
    options.headers['content-type'] = Headers.jsonContentType;
    options.headers['accept'] = Headers.jsonContentType;

    _printRequestData(options);

    handler.next(options);
  }

  @override
  void onResponse(
      Response<dynamic> response, ResponseInterceptorHandler handler) {
    _printResponseData(response);

    handler.next(response);
  }

  _printRequestData(RequestOptions options) {
    if (!_appFlavorData.apiDebugEnabled) return;

    // dPrint(
    //     "Request : ${options.method.toUpperCase()} --> ${options.baseUrl}${options.path}");
    print("Headers:");
    options.headers.forEach((k, v) => print('$k: $v'));
    if (options.queryParameters.isNotEmpty) {
      print("queryParameters:");
      options.queryParameters.forEach((k, v) => print('$k: $v'));
    }
    if (options.data != null) {
      print("Body: ${options.data}");
    }

    print("--> END");
  }

  _printResponseData(Response response) {
    if (!_appFlavorData.apiDebugEnabled) return;

    print(
        "<-- ${response.statusCode} : ${(response.requestOptions.baseUrl) + (response.requestOptions.path)}");
    print("Headers:");
    response.headers.forEach((k, v) => print('$k: $v'));
    print("Response: ${response.data}");
    print("<-- END");
  }

  _printErrorData(DioError err) {
    if (!_appFlavorData.apiDebugEnabled) return;

    print(
        "<--${err.response?.statusCode ?? '' + " : "}  ${err.message} ${(err.response?.requestOptions != null ? (err.response!.requestOptions.baseUrl + err.response!.requestOptions.path) : 'URL')}");
    print("${err.response != null ? err.response!.data : 'Unknown Error'}");
    print("<-- End error");
  }
}
