import { ref } from 'vue'

/**
 * Charge les referentiels (listes courtes) alimentant les selects du formulaire
 * principal de l'ecran « Ajouter un prestataire » (M3 Technique, ERP-141) :
 * categories (type PRESTATAIRE) et sites (86 / 17 / 82).
 *
 * Miroir reduit de `useSupplierReferentials` (M2) : a ce stade (formulaire
 * principal) seuls categories + sites sont necessaires. Les referentiels
 * comptables (modes de TVA, delais/types de reglement, banques) seront charges
 * par l'onglet Comptabilite (ERP-144).
 *
 * Toutes les collections sont recuperees en entier via l'echappatoire prevue
 * `?pagination=false` (referentiels de quelques entrees), avec l'en-tete
 * `Accept: application/ld+json` impose par API Platform 4 pour obtenir l'enveloppe
 * Hydra (`member`). La valeur d'option est l'IRI Hydra (`@id`), renvoyee telle
 * quelle dans le payload POST (relations M2M).
 *
 * Chargement RESILIENT (Promise.allSettled) : chaque referentiel est isole ; un
 * echec (permission manquante, reseau) laisse simplement la liste vide.
 *
 * Etat 100 % local a l'instance (refs) — aucune persistance URL.
 */

/** Option generique au format attendu par MalioSelect / MalioSelectCheckbox. */
export interface RefOption {
    value: string
    label: string
}

/** Option de type de reglement enrichie de son code stable (RG-3.07 / RG-3.08). */
export interface PaymentTypeOption extends RefOption {
    code: string
}

interface HydraMember {
    '@id': string
}

interface ReferentialMember extends HydraMember {
    code: string
    label: string
}

interface CategoryMember extends HydraMember {
    code: string
    name: string
}

interface SiteMember extends HydraMember {
    name: string
    postalCode: string
}

interface CountryMember extends HydraMember {
    code: string
    name: string
}

const LD_JSON_HEADERS = { Accept: 'application/ld+json' }

export function useProviderReferentials() {
    const api = useApi()

    const categories = ref<RefOption[]>([])
    const sites = ref<RefOption[]>([])
    const countries = ref<RefOption[]>([])
    // Referentiels comptables (charges a la demande via loadAccounting).
    const tvaModes = ref<RefOption[]>([])
    const paymentDelays = ref<RefOption[]>([])
    const paymentTypes = ref<PaymentTypeOption[]>([])
    const banks = ref<RefOption[]>([])

    /** Recupere une collection complete (pagination desactivee) en Hydra. */
    async function fetchAll<T extends HydraMember>(
        url: string,
        query: Record<string, string | string[]> = {},
    ): Promise<T[]> {
        const res = await api.get<{ member?: T[] }>(
            url,
            { pagination: 'false', ...query },
            { headers: LD_JSON_HEADERS, toast: false },
        )
        return res.member ?? []
    }

    /** Charge en parallele les referentiels du formulaire principal (categories + sites). */
    async function loadMain(): Promise<void> {
        await Promise.allSettled([
            // RG-3.09 : un prestataire ne porte que des categories de type
            // PRESTATAIRE -> filtre cote API. Libelle affiche = `name`.
            fetchAll<CategoryMember>('/categories', { typeCode: 'PRESTATAIRE' })
                .then((cats) => { categories.value = cats.map(c => ({ value: c['@id'], label: c.name })) }),
            // Sites (RG-3.03) : libelle = numero de departement (2 premiers chiffres
            // du code postal du site), ex: 86100 -> « 86 », 17400 -> « 17 ».
            fetchAll<SiteMember>('/sites')
                .then((sitesList) => { sites.value = sitesList.map(s => ({ value: s['@id'], label: (s.postalCode ?? '').slice(0, 2) })) }),
            // Pays (ERP-116) : la valeur d'option est le NOM du pays (l'adresse stocke
            // `country` en chaine libre, « France »...). value === label. Aligne sur
            // les ecrans client/fournisseur. Sert le select Pays de l'onglet Adresse.
            fetchAll<CountryMember>('/countries')
                .then((list) => { countries.value = list.map(c => ({ value: c.name, label: c.name })) }),
        ])
    }

    /**
     * Charge les referentiels comptables (onglet Comptabilite, ERP-144). Appele
     * uniquement quand l'utilisateur peut voir l'onglet (accounting.view). Resilient
     * (allSettled) : un referentiel en echec reste vide.
     */
    async function loadAccounting(): Promise<void> {
        await Promise.allSettled([
            fetchAll<ReferentialMember>('/tva_modes')
                .then((list) => { tvaModes.value = list.map(t => ({ value: t['@id'], label: t.label })) }),
            fetchAll<ReferentialMember>('/payment_delays')
                .then((list) => { paymentDelays.value = list.map(d => ({ value: d['@id'], label: d.label })) }),
            // Le code stable du type sert les RG-3.07 (VIREMENT) / RG-3.08 (LCR).
            fetchAll<ReferentialMember>('/payment_types')
                .then((list) => { paymentTypes.value = list.map(p => ({ value: p['@id'], label: p.label, code: p.code })) }),
            fetchAll<ReferentialMember>('/banks')
                .then((list) => { banks.value = list.map(b => ({ value: b['@id'], label: b.label })) }),
        ])
    }

    return {
        categories,
        sites,
        countries,
        tvaModes,
        paymentDelays,
        paymentTypes,
        banks,
        loadMain,
        loadAccounting,
    }
}
