import 'package:common/services/msal_service.dart';
import 'package:comwell_key_app/presentation/screens/login/login_route.dart';
import 'package:comwell_key_app/services/exceptions.dart';
import 'package:common/utils/env_utils.dart';
import 'package:comwell_key_app/utils/locator.dart';
import 'package:comwell_key_app/utils/secure_storage.dart';
import 'package:dio/dio.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter/material.dart';

class ResponseHandleInterceptor extends Interceptor {
  final ComwellPreferences _comwellPreferences;
  final MSALService _msalService;

  ResponseHandleInterceptor(this._msalService, this._comwellPreferences);

  BuildContext? get context {
    final navigatorKey = locator<GlobalKey<NavigatorState>>();
    return navigatorKey.currentContext;
  }

  Future<void> checkAuth(RequestOptions requestOptions) async {
    try {
      final accessToken = await _msalService.acquireTokenSilent();
      requestOptions.headers['Authorization'] = accessToken;
    } catch (e, _) {
      debugPrint("checkAuthError=$e");
      throw UnauthorizedException();
    }
  }

  void addUserAgentHeader(RequestOptions requestOptions) {
    requestOptions.headers['User-Agent'] = _comwellPreferences.userAgent;
  }

  @override
  Future<dynamic> onRequest(
    RequestOptions options,
    RequestInterceptorHandler handler,
  ) async {
    try {
      await checkAuth(options);
      options.headers['Ocp-Apim-Subscription-Key'] = dotenv.OCP_APIM_SUBSCRIPTION_KEY;
      addUserAgentHeader(options);
      return handler.next(options);
    } on UnauthorizedException catch (e, st) {
      final exc = DioException(requestOptions: options, error: e, stackTrace: st);
      handler.reject(exc);
      logOut();
    } catch (e, st) {
      handler.reject(DioException(requestOptions: options, error: e, stackTrace: st));
    }
  }

  void logOut() {
    if (context != null) const LoginRoute().go(context!);
  }

  @override
  Future<dynamic> onError(
    DioException err,
    ErrorInterceptorHandler handler,
  ) async {
    final response = err.response;

    if (response == null) {
      debugPrint('Error: No response received');
      return handler.reject(err);
    }
    debugPrint('Error: ${_extractErrorMessage(response.data, "No data")}');

    switch (response.statusCode) {
      case 401:
      case 426:
        logOut();
    }
    return handler.reject(err);
  }

  String _extractErrorMessage(dynamic data, String fallback) {
    if (data == null) return fallback;
    if (data is String) return data;
    if (data is Map) {
      return data['detail']?.toString() ??
          data['message']?.toString() ??
          data['error']?.toString() ??
          fallback;
    }
    return fallback;
  }
}