import '../../domain/entities/pokemon.dart';

/// Conversion JSON <-> entité Pokemon. Unique endroit de parsing.
class PokemonDto {
  PokemonDto._();

  /// Mappe un nom de type français (API Tyradex) vers l'enum.
  static PokemonType frenchTypeToEnum(String frenchType) {
    const map = {
      'Normal': PokemonType.normal,
      'Combat': PokemonType.fighting,
      'Vol': PokemonType.flying,
      'Poison': PokemonType.poison,
      'Sol': PokemonType.ground,
      'Roche': PokemonType.rock,
      'Insecte': PokemonType.bug,
      'Spectre': PokemonType.ghost,
      'Acier': PokemonType.steel,
      'Feu': PokemonType.fire,
      'Eau': PokemonType.water,
      'Plante': PokemonType.grass,
      'Électrik': PokemonType.electric,
      'Psy': PokemonType.psychic,
      'Glace': PokemonType.ice,
      'Dragon': PokemonType.dragon,
      'Ténèbres': PokemonType.dark,
      'Fée': PokemonType.fairy,
    };
    return map[frenchType] ?? PokemonType.unknown;
  }

  /// Construit une entité depuis la réponse Tyradex (objet unique ou élément de liste).
  /// [fallbackId] sert quand le JSON ne contient pas `pokedex_id`.
  static Pokemon fromTyradexJson(Map<String, dynamic> json, {int? fallbackId}) {
    final id = (json['pokedex_id'] as int?) ??
        fallbackId ??
        (throw ArgumentError('pokedex_id absent et fallbackId non fourni'));
    final nameMap = json['name'] as Map<String, dynamic>?;
    final name = nameMap?['fr'] ?? nameMap?['en'] ?? 'unknown';

    final List types = json['types'] ?? [];
    final type1 =
        types.isNotEmpty ? frenchTypeToEnum(types[0]['name']) : PokemonType.unknown;
    final type2 = types.length > 1 ? frenchTypeToEnum(types[1]['name']) : null;

    final Map<String, dynamic>? stats = json['stats'];
    return Pokemon(
      name: name,
      id: id,
      type1: type1,
      type2: type2,
      hp: stats?['hp'] ?? 0,
      atk: stats?['atk'] ?? 0,
      def: stats?['def'] ?? 0,
      spd: stats?['vit'] ?? 0, // 'vit' = vitesse chez Tyradex
      description: json['category'],
    );
  }

  /// Sérialise pour SQLite.
  static Map<String, dynamic> toDb(Pokemon p) {
    return {
      'name': p.name,
      'id': p.id,
      'type1': p.type1.name,
      'type2': p.type2?.name,
      'hp': p.hp,
      'atk': p.atk,
      'def': p.def,
      'spd': p.spd,
      'description': p.description,
      'isCaught': p.isCaught ? 1 : 0,
      'isSeen': p.isSeen ? 1 : 0,
    };
  }

  /// Reconstruit depuis une ligne SQLite.
  static Pokemon fromDb(Map<String, dynamic> row) {
    return Pokemon(
      name: row['name'],
      id: row['id'],
      type1: PokemonType.values.firstWhere(
        (e) => e.name == row['type1'],
        orElse: () => PokemonType.unknown,
      ),
      type2: row['type2'] != null
          ? PokemonType.values.firstWhere(
              (e) => e.name == row['type2'],
              orElse: () => PokemonType.unknown,
            )
          : null,
      hp: row['hp'] ?? 0,
      atk: row['atk'] ?? 0,
      def: row['def'] ?? 0,
      spd: row['spd'] ?? 0,
      description: row['description'],
      isCaught: row['isCaught'] == 1 || row['isCaught'] == true,
      isSeen: row['isSeen'] == 1 || row['isSeen'] == true,
    );
  }
}
