import 'package:dio/dio.dart'; import 'package:cookie_jar/cookie_jar.dart'; import 'package:dio_cookie_manager/dio_cookie_manager.dart'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import '../config/api_config.dart'; import '../services/auth_service.dart'; import '../screens/auth/login_screen.dart'; import '../main.dart'; // navigatorKey를 사용하기 위한 import class ApiService { static final ApiService _instance = ApiService._internal(); factory ApiService() => _instance; late Dio _dio; final CookieJar _cookieJar = CookieJar(); String? _token; ApiService._internal() { _dio = Dio(BaseOptions( baseUrl: ApiConfig.baseUrl, connectTimeout: const Duration(seconds: 10), receiveTimeout: const Duration(seconds: 10), contentType: 'application/json', )); // 쿠키 관리자 설정 (웹 환경에서는 사용하지 않음) if (!kIsWeb) { _dio.interceptors.add(CookieManager(_cookieJar)); } // 로그 인터셉터 (디버깅용) _dio.interceptors.add(LogInterceptor( requestBody: true, responseBody: true, )); } // 토큰 설정 void setToken(String token) { _token = token; _dio.options.headers['Authorization'] = 'Bearer $token'; } // GET 요청 Future get(String path, {Map? queryParameters}) async { try { final response = await _dio.get( path, queryParameters: queryParameters, ); return response.data; } on DioException catch (e) { _handleError(e); rethrow; } } // POST 요청 Future post(String path, {dynamic data}) async { try { final response = await _dio.post( path, data: data ?? {}, ); return response.data; } on DioException catch (e) { _handleError(e); rethrow; } } // PUT 요청 Future put(String path, {dynamic data}) async { try { final response = await _dio.put( path, data: data, ); return response.data; } on DioException catch (e) { _handleError(e); rethrow; } } // DELETE 요청 Future delete(String path) async { try { final response = await _dio.delete(path); return response.data; } on DioException catch (e) { _handleError(e); rethrow; } } // 에러 처리 void _handleError(DioException e) { if (e.response != null) { print('API 에러: ${e.response?.statusCode} - ${e.response?.data}'); // 401 오류 (인증 실패) 처리 if (e.response?.statusCode == 401) { print('인증 오류: 토큰이 유효하지 않습니다. 로그아웃 처리합니다.'); _handleUnauthorized(); } } else { print('API 요청 에러: ${e.message}'); } } // 인증 오류 처리 (401) void _handleUnauthorized() { // 다음 프레임에서 실행하여 현재 API 호출 스택이 완료되도록 함 Future.microtask(() async { try { // AuthService 인스턴스 가져오기 final authService = AuthService(); // 로그아웃 처리 await authService.logout(); // 전역 네비게이터 키를 사용하여 로그인 화면으로 이동 if (navigatorKey.currentContext != null) { Navigator.of(navigatorKey.currentContext!).pushAndRemoveUntil( MaterialPageRoute(builder: (context) => const LoginScreen()), (route) => false, ); } } catch (e) { print('로그아웃 처리 중 오류 발생: $e'); } }); } }