import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:injectable/injectable.dart'; import 'package:superport/core/errors/failures.dart'; import 'package:superport/data/datasources/remote/api_client.dart'; import 'package:superport/core/constants/api_endpoints.dart'; import 'package:superport/data/models/lookups/lookup_data.dart'; abstract class LookupRemoteDataSource { Future> getAllLookups(); Future> getLookupsByType(String type); } @LazySingleton(as: LookupRemoteDataSource) class LookupRemoteDataSourceImpl implements LookupRemoteDataSource { final ApiClient _apiClient; LookupRemoteDataSourceImpl(this._apiClient); @override Future> getAllLookups() async { try { debugPrint('πŸ“ž === LOOKUP κ°œλ³„ API μš”μ²­ μ‹œμž‘ ==='); // κ°œλ³„ API듀을 λ³‘λ ¬λ‘œ 호좜 final List futures = [ _apiClient.get(ApiEndpoints.lookupsVendors), _apiClient.get(ApiEndpoints.lookupsCompanies), _apiClient.get(ApiEndpoints.lookupsWarehouses), ]; final responses = await Future.wait(futures, eagerError: false); debugPrint('πŸ“Š === LOOKUP κ°œλ³„ API 응닡 ==='); // Vendors 데이터 처리 List manufacturers = []; try { final vendorsResponse = responses[0] as Response; if (vendorsResponse.data is List) { manufacturers = (vendorsResponse.data as List) .map((v) => LookupItem( id: v['id'] as int?, name: v['name'] as String )) .toList(); debugPrint('βœ… μ œμ‘°μ‚¬ 데이터: ${manufacturers.length}개'); } } catch (e) { debugPrint('⚠️ μ œμ‘°μ‚¬ 데이터 처리 μ‹€νŒ¨: $e'); } // Companies 데이터 처리 List companies = []; try { final companiesResponse = responses[1] as Response; if (companiesResponse.data is List) { companies = (companiesResponse.data as List) .map((c) => LookupItem( id: c['id'] as int?, name: c['name'] as String )) .toList(); debugPrint('βœ… νšŒμ‚¬ 데이터: ${companies.length}개'); } } catch (e) { debugPrint('⚠️ νšŒμ‚¬ 데이터 처리 μ‹€νŒ¨: $e'); } // Warehouses 데이터 처리 List warehouses = []; try { final warehousesResponse = responses[2] as Response; if (warehousesResponse.data is List) { warehouses = (warehousesResponse.data as List) .map((w) => LookupItem( id: w['id'] as int?, name: w['name'] as String )) .toList(); debugPrint('βœ… μ°½κ³  데이터: ${warehouses.length}개'); } } catch (e) { debugPrint('⚠️ μ°½κ³  데이터 처리 μ‹€νŒ¨: $e'); } // ν†΅ν•©λœ LookupData 생성 final lookupData = LookupData( manufacturers: manufacturers, companies: companies, warehouses: warehouses, equipmentNames: [], // ν˜„μž¬ λ°±μ—”λ“œμ—μ„œ μ œκ³΅ν•˜μ§€ μ•ŠμŒ equipmentCategories: [], // ν˜„μž¬ λ°±μ—”λ“œμ—μ„œ μ œκ³΅ν•˜μ§€ μ•ŠμŒ equipmentStatuses: [], // ν˜„μž¬ λ°±μ—”λ“œμ—μ„œ μ œκ³΅ν•˜μ§€ μ•ŠμŒ ); debugPrint('πŸ“Š 톡합 Lookup 데이터 생성 μ™„λ£Œ'); return Right(lookupData); } on DioException catch (e) { debugPrint('❌ === LOOKUP API DIO μ—λŸ¬ ==='); debugPrint('❌ μ—λŸ¬ νƒ€μž…: ${e.type}'); debugPrint('❌ μƒνƒœ μ½”λ“œ: ${e.response?.statusCode}'); debugPrint('❌ μ—λŸ¬ λ©”μ‹œμ§€: ${e.message}'); // κ°œλ³„ API 였λ₯˜μ˜ 경우 빈 λ°μ΄ν„°λ‘œ fallback return Right(LookupData.empty()); } catch (e) { debugPrint('❌ === LOOKUP API 일반 μ—λŸ¬ ==='); debugPrint('❌ μ—λŸ¬: $e'); return Left(ServerFailure(message: '쑰회 데이터λ₯Ό κ°€μ Έμ˜€λŠ” 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: $e')); } } @override Future> getLookupsByType(String type) async { try { final response = await _apiClient.get( '${ApiEndpoints.lookups}/type', queryParameters: {'lookup_type': type}, ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { // νƒ€μž…λ³„ μ‘°νšŒλ„ 전체 LookupData ν˜•μ‹μœΌλ‘œ λ°˜ν™˜ - IdentityMap νƒ€μž… 였λ₯˜ μˆ˜μ • try { final lookupData = LookupData.fromJson(response.data['data'] as Map); return Right(lookupData); } catch (jsonError) { debugPrint('❌ LookupData JSON νŒŒμ‹± 였λ₯˜: $jsonError'); debugPrint('❌ 응닡 데이터: ${response.data['data']}'); // JSON νŒŒμ‹± μ‹€νŒ¨ μ‹œ 빈 데이터 λ°˜ν™˜ return Right(LookupData.empty()); } } else { final errorMessage = response.data?['error']?['message'] ?? '응닡 데이터가 μ˜¬λ°”λ₯΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€'; return Left(ServerFailure(message: errorMessage)); } } on DioException catch (e) { return Left(_handleDioError(e)); } catch (e) { debugPrint('❌ getLookupsByType 일반 였λ₯˜: $e'); return Left(ServerFailure(message: 'νƒ€μž…λ³„ 쑰회 데이터λ₯Ό κ°€μ Έμ˜€λŠ” 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: $e')); } } Failure _handleDioError(DioException error) { switch (error.type) { case DioExceptionType.connectionTimeout: case DioExceptionType.sendTimeout: case DioExceptionType.receiveTimeout: return NetworkFailure(message: 'λ„€νŠΈμ›Œν¬ μ—°κ²° μ‹œκ°„μ΄ μ΄ˆκ³Όλ˜μ—ˆμŠ΅λ‹ˆλ‹€'); case DioExceptionType.connectionError: return NetworkFailure(message: 'μ„œλ²„μ— μ—°κ²°ν•  수 μ—†μŠ΅λ‹ˆλ‹€'); case DioExceptionType.badResponse: final statusCode = error.response?.statusCode ?? 0; final errorData = error.response?.data; String message; if (errorData is Map) { message = errorData['error']?['message'] ?? errorData['message'] ?? 'μ„œλ²„ 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€'; } else { message = 'μ„œλ²„ 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€'; } if (statusCode == 401) { return AuthenticationFailure(message: '인증이 λ§Œλ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€'); } else if (statusCode == 403) { return AuthenticationFailure(message: 'μ ‘κ·Ό κΆŒν•œμ΄ μ—†μŠ΅λ‹ˆλ‹€'); } else { return ServerFailure(message: message); } case DioExceptionType.cancel: return ServerFailure(message: 'μš”μ²­μ΄ μ·¨μ†Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€'); default: return ServerFailure(message: 'μ•Œ 수 μ—†λŠ” 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€'); } } }