package dev.lions.unionflow.server.api.dto.solidarite;

import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
import dev.lions.unionflow.server.api.enums.solidarite.PrioriteAide;

import jakarta.validation.constraints.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.Builder;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * DTO pour les demandes d'aide dans le système de solidarité
 * 
 * Ce DTO représente une demande d'aide complète avec toutes les informations
 * nécessaires pour le traitement, l'évaluation et le suivi.
 * 
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-16
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DemandeAideDTO {
    
    // === IDENTIFICATION ===
    
    /**
     * Identifiant unique de la demande d'aide
     */
    private String id;
    
    /**
     * Numéro de référence de la demande (généré automatiquement)
     */
    @Pattern(regexp = "^DA-\\d{4}-\\d{6}$", message = "Le numéro de référence doit suivre le format DA-YYYY-NNNNNN")
    private String numeroReference;
    
    // === INFORMATIONS DE BASE ===
    
    /**
     * Type d'aide demandée
     */
    @NotNull(message = "Le type d'aide est obligatoire")
    private TypeAide typeAide;
    
    /**
     * Titre court de la demande
     */
    @NotBlank(message = "Le titre est obligatoire")
    @Size(min = 10, max = 100, message = "Le titre doit contenir entre 10 et 100 caractères")
    private String titre;
    
    /**
     * Description détaillée de la demande
     */
    @NotBlank(message = "La description est obligatoire")
    @Size(min = 50, max = 2000, message = "La description doit contenir entre 50 et 2000 caractères")
    private String description;
    
    /**
     * Justification de la demande
     */
    @Size(max = 1000, message = "La justification ne peut pas dépasser 1000 caractères")
    private String justification;
    
    // === MONTANT ET FINANCES ===
    
    /**
     * Montant demandé (si applicable)
     */
    @DecimalMin(value = "0.0", inclusive = false, message = "Le montant doit être positif")
    @DecimalMax(value = "1000000.0", message = "Le montant ne peut pas dépasser 1 000 000 FCFA")
    private Double montantDemande;
    
    /**
     * Montant approuvé (si différent du montant demandé)
     */
    @DecimalMin(value = "0.0", inclusive = false, message = "Le montant approuvé doit être positif")
    private Double montantApprouve;
    
    /**
     * Montant versé effectivement
     */
    @DecimalMin(value = "0.0", inclusive = false, message = "Le montant versé doit être positif")
    private Double montantVerse;
    
    /**
     * Devise du montant
     */
    @Builder.Default
    private String devise = "FCFA";
    
    // === ACTEURS ===
    
    /**
     * Identifiant du demandeur
     */
    @NotBlank(message = "L'identifiant du demandeur est obligatoire")
    private String demandeurId;
    
    /**
     * Nom complet du demandeur
     */
    private String demandeurNom;
    
    /**
     * Identifiant de l'évaluateur assigné
     */
    private String evaluateurId;
    
    /**
     * Nom de l'évaluateur
     */
    private String evaluateurNom;
    
    /**
     * Identifiant de l'approbateur
     */
    private String approvateurId;
    
    /**
     * Nom de l'approbateur
     */
    private String approvateurNom;
    
    /**
     * Identifiant de l'organisation
     */
    @NotBlank(message = "L'identifiant de l'organisation est obligatoire")
    private String organisationId;
    
    // === STATUT ET PRIORITÉ ===
    
    /**
     * Statut actuel de la demande
     */
    @NotNull(message = "Le statut est obligatoire")
    @Builder.Default
    private StatutAide statut = StatutAide.BROUILLON;
    
    /**
     * Priorité de la demande
     */
    @NotNull(message = "La priorité est obligatoire")
    @Builder.Default
    private PrioriteAide priorite = PrioriteAide.NORMALE;
    
    /**
     * Motif de rejet (si applicable)
     */
    @Size(max = 500, message = "Le motif de rejet ne peut pas dépasser 500 caractères")
    private String motifRejet;
    
    /**
     * Commentaires de l'évaluateur
     */
    @Size(max = 1000, message = "Les commentaires ne peuvent pas dépasser 1000 caractères")
    private String commentairesEvaluateur;
    
    // === DATES ===
    
    /**
     * Date de création de la demande
     */
    @NotNull(message = "La date de création est obligatoire")
    @Builder.Default
    private LocalDateTime dateCreation = LocalDateTime.now();
    
    /**
     * Date de soumission de la demande
     */
    private LocalDateTime dateSoumission;
    
    /**
     * Date limite de traitement
     */
    private LocalDateTime dateLimiteTraitement;
    
    /**
     * Date d'évaluation
     */
    private LocalDateTime dateEvaluation;
    
    /**
     * Date d'approbation
     */
    private LocalDateTime dateApprobation;
    
    /**
     * Date de versement
     */
    private LocalDateTime dateVersement;
    
    /**
     * Date de clôture
     */
    private LocalDateTime dateCloture;
    
    /**
     * Date de dernière modification
     */
    @Builder.Default
    private LocalDateTime dateModification = LocalDateTime.now();
    
    // === INFORMATIONS COMPLÉMENTAIRES ===
    
    /**
     * Pièces justificatives attachées
     */
    private List<PieceJustificativeDTO> piecesJustificatives;
    
    /**
     * Bénéficiaires de l'aide (si différents du demandeur)
     */
    private List<BeneficiaireAideDTO> beneficiaires;
    
    /**
     * Historique des changements de statut
     */
    private List<HistoriqueStatutDTO> historiqueStatuts;
    
    /**
     * Commentaires et échanges
     */
    private List<CommentaireAideDTO> commentaires;
    
    /**
     * Données personnalisées spécifiques au type d'aide
     */
    private Map<String, Object> donneesPersonnalisees;
    
    /**
     * Tags pour catégorisation
     */
    private List<String> tags;
    
    // === MÉTADONNÉES ===
    
    /**
     * Indique si la demande est confidentielle
     */
    @Builder.Default
    private Boolean estConfidentielle = false;
    
    /**
     * Indique si la demande nécessite un suivi
     */
    @Builder.Default
    private Boolean necessiteSuivi = false;
    
    /**
     * Score de priorité calculé automatiquement
     */
    private Double scorePriorite;
    
    /**
     * Nombre de vues de la demande
     */
    @Builder.Default
    private Integer nombreVues = 0;
    
    /**
     * Version du document (pour gestion des conflits)
     */
    @Builder.Default
    private Integer version = 1;
    
    /**
     * Informations de géolocalisation (si pertinent)
     */
    private LocalisationDTO localisation;
    
    /**
     * Informations de contact d'urgence
     */
    private ContactUrgenceDTO contactUrgence;
    
    // === MÉTHODES UTILITAIRES ===
    
    /**
     * Vérifie si la demande est modifiable
     */
    public boolean isModifiable() {
        return statut != null && statut.permetModification();
    }
    
    /**
     * Vérifie si la demande peut être annulée
     */
    public boolean peutEtreAnnulee() {
        return statut != null && statut.permetAnnulation();
    }
    
    /**
     * Vérifie si la demande est urgente
     */
    public boolean isUrgente() {
        return priorite != null && priorite.isUrgente();
    }
    
    /**
     * Vérifie si la demande est terminée
     */
    public boolean isTerminee() {
        return statut != null && statut.isEstFinal();
    }
    
    /**
     * Vérifie si la demande est en succès
     */
    public boolean isEnSucces() {
        return statut != null && statut.isSucces();
    }
    
    /**
     * Calcule le pourcentage d'avancement
     */
    public double getPourcentageAvancement() {
        if (statut == null) return 0.0;
        
        return switch (statut) {
            case BROUILLON -> 5.0;
            case SOUMISE -> 10.0;
            case EN_ATTENTE -> 20.0;
            case EN_COURS_EVALUATION -> 40.0;
            case INFORMATIONS_REQUISES -> 35.0;
            case APPROUVEE, APPROUVEE_PARTIELLEMENT -> 60.0;
            case EN_COURS_TRAITEMENT -> 70.0;
            case EN_COURS_VERSEMENT -> 85.0;
            case VERSEE, LIVREE, TERMINEE -> 100.0;
            case REJETEE, ANNULEE, EXPIREE -> 100.0;
            case SUSPENDUE -> 50.0;
            case EN_SUIVI -> 95.0;
            case CLOTUREE -> 100.0;
        };
    }
    
    /**
     * Retourne le délai restant en heures
     */
    public long getDelaiRestantHeures() {
        if (dateLimiteTraitement == null) return -1;
        
        LocalDateTime maintenant = LocalDateTime.now();
        if (maintenant.isAfter(dateLimiteTraitement)) return 0;
        
        return java.time.Duration.between(maintenant, dateLimiteTraitement).toHours();
    }
    
    /**
     * Vérifie si le délai est dépassé
     */
    public boolean isDelaiDepasse() {
        return getDelaiRestantHeures() == 0;
    }
    
    /**
     * Retourne la durée de traitement en jours
     */
    public long getDureeTraitementJours() {
        if (dateCreation == null) return 0;
        
        LocalDateTime dateFin = dateCloture != null ? dateCloture : LocalDateTime.now();
        return java.time.Duration.between(dateCreation, dateFin).toDays();
    }
}
