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

/**
 * Énumération des priorités d'aide dans le système de solidarité
 *
 * <p>Cette énumération définit les niveaux de priorité pour les demandes d'aide, permettant de
 * prioriser le traitement selon l'urgence de la situation.
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-16
 */
public enum PrioriteAide {
  CRITIQUE(
      "Critique",
      "critical",
      1,
      "Situation critique nécessitant une intervention immédiate",
      "#F44336",
      "emergency",
      24,
      true,
      true),

  URGENTE(
      "Urgente",
      "urgent",
      2,
      "Situation urgente nécessitant une réponse rapide",
      "#FF5722",
      "priority_high",
      72,
      true,
      false),

  ELEVEE(
      "Élevée",
      "high",
      3,
      "Priorité élevée, traitement dans les meilleurs délais",
      "#FF9800",
      "keyboard_arrow_up",
      168,
      false,
      false),

  NORMALE(
      "Normale",
      "normal",
      4,
      "Priorité normale, traitement selon les délais standards",
      "#2196F3",
      "remove",
      336,
      false,
      false),

  FAIBLE(
      "Faible",
      "low",
      5,
      "Priorité faible, traitement quand les ressources le permettent",
      "#4CAF50",
      "keyboard_arrow_down",
      720,
      false,
      false);

  private final String libelle;
  private final String code;
  private final int niveau;
  private final String description;
  private final String couleur;
  private final String icone;
  private final int delaiTraitementHeures;
  private final boolean notificationImmediate;
  private final boolean escaladeAutomatique;

  PrioriteAide(
      String libelle,
      String code,
      int niveau,
      String description,
      String couleur,
      String icone,
      int delaiTraitementHeures,
      boolean notificationImmediate,
      boolean escaladeAutomatique) {
    this.libelle = libelle;
    this.code = code;
    this.niveau = niveau;
    this.description = description;
    this.couleur = couleur;
    this.icone = icone;
    this.delaiTraitementHeures = delaiTraitementHeures;
    this.notificationImmediate = notificationImmediate;
    this.escaladeAutomatique = escaladeAutomatique;
  }

  // === GETTERS ===

  public String getLibelle() {
    return libelle;
  }

  public String getCode() {
    return code;
  }

  public int getNiveau() {
    return niveau;
  }

  public String getDescription() {
    return description;
  }

  public String getCouleur() {
    return couleur;
  }

  public String getIcone() {
    return icone;
  }

  public int getDelaiTraitementHeures() {
    return delaiTraitementHeures;
  }

  public boolean isNotificationImmediate() {
    return notificationImmediate;
  }

  public boolean isEscaladeAutomatique() {
    return escaladeAutomatique;
  }

  // === MÉTHODES UTILITAIRES ===

  /** Vérifie si la priorité est critique ou urgente */
  public boolean isUrgente() {
    return this == CRITIQUE || this == URGENTE;
  }

  /** Vérifie si la priorité nécessite un traitement immédiat */
  public boolean necessiteTraitementImmediat() {
    return niveau <= 2;
  }

  /** Retourne la date limite de traitement */
  public java.time.LocalDateTime getDateLimiteTraitement() {
    return java.time.LocalDateTime.now().plusHours(delaiTraitementHeures);
  }

  /** Retourne la priorité suivante (escalade) */
  public PrioriteAide getPrioriteEscalade() {
    return switch (this) {
      case FAIBLE -> NORMALE;
      case NORMALE -> ELEVEE;
      case ELEVEE -> URGENTE;
      case URGENTE -> CRITIQUE;
      case CRITIQUE -> CRITIQUE; // Déjà au maximum
    };
  }

  /** Détermine la priorité basée sur le type d'aide */
  public static PrioriteAide determinerPriorite(TypeAide typeAide) {
    if (typeAide.isUrgent()) {
      return switch (typeAide) {
        case AIDE_FINANCIERE_URGENTE, AIDE_FRAIS_MEDICAUX -> CRITIQUE;
        case HEBERGEMENT_URGENCE, AIDE_ALIMENTAIRE -> URGENTE;
        default -> ELEVEE;
      };
    }

    if (typeAide.getPriorite().equals("important")) {
      return ELEVEE;
    }

    return NORMALE;
  }

  /** Retourne les priorités urgentes */
  public static java.util.List<PrioriteAide> getPrioritesUrgentes() {
    return java.util.Arrays.stream(values())
        .filter(PrioriteAide::isUrgente)
        .collect(java.util.stream.Collectors.toList());
  }

  /** Retourne les priorités par niveau croissant */
  public static java.util.List<PrioriteAide> getParNiveauCroissant() {
    return java.util.Arrays.stream(values())
        .sorted(java.util.Comparator.comparingInt(PrioriteAide::getNiveau))
        .collect(java.util.stream.Collectors.toList());
  }

  /** Retourne les priorités par niveau décroissant */
  public static java.util.List<PrioriteAide> getParNiveauDecroissant() {
    return java.util.Arrays.stream(values())
        .sorted(java.util.Comparator.comparingInt(PrioriteAide::getNiveau).reversed())
        .collect(java.util.stream.Collectors.toList());
  }

  /** Trouve la priorité par code */
  public static PrioriteAide parCode(String code) {
    return java.util.Arrays.stream(values())
        .filter(p -> p.getCode().equals(code))
        .findFirst()
        .orElse(NORMALE);
  }

  /** Calcule le score de priorité (plus bas = plus prioritaire) */
  public double getScorePriorite() {
    double score = niveau;

    // Bonus pour notification immédiate
    if (notificationImmediate) score -= 0.5;

    // Bonus pour escalade automatique
    if (escaladeAutomatique) score -= 0.3;

    // Malus pour délai long
    if (delaiTraitementHeures > 168) score += 0.2;

    return score;
  }

  /** Vérifie si le délai de traitement est dépassé */
  public boolean isDelaiDepasse(java.time.LocalDateTime dateCreation) {
    return isDelaiDepasse(dateCreation, java.time.LocalDateTime.now());
  }

  /** Vérifie si le délai de traitement est dépassé (version avec date de référence) */
  public boolean isDelaiDepasse(java.time.LocalDateTime dateCreation, java.time.LocalDateTime maintenant) {
    java.time.LocalDateTime dateLimite = dateCreation.plusHours(delaiTraitementHeures);
    // Utilise isAfter strictement : le délai est dépassé seulement si on est APRÈS la limite
    // Si on est exactement à la limite, le délai n'est pas encore dépassé
    return maintenant.isAfter(dateLimite);
  }

  /** Calcule le pourcentage de temps écoulé */
  public double getPourcentageTempsEcoule(java.time.LocalDateTime dateCreation) {
    java.time.LocalDateTime maintenant = java.time.LocalDateTime.now();
    java.time.LocalDateTime dateLimite = dateCreation.plusHours(delaiTraitementHeures);

    long dureeTotal = java.time.Duration.between(dateCreation, dateLimite).toMinutes();
    long dureeEcoulee = java.time.Duration.between(dateCreation, maintenant).toMinutes();

    if (dureeTotal <= 0) return 100.0;

    return Math.min(100.0, (dureeEcoulee * 100.0) / dureeTotal);
  }

  /** Retourne le message d'alerte selon le temps écoulé */
  public String getMessageAlerte(java.time.LocalDateTime dateCreation) {
    double pourcentage = getPourcentageTempsEcoule(dateCreation);

    if (pourcentage >= 100) {
      return "Délai de traitement dépassé !";
    } else if (pourcentage >= 80) {
      return "Délai de traitement bientôt dépassé";
    } else if (pourcentage >= 60) {
      return "Plus de la moitié du délai écoulé";
    }

    return null;
  }
}
