import 'dart:convert';
import 'package:http/http.dart' as http;
import '../../core/config/app_constants.dart';
import '../../core/logger.dart';
import '../../domain/entities/pokemon.dart';
import '../dto/pokemon_dto.dart';

/// Accès distant à l'API Tyradex.
class PokemonRemoteDataSource {
  final http.Client _client;
  final String languageCode;

  PokemonRemoteDataSource({http.Client? client, this.languageCode = 'fr'})
      : _client = client ?? http.Client();

  Future<Pokemon> getById(int id) async {
    AppLogger.info('API: fetching Pokémon $id (lang: $languageCode)');
    final response = await _client
        .get(Uri.https(AppConstants.apiBaseUrl, '${AppConstants.apiPokemonPath}/$id'));
    if (response.statusCode != 200) {
      throw Exception(
          'Erreur récupération du pokémon $id, code ${response.statusCode}');
    }
    final json = jsonDecode(response.body) as Map<String, dynamic>;
    return PokemonDto.fromTyradexJson(json,
        fallbackId: id, languageCode: languageCode);
  }

  /// Fetches the English genus (category) from PokéAPI for a given Pokémon id.
  /// Returns null on any error (network, missing entry, etc.).
  Future<String?> getEnglishGenus(int id) async {
    try {
      final response = await _client
          .get(Uri.https('pokeapi.co', '/api/v2/pokemon-species/$id/'));
      if (response.statusCode != 200) return null;
      final json = jsonDecode(response.body) as Map<String, dynamic>;
      final genera = json['genera'] as List<dynamic>? ?? [];
      for (final g in genera) {
        final lang = (g['language'] as Map<String, dynamic>?)?['name'];
        if (lang == 'en') return g['genus'] as String?;
      }
    } catch (_) {}
    return null;
  }

  Future<List<Pokemon>> getAll() async {
    AppLogger.info('API: fetching ALL Pokémon (lang: $languageCode)');
    final response = await _client
        .get(Uri.https(AppConstants.apiBaseUrl, AppConstants.apiPokemonPath));
    if (response.statusCode != 200) {
      throw Exception('Failed to load pokemon (code ${response.statusCode})');
    }
    final List<dynamic> jsonList = jsonDecode(response.body);
    final result = <Pokemon>[];
    for (final json in jsonList) {
      if (json['pokedex_id'] == 0) continue;
      try {
        result.add(PokemonDto.fromTyradexJson(
          json as Map<String, dynamic>,
          languageCode: languageCode,
        ));
      } catch (e, st) {
        AppLogger.error('Parsing pokemon échoué: ${json['name']}', e, st);
      }
    }
    return result;
  }
}
