import 'package:uuid/uuid.dart'; import '../../../domain/entities/restaurant.dart'; import '../naver/naver_local_search_api.dart'; import '../../../core/utils/category_mapper.dart'; /// 네이버 데이터 변환기 /// /// 네이버 API 응답을 도메인 엔티티로 변환합니다. class NaverDataConverter { static const _uuid = Uuid(); /// NaverLocalSearchResult를 Restaurant 엔티티로 변환 static Restaurant fromLocalSearchResult( NaverLocalSearchResult result, { String? id, }) { // 좌표 변환 (네이버 지도 좌표계 -> WGS84) final convertedCoords = _convertNaverMapCoordinates( result.mapx, result.mapy, ); // 카테고리 파싱 및 정규화 final categoryParts = result.category.split('>').map((s) => s.trim()).toList(); final mainCategory = categoryParts.isNotEmpty ? categoryParts.first : '음식점'; final subCategory = categoryParts.length > 1 ? categoryParts.last : mainCategory; // CategoryMapper를 사용한 정규화 final normalizedCategory = CategoryMapper.normalizeNaverCategory(mainCategory, subCategory); return Restaurant( id: id ?? _uuid.v4(), name: result.title, category: normalizedCategory, subCategory: subCategory, description: result.description.isNotEmpty ? result.description : null, phoneNumber: result.telephone.isNotEmpty ? result.telephone : null, roadAddress: result.roadAddress.isNotEmpty ? result.roadAddress : result.address, jibunAddress: result.address, latitude: convertedCoords['latitude'] ?? 37.5665, longitude: convertedCoords['longitude'] ?? 126.9780, naverUrl: result.link.isNotEmpty ? result.link : null, createdAt: DateTime.now(), updatedAt: DateTime.now(), source: DataSource.NAVER, ); } /// GraphQL 응답을 Restaurant 엔티티로 변환 static Restaurant fromGraphQLResponse( Map placeData, { String? id, String? naverUrl, }) { // 영업시간 파싱 String? businessHours; if (placeData['businessHours'] != null) { final hours = placeData['businessHours'] as List; businessHours = hours .where((h) => h['businessHours'] != null) .map((h) => h['businessHours']) .join('\n'); } // 좌표 추출 double? latitude; double? longitude; if (placeData['location'] != null) { latitude = placeData['location']['latitude']?.toDouble(); longitude = placeData['location']['longitude']?.toDouble(); } // 카테고리 파싱 및 정규화 final rawCategory = placeData['category'] ?? '음식점'; final categoryParts = rawCategory.split('>').map((s) => s.trim()).toList(); final mainCategory = categoryParts.isNotEmpty ? categoryParts.first : '음식점'; final subCategory = categoryParts.length > 1 ? categoryParts.last : mainCategory; // CategoryMapper를 사용한 정규화 final normalizedCategory = CategoryMapper.normalizeNaverCategory(mainCategory, subCategory); return Restaurant( id: id ?? _uuid.v4(), name: placeData['name'] ?? '이름 없음', category: normalizedCategory, subCategory: subCategory, description: placeData['description'], phoneNumber: placeData['phone'], roadAddress: placeData['address']?['roadAddress'] ?? '', jibunAddress: placeData['address']?['jibunAddress'] ?? '', latitude: latitude ?? 37.5665, longitude: longitude ?? 126.9780, businessHours: businessHours, naverUrl: naverUrl, createdAt: DateTime.now(), updatedAt: DateTime.now(), source: DataSource.NAVER, ); } /// 네이버 지도 좌표를 WGS84로 변환 static Map _convertNaverMapCoordinates( double? mapx, double? mapy, ) { if (mapx == null || mapy == null) { return {'latitude': null, 'longitude': null}; } // 네이버 지도 좌표계는 KATEC을 사용 // 간단한 변환 공식 (정확도는 떨어지지만 실용적) // 실제로는 더 정교한 변환이 필요할 수 있음 final longitude = mapx / 10000000.0; final latitude = mapy / 10000000.0; return { 'latitude': latitude, 'longitude': longitude, }; } }