import 'package:p_tits_pas/models/user.dart';
import 'package:p_tits_pas/utils/enfant_status_utils.dart';

/// Réponse unifiée GET /dossiers/:numeroDossier. Ticket #119, #107.
class DossierUnifie {
  final String type; // 'am' | 'family'
  final dynamic dossier; // DossierAM | DossierFamille

  DossierUnifie({required this.type, required this.dossier});

  bool get isAm => type == 'am';
  bool get isFamily => type == 'family';

  DossierAM get asAm => dossier as DossierAM;
  DossierFamille get asFamily => dossier as DossierFamille;

  factory DossierUnifie.fromJson(Map<String, dynamic> json) {
    final t = json['type'];
    final raw = t is String ? t : 'family';
    final typeStr = raw.toLowerCase();
    final d = json['dossier'];
    if (d == null || d is! Map<String, dynamic>) {
      throw FormatException('dossier manquant ou invalide');
    }
    final dossierMap = Map<String, dynamic>.from(d as Map);
    // Seul `am` (casse tolérée) charge le dossier AM ; le reste = famille (API : type "family").
    final isAm = typeStr == 'am';
    final dossier = isAm ? DossierAM.fromJson(dossierMap) : DossierFamille.fromJson(dossierMap);
    return DossierUnifie(type: isAm ? 'am' : 'family', dossier: dossier);
  }
}

/// Dossier AM (type: 'am'). Champs alignés API.
class DossierAM {
  final String? numeroDossier;
  final AppUser user;
  final String? numeroAgrement;
  final String? nir;
  final String? presentation;
  final String? dateAgrement;
  final int? nbMaxEnfants;
  final int? placesDisponibles;
  final String? villeResidence;

  DossierAM({
    this.numeroDossier,
    required this.user,
    this.numeroAgrement,
    this.nir,
    this.presentation,
    this.dateAgrement,
    this.nbMaxEnfants,
    this.placesDisponibles,
    this.villeResidence,
  });

  factory DossierAM.fromJson(Map<String, dynamic> json) {
    final userJson = json['user'];
    final userMap = userJson is Map<String, dynamic>
        ? userJson
        : <String, dynamic>{};
    final nbMax = json['nb_max_enfants'];
    final places = json['place_disponible'];
    return DossierAM(
      numeroDossier: json['numero_dossier']?.toString(),
      user: AppUser.fromJson(Map<String, dynamic>.from(userMap)),
      numeroAgrement: json['numero_agrement']?.toString(),
      nir: json['nir']?.toString(),
      presentation: (json['biographie'] ?? json['presentation'])?.toString(),
      dateAgrement: json['date_agrement']?.toString(),
      nbMaxEnfants: nbMax is int ? nbMax : (nbMax is num ? nbMax.toInt() : null),
      placesDisponibles: places is int ? places : (places is num ? places.toInt() : null),
      villeResidence: json['ville_residence']?.toString(),
    );
  }
}

/// Dossier famille (type: 'family'). Champs alignés API.
class DossierFamille {
  final String? numeroDossier;
  final List<ParentDossier> parents;
  final List<EnfantDossier> enfants;
  final String? presentation;

  DossierFamille({
    this.numeroDossier,
    required this.parents,
    required this.enfants,
    this.presentation,
  });

  factory DossierFamille.fromJson(Map<String, dynamic> json) {
    final parentsRaw = json['parents'];
    final parentsList = parentsRaw is List
        ? (parentsRaw)
            .where((e) => e is Map)
            .map((e) => ParentDossier.fromJson(Map<String, dynamic>.from(e as Map)))
            .toList()
        : <ParentDossier>[];
    final enfantsRaw = json['enfants'];
    final enfantsList = enfantsRaw is List
        ? (enfantsRaw)
            .where((e) => e is Map)
            .map((e) => EnfantDossier.fromJson(Map<String, dynamic>.from(e as Map)))
            .toList()
        : <EnfantDossier>[];
    return DossierFamille(
      numeroDossier: json['numero_dossier']?.toString(),
      parents: parentsList,
      enfants: enfantsList,
      presentation: (json['texte_motivation'] ??
              json['presentation'] ??
              json['presentation_dossier'] ??
              json['texteMotivation'] ??
              json['presentationDossier'])
          ?.toString(),
    );
  }

  bool get isEnAttente =>
      parents.any((p) => p.statut == 'en_attente');
}

/// Parent dans un dossier famille (champs user exposés).
class ParentDossier {
  final String id;
  final String email;
  final String? prenom;
  final String? nom;
  final String? telephone;
  final String? adresse;
  final String? ville;
  final String? codePostal;
  final String? dateNaissance;
  final String? genre;
  final String? situationFamiliale;
  final String? creeLe;
  final String? statut;

  ParentDossier({
    required this.id,
    required this.email,
    this.prenom,
    this.nom,
    this.telephone,
    this.adresse,
    this.ville,
    this.codePostal,
    this.dateNaissance,
    this.genre,
    this.situationFamiliale,
    this.creeLe,
    this.statut,
  });

  String get fullName => '${prenom ?? ''} ${nom ?? ''}'.trim();

  factory ParentDossier.fromJson(Map<String, dynamic> json) {
    return ParentDossier(
      id: json['user_id']?.toString() ?? json['id']?.toString() ?? '',
      email: json['email']?.toString() ?? '',
      prenom: json['prenom']?.toString(),
      nom: json['nom']?.toString(),
      telephone: json['telephone']?.toString(),
      adresse: json['adresse']?.toString(),
      ville: json['ville']?.toString(),
      codePostal: json['code_postal']?.toString(),
      dateNaissance: json['date_naissance']?.toString(),
      genre: json['genre']?.toString(),
      situationFamiliale: json['situation_familiale']?.toString(),
      creeLe: json['cree_le']?.toString(),
      statut: json['statut']?.toString(),
    );
  }
}

/// Enfant dans un dossier famille.
class EnfantDossier {
  final String id;
  final String? firstName;
  final String? lastName;
  final String? birthDate;
  final String? gender;
  final String? status;
  final String? dueDate;
  final String? photoUrl;
  final bool consentPhoto;
  final bool estMultiple;

  EnfantDossier({
    required this.id,
    this.firstName,
    this.lastName,
    this.birthDate,
    this.gender,
    this.status,
    this.dueDate,
    this.photoUrl,
    this.consentPhoto = false,
    this.estMultiple = false,
  });

  String get fullName => '${firstName ?? ''} ${lastName ?? ''}'.trim();

  static String? _optionalPhotoUrl(dynamic v) {
    if (v == null) return null;
    if (v is String) {
      final s = v.trim();
      return s.isEmpty ? null : s;
    }
    final s = v.toString().trim();
    return s.isEmpty ? null : s;
  }

  factory EnfantDossier.fromJson(Map<String, dynamic> json) {
    final rawPhoto = json['photo_url'] ?? json['photoUrl'];
    final resolvedPhoto = _optionalPhotoUrl(rawPhoto);
    return EnfantDossier(
      id: json['id']?.toString() ?? '',
      firstName: (json['first_name'] ?? json['prenom'])?.toString(),
      lastName: (json['last_name'] ?? json['nom'])?.toString(),
      birthDate: json['birth_date']?.toString(),
      gender: (json['gender'] ?? json['genre'])?.toString(),
      status: normalizeEnfantStatus(json['status']?.toString()),
      dueDate: json['due_date']?.toString(),
      photoUrl: resolvedPhoto,
      consentPhoto:
          json['consent_photo'] == true || json['consentPhoto'] == true,
      estMultiple:
          json['est_multiple'] == true || json['estMultiple'] == true,
    );
  }
}
