/**
 * Types du module Factures (TL-301) — miroir exact des props construites par
 * `App\Services\Factures\FacturePageService`. Aucun montant n'est calculé côté
 * navigateur : les totaux arrivent du serveur (route `factures.apercu`).
 */

export type FactureType = 'facture' | 'proforma' | 'avoir';
export type FactureStatut = 'brouillon' | 'emise' | 'payee' | 'annulee' | 'convertie';
export type Devise = 'TND' | 'EUR' | 'USD';
export type ClientType = 'proprietaire' | 'client' | 'libre';
/**
 * Nature de l'identifiant du client — décide du libellé imprimé (« MF : », « CIN : »…).
 * « aucun » : un particulier sans identifiant, choisi explicitement (un « MF » vide bloque l'émission).
 */
export type IdentifiantType = 'mf' | 'cin' | 'passeport' | 'aucun';

export interface DeviseConfig {
    decimales: number;
    symbole: string;
}

export interface Article {
    reference: string;
    designation: string;
    taux_tva: number;
}

export interface FactureOptions {
    devises: Record<Devise, DeviseConfig>;
    taux_tva: number[];
    tva_defaut: number;
    echeances: number[];
    echeance_defaut: number;
    articles: Article[];
    timbre: number;
    canaux: Record<string, string>;
    import_actif: boolean;
}

export interface FactureDroits {
    create: boolean;
    emettre: boolean;
    delete: boolean;
}

/** Une ligne de la liste. */
export interface FactureListe {
    id: number;
    numero: string | null;
    type: FactureType;
    statut: FactureStatut;
    en_retard: boolean;
    date_facture: string; // ISO
    date_echeance: string | null;
    client_nom: string;
    devise: Devise;
    total_ttc: number;
    origine: string;
    origine_libelle: string | null;
    envoyee_le: string | null;
    payee_le: string | null;
}

/** Période de la liste (PeriodeListe côté serveur), bornes ISO incluses. */
export interface PeriodeListe {
    mode: 'mois' | 'annee' | 'personnalise';
    du: string;
    au: string;
    /** Année que montre la bande des mois. */
    annee: number;
    /** 1 → 12 en mode mois, sinon null. */
    mois: number | null;
}

export interface FacturesIndexProps {
    factures: FactureListe[];
    periode: PeriodeListe;
    /** Pièces par mois de `periode.annee`, clés 1 → 12. */
    repartition: Record<number, number>;
    kpis: {
        /** Toutes périodes : factures émises non payées, avoirs partiels déduits. */
        a_encaisser: Record<Devise, number>;
        /** Toutes périodes. */
        en_retard: number;
        /** Date (ISO) de la plus ancienne facture impayée, ou null. */
        impayees_depuis: string | null;
        brouillons: number;
        /** Factures émises moins avoirs émis, HT, par devise. */
        facture_ht: Record<Devise, number>;
        nb_emises: number;
    };
    prochains: Record<FactureType, string>;
    /** Date (ISO) de la dernière pièce Swiver déclarée à la reprise, par série. */
    planchers: Record<FactureType, string | null>;
    config: FactureOptions;
    can: FactureDroits;
}

// `type` et non `interface` pour ces deux-là : `useForm<T>()` d'Inertia exige un
// type indexable (FormDataType), ce qu'une interface n'est jamais.
export type LigneForm = {
    reference: string | null;
    designation: string;
    quantite: number;
    prix_unitaire_ht: number;
    remise_pct: number;
    taux_tva: number;
    source_type: 'commission' | 'reservation' | null;
    source_id: number | null;
    /** Rapport de versement Airbnb : clé du séjour (voyageur, dates, annonce), repassée telle quelle. */
    source_cle?: string | null;
    /** Relevé bancaire : versement sous lequel la ligne est rangée. */
    groupe?: string | null;
    /** Relevé bancaire : montant d'origine × taux BCT du jour = PU HT (effacé par le serveur si le PU change). */
    montant_origine?: number | null;
    devise_origine?: string | null;
    taux_change?: number | null;
    taux_date?: string | null;
};

/** Ce que l'éditeur envoie à `factures.store`, `factures.update` et `factures.apercu`. */
export type FactureForm = {
    type: FactureType;
    client_type: ClientType | null;
    client_ref_id: number | null;
    client_nom: string;
    client_adresse: string | null;
    client_matricule_fiscal: string | null;
    client_identifiant_type: IdentifiantType;
    client_email: string | null;
    date_facture: string; // ISO YYYY-MM-DD
    echeance_jours: number;
    devise: Devise;
    note_entete: string | null;
    note_pied: string | null;
    /** Fondement légal d'une ligne à 0 % de TVA — exigé à l'émission, imprimé sous le détail de la TVA. */
    mention_exoneration: string | null;
    timbre_fiscal: boolean;
    origine: string | null;
    origine_libelle: string | null;
    reservation_id: number | null;
    lignes: LigneForm[];
};

export interface FactureLiee {
    id: number;
    numero: string | null;
    type: FactureType;
    statut?: FactureStatut;
}

/** En-tête d'une facture enregistrée (null tant que l'éditeur est vierge). */
export interface FactureEntete {
    id: number;
    numero: string | null;
    type: FactureType;
    statut: FactureStatut;
    en_retard: boolean;
    origine: string;
    origine_libelle: string | null;
    reservation_id: number | null;
    emise_le: string | null;
    envoyee_le: string | null;
    envoyee_a: string | null;
    payee_le: string | null;
    total_ttc: number;
    devise: Devise;
    client_email: string | null;
    document_source: boolean;
    facture_origine: FactureLiee | null;
    derivees: FactureLiee[];
}

export interface ControleImport {
    libelle: string;
    calcule: number;
    document: number | null;
    ok: boolean | null;
}

/** Bandeau d'information de l'éditeur : réservation d'origine, ou lecture d'un PDF. */
export type ContexteEditeur =
    | {
          type: 'reservation';
          reservation: string;
          reservation_id: number;
          /** « Airbnb », « Booking.com »… ; null pour une réservation directe. */
          canal: string | null;
          /** Montant total TTC de la réservation (prolongations en dinars comprises sur une facture en TND), sans change. */
          montant_sejour: number;
          /** Devise de la réservation — la note d'écart se tait si l'utilisateur en change. */
          devise: Devise;
          /** Devise de la réservation hors TND/EUR/USD : total repris converti en dinars. */
          devise_origine: string | null;
          /** Prolongations (en dinars) laissées hors d'une facture en devise. */
          prolongations_tnd: number | null;
          deja_facturee: { id: number; numero: string | null; statut: FactureStatut }[];
          /** Réservation annulée ou simple demande : l'émission sera refusée. */
          statut_reservation: 'annulee' | 'demande' | null;
      }
    | {
          type: 'import';
          fichier: string;
          numero_source: string | null;
          date_source: string | null;
          controles: ControleImport[];
      };

export interface FactureEditProps {
    facture: FactureEntete | null;
    formulaire: FactureForm;
    contexte: ContexteEditeur | null;
    options: FactureOptions;
    prochains: Record<FactureType, string>;
    can: FactureDroits;
}

/** Réponse de `factures.apercu`. */
export interface Apercu {
    html: string;
    totaux: {
        lignes: number[];
        total_ht: number;
        total_remise: number;
        tva: { taux: number; base: number; montant: number }[];
        total_tva: number;
        montant_timbre: number;
        total_ttc: number;
        lettres: string;
    };
}

/** Une réservation proposée au générateur de commission (`factures.commission.candidats`). */
export interface CandidatCommission {
    reservation_id: number;
    reference: string;
    logement: string;
    proprietaire: string | null;
    proprietaire_id: number | null;
    voyageur: string;
    check_in: string;
    check_out: string;
    canal: string;
    montant: number | null;
    commission: number | null;
    taux_commission: number;
    designation: string;
    deja_facturee: { id: number; numero: string | null } | null;
    erreur: string | null;
}

/** Règle de paiement d'un logement (`App\Services\Factures\RegleDePaiement`). */
export type ReglePaiement = 'menage_commission' | 'menage' | 'pourcentage';

/** Un séjour du rapport de versement Airbnb, rapproché et calculé par le serveur. */
export interface SejourRapport {
    cle: string;
    voyageur: string;
    annonce: string;
    arrivee: string;
    depart: string;
    nuits: number | null;
    montant_reservation: number;
    montant_cohote: number;
    recu: number;
    /** Airbnb a déjà versé une part au propriétaire : on facture ce qui nous est resté. */
    partage: boolean;
    reservation: { id: number; reference: string; check_in: string; check_out: string } | null;
    logement: { id: number; nom: string; proprietaire: string | null; proprietaire_id: number | null } | null;
    logement_origine: 'reservation' | 'annonce' | 'manuel' | null;
    regle: ReglePaiement;
    commission_pct: number;
    commission_saisie: boolean;
    pourcentage: number;
    menage_tnd: number;
    /** frais : le frais du logement · synchro / proprietaire : dinars ÷ `menage_taux` · dinars : facture en TND. */
    menage_source: 'frais' | 'synchro' | 'proprietaire' | 'dinars' | null;
    menage_taux: number | null;
    menage: number | null;
    base: number;
    ttc_regle: number | null;
    ttc: number | null;
    ht: number | null;
    designation: string | null;
    deja_facturee: { id: number; numero: string | null } | null;
    avertissements: string[];
    erreur: string | null;
}

/**
 * Un logement proposé au choix manuel d'un séjour (`SearchableSelect`).
 * `type` et non `interface` : `SearchableSelect` attend un type indexable.
 */
export type LogementChoix = {
    id: number;
    name: string;
    internal_name: string | null;
};

/** Réponse de `factures.rapport-airbnb.analyse`. */
export interface AnalyseRapport {
    jeton: string;
    fichier: string;
    devise: Devise;
    payout: number | null;
    somme: number;
    autres: { type: string; montant: number; texte: string }[];
    sejours: SejourRapport[];
    logements: LogementChoix[];
}

/** Un relevé déjà importé (`factures.releves.index`), le plus récent d'abord. */
export interface ReleveResume {
    id: number;
    banque: string;
    compte: string;
    devise: Devise;
    du: string; // ISO
    au: string; // ISO
    /** Versements Airbnb crédités sur le relevé. */
    credits: number;
    /** Combien d'entre eux sont portés par une facture (ni supprimée ni annulée). */
    factures: number;
}

/** Où en est un versement : le seul `a_facturer` se coche. */
export type StatutCredit = 'facture' | 'rapport_manquant' | 'taux_manquant' | 'a_facturer';

/** Un séjour du rapport rattaché à un versement, avec sa ligne HT convertie au taux du jour du versement. */
export type SejourReleve = SejourRapport & { ht_tnd: number | null };

/** Un versement Airbnb crédité sur le relevé. */
export interface CreditReleve {
    id: number;
    date_operation: string; // ISO
    date_valeur: string | null;
    reference_banque: string;
    reference_airbnb: string | null;
    montant: number;
    frais: number | null;
    /** Cours du jour de l'opération ; `date_cotation` diffère un week-end ou un jour férié (dernier cours publié). */
    taux: { valeur: number; date_cotation: string; source: 'bct' | 'manuel' } | null;
    montant_tnd: number | null;
    statut: StatutCredit;
    facture: { id: number; numero: string | null; statut: FactureStatut } | null;
    rapport: { fichier: string | null; payout: number; somme: number; nb_sejours: number } | null;
    /** Vide sans rapport. */
    sejours: SejourReleve[];
    /** HT des séjours facturables (sans erreur, pas encore facturés), dans la devise du relevé. */
    total_ht: number;
    /** Le même HT en dinars. */
    total_ht_tnd: number;
}

/** Réponse de `factures.releves.store`, `.etat`, `.taux` (et `.rapports`, avec `rattachement`). */
export interface EtatReleve {
    releve: {
        id: number;
        banque: string;
        compte: string;
        devise: Devise;
        du: string;
        au: string;
        fichier: string | null;
        solde_depart: number;
        solde_final: number;
        total_credit: number;
        /** Solde de départ + crédits − débits = solde final (contrôle fait à la lecture). */
        controle_ok: boolean;
    };
    credits: CreditReleve[];
    totaux: { versements: number; versements_tnd: number; taux_manquants: number };
    logements: LogementChoix[];
}

/** Ce que le dépôt des rapports Airbnb a donné (`factures.releves.rapports`). */
export interface RattachementRapports {
    rattaches: { credit_id: number; fichier: string }[];
    sans_credit: { fichier: string; montant: number | null }[];
    erreurs: { fichier: string; message: string }[];
}

/** Suggestion de destinataire (`factures.clients`). */
export interface SuggestionClient {
    type: ClientType;
    id: number | null;
    nom: string;
    adresse: string | null;
    matricule_fiscal: string | null;
    identifiant_type: IdentifiantType;
    email: string | null;
    detail: string;
}
