import '../../domain/entities/pokemon.dart'; /// Conversion JSON <-> entité Pokemon. Unique endroit de parsing. class PokemonDto { PokemonDto._(); static PokemonType _frenchTypeToEnum(String type) { 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[type] ?? PokemonType.unknown; } // Tyradex always returns type names in French regardless of endpoint language. static PokemonType _typeToEnum(String typeName, String languageCode) { return _frenchTypeToEnum(typeName); } /// Construit une entité depuis la réponse Tyradex. /// [languageCode] détermine quelle langue utiliser pour [name] ('fr' ou 'en'). static Pokemon fromTyradexJson( Map json, { int? fallbackId, String languageCode = 'fr', }) { final id = (json['pokedex_id'] as int?) ?? fallbackId ?? (throw ArgumentError('pokedex_id absent et fallbackId non fourni')); final nameMap = json['name'] as Map?; final nameFr = nameMap?['fr'] as String? ?? 'unknown'; final nameEn = nameMap?['en'] as String? ?? nameFr; final name = languageCode == 'en' ? nameEn : nameFr; final List types = json['types'] ?? []; // Tyradex retourne toujours les types dans la langue du endpoint (fr ou en). final type1 = types.isNotEmpty ? _typeToEnum(types[0]['name'] as String, languageCode) : PokemonType.unknown; final type2 = types.length > 1 ? _typeToEnum(types[1]['name'] as String, languageCode) : null; final Map? stats = json['stats']; // Tyradex expose 'category' (FR) et parfois 'category_en' (EN). final descFr = json['category'] as String?; final descEn = (json['category_en'] ?? json['category']) as String?; return Pokemon( name: name, nameFr: nameFr, nameEn: nameEn, id: id, type1: type1, type2: type2, hp: stats?['hp'] ?? 0, atk: stats?['atk'] ?? 0, def: stats?['def'] ?? 0, spd: stats?['vit'] ?? 0, description: descFr, descriptionEn: descEn, ); } /// Sérialise pour SQLite (stocke les deux noms et descriptions). static Map toDb(Pokemon p) { return { 'name': p.name, 'name_fr': p.nameFr ?? p.name, 'name_en': p.nameEn ?? 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, 'description_en': p.descriptionEn, 'isCaught': p.isCaught ? 1 : 0, 'isSeen': p.isSeen ? 1 : 0, }; } /// Reconstruit depuis une ligne SQLite. /// [languageCode] détermine quel nom afficher. static Pokemon fromDb(Map row, {String languageCode = 'fr'}) { final nameFr = row['name_fr'] as String? ?? row['name'] as String; final nameEn = row['name_en'] as String? ?? nameFr; final name = languageCode == 'en' ? nameEn : nameFr; return Pokemon( name: name, nameFr: nameFr, nameEn: nameEn, 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'], descriptionEn: row['description_en'] as String?, isCaught: row['isCaught'] == 1 || row['isCaught'] == true, isSeen: row['isSeen'] == 1 || row['isSeen'] == true, ); } }