package dev.lions.unionflow.server.entity;

import dev.lions.unionflow.server.api.enums.abonnement.PlageMembres;
import dev.lions.unionflow.server.api.enums.abonnement.TypeFormule;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import lombok.*;

/**
 * Catalogue des forfaits SaaS UnionFlow.
 *
 * <p>Starter (≤50) → Standard (≤200) → Premium (≤500) → Crystal (illimité)
 * Fourchette tarifaire : 5 000 à 10 000 XOF/mois. Stockage max : 1 Go.
 *
 * <p>Table : {@code formules_abonnement}
 */
@Entity
@Table(
    name = "formules_abonnement",
    indexes = {
      @Index(name = "idx_formule_code_plage", columnList = "code, plage", unique = true),
      @Index(name = "idx_formule_code",       columnList = "code"),
      @Index(name = "idx_formule_plage",      columnList = "plage"),
      @Index(name = "idx_formule_actif",      columnList = "actif")
    })
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class FormuleAbonnement extends BaseEntity {

  @Enumerated(EnumType.STRING)
  @NotNull
  @Column(name = "code", nullable = false, length = 20)
  private TypeFormule code;

  /**
   * Plage de taille d'organisation à laquelle cette formule s'applique.
   * Combinée avec le code de formule, forme une clé unique dans le catalogue.
   */
  @Enumerated(EnumType.STRING)
  @NotNull
  @Column(name = "plage", nullable = false, length = 20)
  private PlageMembres plage;

  @NotBlank
  @Column(name = "libelle", nullable = false, length = 100)
  private String libelle;

  @Column(name = "description", columnDefinition = "TEXT")
  private String description;

  /** Nombre maximum de membres. NULL = illimité (Crystal) */
  @Column(name = "max_membres")
  private Integer maxMembres;

  /** Stockage maximum en Mo — 1 024 Mo (1 Go) par défaut */
  @Builder.Default
  @Column(name = "max_stockage_mo", nullable = false)
  private Integer maxStockageMo = 1024;

  @NotNull
  @DecimalMin("0.00")
  @Digits(integer = 8, fraction = 2)
  @Column(name = "prix_mensuel", nullable = false, precision = 10, scale = 2)
  private BigDecimal prixMensuel;

  @NotNull
  @DecimalMin("0.00")
  @Digits(integer = 8, fraction = 2)
  @Column(name = "prix_annuel", nullable = false, precision = 10, scale = 2)
  private BigDecimal prixAnnuel;

  @Builder.Default
  @Column(name = "ordre_affichage", nullable = false)
  private Integer ordreAffichage = 0;

  // ── Champs Option C (ajoutés en V19) ──────────────────────────────────────

  /** Nom commercial du plan (MICRO, DECOUVERTE, ESSENTIEL, AVANCE, PROFESSIONNEL, ENTERPRISE) */
  @Column(name = "plan_commercial", length = 30)
  private String planCommercial;

  /** Niveau de reporting disponible (BASIQUE, STANDARD, AVANCE) */
  @Column(name = "niveau_reporting", length = 20)
  private String niveauReporting;

  /** Accès à l'API REST (false pour les plans de base) */
  @Builder.Default
  @Column(name = "api_access", nullable = false)
  private Boolean apiAccess = false;

  /** Accès au module de fédération multi-org (ENTERPRISE uniquement) */
  @Builder.Default
  @Column(name = "federation_access", nullable = false)
  private Boolean federationAccess = false;

  /** Support prioritaire inclus */
  @Builder.Default
  @Column(name = "support_prioritaire", nullable = false)
  private Boolean supportPrioritaire = false;

  /** SLA garanti (ex: "99.0%", "99.9%") */
  @Column(name = "sla_garanti", length = 10)
  private String slaGaranti;

  /** Nombre maximum d'administrateurs. NULL = illimité */
  @Column(name = "max_admins")
  private Integer maxAdmins;

  /** Code du provider de paiement par défaut (WAVE, ORANGE_MONEY, MTN_MOMO, PISPI). NULL = global. */
  @Column(name = "provider_defaut", length = 20)
  private String providerDefaut;

  public boolean isIllimitee() {
    return maxMembres == null;
  }

  public boolean accepteNouveauMembre(int quotaActuel) {
    return isIllimitee() || quotaActuel < maxMembres;
  }
}
