import 'package:lunchpick/data/api/naver_api_client.dart';
import 'package:lunchpick/data/api/naver/naver_local_search_api.dart';
import 'package:lunchpick/core/errors/network_exceptions.dart';

/// 테스트용 모의 네이버 API 클라이언트
class MockNaverApiClient extends NaverApiClient {
  final Map<String, String> _urlMappings = {};
  final Map<String, String> _htmlResponses = {};
  final Map<String, dynamic> _searchResults = {};
  final Map<String, dynamic> _graphqlResponses = {};

  /// URL 리다이렉션 매핑 설정
  void setUrlRedirect(String fromUrl, String toUrl) {
    _urlMappings[fromUrl] = toUrl;
  }

  /// HTML 응답 설정
  void setHtmlResponse(String url, String html) {
    _htmlResponses[url] = html;
  }

  /// 검색 결과 설정
  void setSearchResults(String query, List<NaverLocalSearchResult> results) {
    _searchResults[query] = results;
  }

  /// GraphQL 응답 설정
  void setGraphQLResponse(Map<String, dynamic> response) {
    _graphqlResponses['default'] = response;
  }

  /// 에러 시뮬레이션 설정
  bool shouldThrowError = false;
  String errorMessage = '테스트 에러';

  @override
  Future<String> resolveShortUrl(String shortUrl) async {
    if (shouldThrowError && !_throw429) {
      throw Exception(errorMessage);
    }

    // 설정된 매핑이 있으면 반환
    if (_urlMappings.containsKey(shortUrl)) {
      return _urlMappings[shortUrl]!;
    }

    // 기본적으로 원본 URL 반환
    return shortUrl;
  }

  @override
  Future<String> fetchMapPageHtml(String url) async {
    if (shouldThrowError || _throw429) {
      throw const RateLimitException(
        retryAfter: '60',
        originalError: '429 Too Many Requests',
      );
    }

    // 설정된 HTML이 있으면 반환
    if (_htmlResponses.containsKey(url)) {
      return _htmlResponses[url]!;
    }

    // 기본 HTML 반환
    return '''
      <html>
        <head>
          <meta property="og:title" content="기본 테스트 식당">
        </head>
        <body>
          <span class="GHAhO">기본 테스트 식당</span>
        </body>
      </html>
    ''';
  }

  @override
  Future<List<NaverLocalSearchResult>> searchLocal({
    required String query,
    double? latitude,
    double? longitude,
    int display = 20,
    int start = 1,
    String sort = 'random',
  }) async {
    if (shouldThrowError) {
      throw Exception(errorMessage);
    }

    if (_throw429) {
      throw const RateLimitException(
        retryAfter: '60',
        originalError: '429 Too Many Requests',
      );
    }

    // 설정된 검색 결과가 있으면 반환
    if (_searchResults.containsKey(query)) {
      return _searchResults[query] as List<NaverLocalSearchResult>;
    }

    // 기본 검색 결과 반환
    return [
      NaverLocalSearchResult.fromJson({
        'title': '<b>$query</b> 테스트',
        'link': 'https://map.naver.com/p/restaurant/1234567890',
        'category': '한식>김치찌개',
        'description': '테스트 설명',
        'telephone': '02-1234-5678',
        'address': '서울시 종로구',
        'roadAddress': '서울시 종로구 세종대로 110',
        'mapx': 1269784147,
        'mapy': 375666805,
      }),
    ];
  }

  @override
  Future<Map<String, dynamic>> fetchGraphQL({
    required String operationName,
    Map<String, dynamic>? variables,
    required String query,
  }) async {
    if (shouldThrowError || _throw429) {
      throw const RateLimitException(
        retryAfter: '60',
        originalError: '429 Too Many Requests',
      );
    }

    // 설정된 GraphQL 응답이 있으면 반환
    if (_graphqlResponses.containsKey('default')) {
      return {'data': _graphqlResponses['default']};
    }

    // 기본 응답 반환 (places 배열 형태로 반환)
    return {
      'data': {
        'places': [
          {
            'id': '1',
            'name': '기본 테스트 식당',
            'category': '한식',
            'address': '서울시 종로구',
          },
        ],
      },
    };
  }

  Future<String?> fetchPlaceNameFromPcmap(String placeId) async {
    if (shouldThrowError || _throw429) {
      throw Exception(errorMessage);
    }

    // 테스트에서 설정한 값이 있으면 반환
    if (_placeNames.containsKey(placeId)) {
      return _placeNames[placeId];
    }

    // 기본값 반환
    return '기본 테스트 식당';
  }

  // fetchPlaceNameFromPcmap용 응답 저장소
  final Map<String, String> _placeNames = {};

  /// 장소명 설정
  void setPlaceName(String placeId, String placeName) {
    _placeNames[placeId] = placeName;
  }

  // V2 확장 메서드들
  final Map<String, String> _finalRedirectUrls = {};
  final Map<String, String> _secondKoreanTexts = {};
  bool _throw429 = false;

  void setFinalRedirectUrl(String from, String to) {
    _finalRedirectUrls[from] = to;
  }

  void setSecondKoreanText(String url, String text) {
    _secondKoreanTexts[url] = text;
  }

  void setThrow429Error() {
    _throw429 = true;
  }

  @override
  Future<String> getFinalRedirectUrl(String url) async {
    if (_throw429) {
      throw RateLimitException(
        retryAfter: '60',
        originalError: '429 Too Many Requests',
      );
    }

    await Future.delayed(const Duration(milliseconds: 500));
    return _finalRedirectUrls[url] ?? url;
  }

  Future<String?> extractSecondKoreanText(String url) async {
    if (_throw429) {
      throw const RateLimitException(
        retryAfter: '60',
        originalError: '429 Too Many Requests',
      );
    }

    await Future.delayed(const Duration(milliseconds: 500));
    return _secondKoreanTexts[url];
  }

  // fetchKoreanTextsFromPcmap 구현
  final Map<String, Map<String, dynamic>> _koreanTextsData = {};

  void setKoreanTextsData(String placeId, Map<String, dynamic> data) {
    _koreanTextsData[placeId] = data;
  }

  @override
  Future<Map<String, dynamic>> fetchKoreanTextsFromPcmap(String placeId) async {
    if (shouldThrowError || _throw429) {
      throw const RateLimitException(
        retryAfter: '60',
        originalError: '429 Too Many Requests',
      );
    }

    // 설정된 데이터가 있으면 반환
    if (_koreanTextsData.containsKey(placeId)) {
      return _koreanTextsData[placeId]!;
    }

    // 기본 데이터 반환
    return {
      'success': true,
      'koreanTexts': ['기본 테스트 식당'],
      'jsonLdName': '기본 테스트 식당',
      'apolloStateName': null,
    };
  }
}

// NaverLocalSearchResult는 이미 naver_api_client.dart에 정의되어 있음
