import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:lunchpick/core/utils/app_logger.dart';

import '../../core/network/network_client.dart';
import '../../core/errors/network_exceptions.dart';
import '../../domain/entities/restaurant.dart';
import 'naver/naver_local_search_api.dart';
import 'naver/naver_url_resolver.dart';
import 'naver/naver_graphql_api.dart';
import 'naver/naver_proxy_client.dart';
import 'converters/naver_data_converter.dart';
import '../datasources/remote/naver_html_extractor.dart';

/// 네이버 API 통합 클라이언트
///
/// 네이버 오픈 API와 지도 서비스를 위한 통합 클라이언트입니다.
/// 내부적으로 각 기능별로 분리된 API 클라이언트를 사용합니다.
class NaverApiClient {
  final NetworkClient _networkClient;

  // 분리된 API 클라이언트들
  late final NaverLocalSearchApi _localSearchApi;
  late final NaverUrlResolver _urlResolver;
  late final NaverGraphQLApi _graphqlApi;
  late final NaverProxyClient _proxyClient;

  NaverApiClient({NetworkClient? networkClient})
    : _networkClient = networkClient ?? NetworkClient() {
    // 각 API 클라이언트 초기화
    _localSearchApi = NaverLocalSearchApi(networkClient: _networkClient);
    _urlResolver = NaverUrlResolver(networkClient: _networkClient);
    _graphqlApi = NaverGraphQLApi(networkClient: _networkClient);
    _proxyClient = NaverProxyClient(networkClient: _networkClient);
  }

  /// 네이버 로컬 검색 API 호출
  ///
  /// 검색어와 좌표를 기반으로 주변 식당을 검색합니다.
  Future<List<NaverLocalSearchResult>> searchLocal({
    required String query,
    double? latitude,
    double? longitude,
    int display = 20,
    int start = 1,
    String sort = 'random',
  }) async {
    return _localSearchApi.searchLocal(
      query: query,
      latitude: latitude,
      longitude: longitude,
      display: display,
      start: start,
      sort: sort,
    );
  }

  /// 단축 URL을 실제 URL로 변환
  Future<String> resolveShortUrl(String shortUrl) async {
    return _urlResolver.resolveShortUrl(shortUrl);
  }

  /// 네이버 지도 페이지 HTML 가져오기
  Future<String> fetchMapPageHtml(String url) async {
    try {
      // 웹 환경에서는 프록시 사용
      if (kIsWeb) {
        return await _proxyClient.fetchViaProxy(url);
      }

      // 모바일 환경에서는 직접 요청
      final response = await _networkClient.get<String>(
        url,
        options: Options(
          responseType: ResponseType.plain,
          headers: {
            'User-Agent':
                'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1',
            'Accept':
                'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Accept-Language': 'ko-KR,ko;q=0.9,en;q=0.8',
          },
        ),
      );

      if (response.data == null || response.data!.isEmpty) {
        throw ParseException(message: 'HTML 응답이 비어있습니다');
      }

      return response.data!;
    } on DioException catch (e) {
      AppLogger.error(
        'fetchMapPageHtml error: $e',
        error: e,
        stackTrace: e.stackTrace,
      );

      if (e.error is NetworkException) {
        throw e.error!;
      }

      throw ServerException(
        message: '페이지를 불러올 수 없습니다',
        statusCode: e.response?.statusCode ?? 500,
        originalError: e,
      );
    }
  }

  /// GraphQL API 호출
  Future<Map<String, dynamic>> fetchGraphQL({
    required String operationName,
    required String query,
    Map<String, dynamic>? variables,
  }) async {
    return _graphqlApi.fetchGraphQL(
      operationName: operationName,
      query: query,
      variables: variables,
    );
  }

  /// pcmap URL에서 한글 텍스트 리스트 가져오기
  ///
  /// restaurant/{ID}/home 형식의 URL에서 모든 한글 텍스트를 추출합니다.
  Future<Map<String, dynamic>> fetchKoreanTextsFromPcmap(String placeId) async {
    // restaurant 타입 URL 사용
    final pcmapUrl = 'https://pcmap.place.naver.com/restaurant/$placeId/home';

    try {
      AppLogger.debug('========== 네이버 pcmap 한글 추출 시작 ==========');
      AppLogger.debug('요청 URL: $pcmapUrl');
      AppLogger.debug('Place ID: $placeId');

      String html;
      if (kIsWeb) {
        // 웹 환경에서는 프록시 사용
        html = await _proxyClient.fetchViaProxy(pcmapUrl);
      } else {
        // 모바일 환경에서는 직접 요청
        final response = await _networkClient.get<String>(
          pcmapUrl,
          options: Options(
            responseType: ResponseType.plain,
            headers: {
              'User-Agent':
                  'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1',
              'Accept': 'text/html,application/xhtml+xml',
              'Accept-Language': 'ko-KR,ko;q=0.9,en;q=0.8',
              'Referer': 'https://map.naver.com/',
            },
          ),
        );

        if (response.statusCode != 200 || response.data == null) {
          AppLogger.error(
            'NaverApiClient: pcmap 페이지 로드 실패 - status: ${response.statusCode}',
          );
          return {
            'success': false,
            'error': 'HTTP ${response.statusCode}',
            'koreanTexts': <String>[],
          };
        }

        html = response.data!;
      }

      // 모든 한글 텍스트 추출
      final koreanTexts = NaverHtmlExtractor.extractAllValidKoreanTexts(html);

      // JSON-LD 데이터 추출 시도
      final jsonLdName = NaverHtmlExtractor.extractPlaceNameFromJsonLd(html);

      // Apollo State 데이터 추출 시도
      final apolloName = NaverHtmlExtractor.extractPlaceNameFromApolloState(
        html,
      );

      AppLogger.debug('========== 추출 결과 ==========');
      AppLogger.debug('총 한글 텍스트 수: ${koreanTexts.length}');
      AppLogger.debug('JSON-LD 상호명: $jsonLdName');
      AppLogger.debug('Apollo State 상호명: $apolloName');
      AppLogger.debug('=====================================');

      return {
        'success': true,
        'placeId': placeId,
        'url': pcmapUrl,
        'koreanTexts': koreanTexts,
        'jsonLdName': jsonLdName,
        'apolloStateName': apolloName,
        'extractedAt': DateTime.now().toIso8601String(),
      };
    } catch (e, stackTrace) {
      AppLogger.error(
        'NaverApiClient: pcmap 페이지 파싱 실패 - $e',
        error: e,
        stackTrace: stackTrace,
      );
      return {
        'success': false,
        'error': e.toString(),
        'koreanTexts': <String>[],
      };
    }
  }

  /// 최종 리다이렉트 URL 가져오기
  Future<String> getFinalRedirectUrl(String url) async {
    return _urlResolver.getFinalRedirectUrl(url);
  }

  /// 리소스 정리
  void dispose() {
    _localSearchApi.dispose();
    _urlResolver.dispose();
    _graphqlApi.dispose();
    _proxyClient.dispose();
    _networkClient.dispose();
  }
}

/// NaverLocalSearchResult를 Restaurant으로 변환하는 확장 메서드
extension NaverLocalSearchResultExtension on NaverLocalSearchResult {
  Restaurant toRestaurant({required String id}) {
    return NaverDataConverter.fromLocalSearchResult(this, id: id);
  }
}
