import 'package:dio/dio.dart';
import 'package:get_it/get_it.dart';
import 'package:flutter/foundation.dart';
import 'package:superport/core/constants/api_endpoints.dart';
import 'package:superport/domain/repositories/auth_repository.dart';
import 'package:superport/data/models/auth/refresh_token_request.dart';
import 'package:superport/core/config/environment.dart';
import 'package:superport/core/navigation/app_navigator.dart';

/// 인증 인터셉터
class AuthInterceptor extends Interceptor {
  AuthRepository? _authRepository;
  final Dio dio;
  
  AuthInterceptor(this.dio, {AuthRepository? overrideAuthRepository}) {
    _authRepository = overrideAuthRepository;
  }
  
  AuthRepository? get authRepository {
    try {
      _authRepository ??= GetIt.instance<AuthRepository>();
      return _authRepository;
    } catch (e) {
      if (kDebugMode) {
        debugPrint('Failed to get AuthRepository in AuthInterceptor: $e');
      }
      return null;
    }
  }
  
  @override
  void onRequest(
    RequestOptions options,
    RequestInterceptorHandler handler,
  ) async {
    if (Environment.enableLogging && kDebugMode) {
      debugPrint('[AuthInterceptor] onRequest: ${options.method} ${options.path}');
    }
    
    // 로그인, 토큰 갱신 요청은 토큰 없이 진행
    if (_isAuthEndpoint(options.path)) {
      if (Environment.enableLogging && kDebugMode) {
        debugPrint('[AuthInterceptor] Auth endpoint detected, skipping token attachment');
      }
      handler.next(options);
      return;
    }
    
    // 저장된 액세스 토큰 가져오기
    final repo = authRepository;
    if (Environment.enableLogging && kDebugMode) {
      debugPrint('[AuthInterceptor] AuthRepository available: ${repo != null}');
    }
    
    if (repo != null) {
      final tokenEither = await repo.getStoredAccessToken();
      final accessToken = tokenEither.fold((_) => null, (t) => t);
      if (Environment.enableLogging && kDebugMode) {
        debugPrint('[AuthInterceptor] Access token retrieved: ${accessToken != null ? 'Yes' : 'No'}');
      }
      
      if (accessToken != null) {
        options.headers['Authorization'] = 'Bearer $accessToken';
        if (Environment.enableLogging && kDebugMode) {
          debugPrint('[AuthInterceptor] Authorization header set');
        }
      } else {
        if (Environment.enableLogging && kDebugMode) {
          debugPrint('[AuthInterceptor] WARNING: No access token available for protected endpoint');
        }
      }
    } else {
      if (Environment.enableLogging && kDebugMode) {
        debugPrint('[AuthInterceptor] ERROR: AuthRepository not available from GetIt');
      }
    }
    
    if (Environment.enableLogging && kDebugMode) {
      debugPrint('[AuthInterceptor] Final headers: ${options.headers}');
    }
    handler.next(options);
  }
  
  @override
  void onError(
    DioException err,
    ErrorInterceptorHandler handler,
  ) async {
    if (Environment.enableLogging && kDebugMode) {
      debugPrint('[AuthInterceptor] onError: ${err.response?.statusCode} ${err.message}');
    }
    
    // 401 Unauthorized 에러 처리
    if (err.response?.statusCode == 401) {
      // 인증 관련 엔드포인트는 재시도하지 않음
      if (_isAuthEndpoint(err.requestOptions.path)) {
        if (Environment.enableLogging && kDebugMode) {
          debugPrint('[AuthInterceptor] Auth endpoint 401 error, skipping retry');
        }
        handler.next(err);
        return;
      }
      
      final repo = authRepository;
      if (repo != null) {
        if (Environment.enableLogging && kDebugMode) {
          debugPrint('[AuthInterceptor] Attempting token refresh...');
        }
        // 토큰 갱신 시도
        final refreshTokenEither = await repo.getStoredRefreshToken();
        final refreshToken = refreshTokenEither.fold((_) => null, (t) => t);
        final refreshResult = refreshToken == null
            ? null
            : await repo.refreshToken(RefreshTokenRequest(refreshToken: refreshToken));
        
        final refreshSuccess = refreshResult != null && refreshResult.isRight();
        
        if (refreshSuccess) {
          // 새로운 토큰으로 원래 요청 재시도
          try {
            final newAccessTokenEither = await repo.getStoredAccessToken();
            final newAccessToken = newAccessTokenEither.fold((_) => null, (t) => t);
            
            if (newAccessToken != null) {
              if (Environment.enableLogging && kDebugMode) {
                debugPrint('[AuthInterceptor] Retrying request with new token');
              }
              err.requestOptions.headers['Authorization'] = 'Bearer $newAccessToken';
              
              // dio 인스턴스를 통해 재시도
              final response = await dio.fetch(err.requestOptions);
              handler.resolve(response);
              return;
            }
          } catch (e) {
            if (Environment.enableLogging && kDebugMode) {
              debugPrint('[AuthInterceptor] Request retry failed: $e');
            }
            // 재시도 실패
            handler.next(err);
            return;
          }
        }
        
        // 토큰 갱신 실패 시 로그인 화면으로 이동
        if (Environment.enableLogging && kDebugMode) {
          debugPrint('[AuthInterceptor] Clearing session due to auth failure');
        }
        await repo.clearLocalSession();
        // 로그인 화면으로 이동 (모든 스택 제거)
        navigateToLoginClearingStack();
      }
    }
    
    handler.next(err);
  }
  
  
  /// 인증 관련 엔드포인트 확인
  bool _isAuthEndpoint(String path) {
    return path.contains(ApiEndpoints.login) ||
           path.contains(ApiEndpoints.refresh) ||
           path.contains(ApiEndpoints.logout);
  }
}
