<template>
    <div>
        <!-- En-tete : retour vers le repertoire + titre. -->
        <div class="flex items-center gap-3 pt-11">
            <MalioButtonIcon
                icon="mdi:arrow-left-bold"
                icon-size="24"
                variant="ghost"
                v-bind="{ ariaLabel: t('technique.providers.form.back') }"
                @click="goBack"
            />
            <h1 class="text-[30px] font-semibold text-m-primary">{{ t('technique.providers.form.title') }}</h1>
        </div>

        <!-- ── Formulaire principal (pre-onglets) ─────────────────────────────
             Sans validation de ce bloc, les onglets restent inaccessibles. Au
             succes du POST, les champs passent en lecture seule et on bascule
             automatiquement sur l'onglet Contact (PAS d'onglet Information au M3).
             Selecteur de site present ici (RG-3.03, relation directe). -->
        <div class="mt-[48px] grid grid-cols-3 xl:grid-cols-4 gap-x-[44px] gap-y-4">
            <MalioInputText
                v-model="main.companyName"
                :label="t('technique.providers.form.main.companyName')"
                :required="true"
                :readonly="mainLocked"
                :error="mainErrors.errors.companyName"
            />
            <MalioSelectCheckbox
                :model-value="main.categoryIris"
                :options="referentials.categories.value"
                :label="t('technique.providers.form.main.categories')"
                :display-tag="true"
                :readonly="mainLocked"
                :required="true"
                :error="mainErrors.errors.categories"
                @update:model-value="(v: (string | number)[]) => main.categoryIris = v.map(String)"
            />
            <MalioSelectCheckbox
                :model-value="main.siteIris"
                :options="referentials.sites.value"
                :label="t('technique.providers.form.main.sites')"
                :display-tag="true"
                :readonly="mainLocked"
                :required="true"
                :error="mainErrors.errors.sites"
                @update:model-value="(v: (string | number)[]) => main.siteIris = v.map(String)"
            />
        </div>

        <div v-if="!mainLocked" class="mt-12 flex justify-center">
            <MalioButton
                variant="primary"
                :label="t('technique.providers.form.submit')"
                :disabled="mainSubmitting"
                @click="submitMain"
            />
        </div>

        <!-- ── Onglets a validation incrementale ─────────────────────────────
             Onglet Contact actif (ERP-142) ; Adresse / Comptabilite arrivent aux
             tickets ERP-143 / 144 : placeholders « A venir » pour l'instant. -->
        <MalioTabList v-model="activeTab" :tabs="tabs" class="mt-[60px]">
            <!-- Onglet Contact : saisie multi-contacts (blocs ajoutables). -->
            <template #contact>
                <div class="mt-12 flex flex-col gap-6">
                    <!-- ERP-172 : poubelle visible seulement s'il reste un AUTRE bloc deja
                         enregistre (id en base) — cf. isRowRemovable. Empeche de supprimer un
                         bloc tant que rien n'est sauvegarde, et de supprimer son dernier
                         bloc enregistre. -->
                    <ProviderContactBlock
                        v-for="(contact, index) in contacts"
                        :key="index"
                        :model-value="contact"
                        :removable="isRowRemovable(contacts, index)"
                        :readonly="isValidated('contact')"
                        :errors="contactErrors[index]"
                        @update:model-value="(v) => contacts[index] = v"
                        @remove="askRemoveContact(index)"
                    />
                    <div v-if="!isValidated('contact')" class="flex justify-center gap-6">
                        <MalioButton
                            variant="secondary"
                            icon-name="mdi:add-bold"
                            icon-position="left"
                            :label="t('technique.providers.form.contact.add')"
                            :disabled="!canAddContact"
                            @click="addContact"
                        />
                        <MalioButton
                            variant="primary"
                            :label="t('technique.providers.form.submit')"
                            :disabled="tabSubmitting || providerId === null"
                            @click="onSubmitContacts"
                        />
                    </div>
                </div>
            </template>
            <!-- Onglet Adresse : saisie multi-adresses (blocs ajoutables). -->
            <template #address>
                <div class="mt-12 flex flex-col gap-6">
                    <ProviderAddressBlock
                        v-for="(address, index) in addresses"
                        :key="index"
                        :model-value="address"
                        :category-options="referentials.categories.value"
                        :site-options="referentials.sites.value"
                        :contact-options="contactOptions"
                        :country-options="countryOptions"
                        :removable="isRowRemovable(addresses, index)"
                        :readonly="isValidated('address')"
                        :errors="addressErrors[index]"
                        @update:model-value="(v) => addresses[index] = v"
                        @remove="askRemoveAddress(index)"
                        @degraded="onAddressDegraded"
                    />
                    <div v-if="!isValidated('address')" class="flex justify-center gap-6">
                        <MalioButton
                            variant="secondary"
                            icon-name="mdi:add-bold"
                            icon-position="left"
                            :label="t('technique.providers.form.address.add')"
                            :disabled="!canAddAddress"
                            @click="addAddress"
                        />
                        <MalioButton
                            variant="primary"
                            :label="t('technique.providers.form.submit')"
                            :disabled="tabSubmitting || providerId === null"
                            @click="onSubmitAddresses"
                        />
                    </div>
                </div>
            </template>
            <!-- Onglet Comptabilite (present uniquement si accounting.view ; editable si manage). -->
            <template v-if="canAccountingView" #accounting>
                <div class="mt-12 flex flex-col gap-6">
                    <div class="bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
                        <div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
                            <MalioInputText
                                v-model="accounting.siren"
                                :label="t('technique.providers.form.accounting.siren')"
                                :mask="SIREN_MASK"
                                :readonly="accountingReadonly"
                                :required="true"
                                :error="accountingErrors.errors.siren"
                            />
                            <MalioInputText
                                v-model="accounting.accountNumber"
                                :label="t('technique.providers.form.accounting.accountNumber')"
                                :readonly="accountingReadonly"
                                :required="true"
                                :error="accountingErrors.errors.accountNumber"
                            />
                            <MalioSelect
                                :model-value="accounting.tvaModeIri"
                                :options="referentials.tvaModes.value"
                                :label="t('technique.providers.form.accounting.tvaMode')"
                                :readonly="accountingReadonly"
                                empty-option-label=""
                                :required="true"
                                :error="accountingErrors.errors.tvaMode"
                                @update:model-value="(v: string | number | null) => accounting.tvaModeIri = v === null ? null : String(v)"
                            />
                            <MalioInputText
                                v-model="accounting.nTva"
                                :label="t('technique.providers.form.accounting.nTva')"
                                :readonly="accountingReadonly"
                                :required="true"
                                :error="accountingErrors.errors.nTva"
                            />
                            <MalioSelect
                                :model-value="accounting.paymentDelayIri"
                                :options="referentials.paymentDelays.value"
                                :label="t('technique.providers.form.accounting.paymentDelay')"
                                :readonly="accountingReadonly"
                                empty-option-label=""
                                :required="true"
                                :error="accountingErrors.errors.paymentDelay"
                                @update:model-value="(v: string | number | null) => accounting.paymentDelayIri = v === null ? null : String(v)"
                            />
                            <MalioSelect
                                :model-value="accounting.paymentTypeIri"
                                :options="referentials.paymentTypes.value"
                                :label="t('technique.providers.form.accounting.paymentType')"
                                :readonly="accountingReadonly"
                                empty-option-label=""
                                :required="true"
                                :error="accountingErrors.errors.paymentType"
                                @update:model-value="onPaymentTypeChange"
                            />
                            <!-- Banque : visible et obligatoire seulement si VIREMENT (RG-3.07). -->
                            <MalioSelect
                                v-if="isBankRequired"
                                :model-value="accounting.bankIri"
                                :options="referentials.banks.value"
                                :label="t('technique.providers.form.accounting.bank')"
                                :readonly="accountingReadonly"
                                empty-option-label=""
                                :required="true"
                                :error="accountingErrors.errors.bank"
                                @update:model-value="(v: string | number | null) => accounting.bankIri = v === null ? null : String(v)"
                            />
                        </div>
                    </div>

                    <!-- Blocs RIB — affiches uniquement si type de reglement = LCR (RG-3.08). -->
                    <div
                        v-for="(rib, index) in visibleRibs"
                        :key="index"
                        class="relative bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
                    >
                        <MalioButtonIcon
                            v-if="!accountingReadonly && isRowRemovable(visibleRibs, index)"
                            icon="mdi:delete-outline"
                            variant="ghost"
                            button-class="absolute top-3 right-3"
                            v-bind="{ ariaLabel: t('technique.providers.form.accounting.removeRib') }"
                            @click="askRemoveRib(index)"
                        />
                        <div class="grid grid-cols-4 gap-x-[44px] gap-y-4">
                            <MalioInputText
                                v-model="rib.label"
                                :label="t('technique.providers.form.accounting.ribLabel')"
                                :readonly="accountingReadonly"
                                :required="true"
                                :error="ribErrors[index]?.label"
                            />
                            <MalioInputText
                                v-model="rib.bic"
                                :label="t('technique.providers.form.accounting.ribBic')"
                                :readonly="accountingReadonly"
                                :required="true"
                                :error="ribErrors[index]?.bic"
                            />
                            <MalioInputText
                                v-model="rib.iban"
                                :label="t('technique.providers.form.accounting.ribIban')"
                                :readonly="accountingReadonly"
                                :required="true"
                                :error="ribErrors[index]?.iban"
                            />
                        </div>
                    </div>

                    <div v-if="!accountingReadonly" class="flex justify-center gap-6">
                        <MalioButton
                            v-if="isRibRequired"
                            variant="secondary"
                            icon-name="mdi:add-bold"
                            icon-position="left"
                            :label="t('technique.providers.form.accounting.addRib')"
                            :disabled="!canAddRib"
                            @click="addRib"
                        />
                        <MalioButton
                            variant="primary"
                            :label="t('technique.providers.form.submit')"
                            :disabled="tabSubmitting || providerId === null"
                            @click="onSubmitAccounting"
                        />
                    </div>
                </div>
            </template>
        </MalioTabList>

        <!-- Modal de confirmation generique (suppression d'un bloc contact). -->
        <MalioModal v-model="confirmModal.open" modal-class="max-w-md">
            <template #header>
                <h2 class="text-[24px] font-bold">{{ t('technique.providers.form.confirmDelete.title') }}</h2>
            </template>
            <p>{{ confirmModal.message }}</p>
            <template #footer>
                <MalioButton
                    variant="secondary"
                    button-class="flex-1"
                    :label="t('technique.providers.form.confirmDelete.cancel')"
                    @click="confirmModal.open = false"
                />
                <MalioButton
                    variant="danger"
                    button-class="flex-1"
                    :label="t('technique.providers.form.confirmDelete.confirm')"
                    @click="runConfirm"
                />
            </template>
        </MalioModal>
    </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { useProviderReferentials, type RefOption } from '~/modules/technique/composables/useProviderReferentials'
import { useProviderForm } from '~/modules/technique/composables/useProviderForm'
import {
    isBankRequiredForPaymentType,
    isRibRequiredForPaymentType,
} from '~/modules/technique/utils/forms/providerAccounting'
import { extractApiErrorMessage } from '~/shared/utils/api'
import { isRowRemovable } from '~/shared/utils/collectionRow'

// Masque SIREN : 9 chiffres (la normalisation finale reste serveur).
const SIREN_MASK = '#########'

const { t } = useI18n()
const router = useRouter()
const toast = useToast()
const { can } = usePermissions()

useHead({ title: t('technique.providers.form.title') })

// Gating de la route : la creation est reservee a `manage` (POST /providers garde
// manage seul — Compta ne cree pas). Compta (accounting seul) et Usine sont
// rediriges vers le repertoire.
if (!can('technique.providers.manage')) {
    await navigateTo('/providers')
}

const referentials = useProviderReferentials()

const {
    main,
    providerId,
    mainLocked,
    mainSubmitting,
    mainErrors,
    canAccountingView,
    tabKeys,
    activeTab,
    unlockedIndex,
    submitMain,
    tabSubmitting,
    isValidated,
    contacts,
    contactErrors,
    canAddContact,
    addContact,
    removeContact,
    submitContacts,
    addresses,
    addressErrors,
    canAddAddress,
    addAddress,
    removeAddress,
    submitAddresses,
    accounting,
    ribs,
    accountingErrors,
    ribErrors,
    accountingReadonly,
    setPaymentType,
    canAddRib,
    addRib,
    removeRib,
    submitAccounting,
} = useProviderForm()

/** Retour vers le repertoire prestataires (fleche d'en-tete). */
function goBack(): void {
    router.push('/providers')
}

/**
 * Message d'erreur a afficher dans un toast a partir d'une erreur d'API. Retourne
 * TOUJOURS une chaine (le composant de toast plante sur `undefined`).
 */
function apiErrorMessage(error: unknown): string {
    const data = (error as { response?: { _data?: unknown } })?.response?._data
    return extractApiErrorMessage(data) || t('technique.providers.toast.error')
}

// Dernier onglet REMPLISSABLE par le role : tabKeys exclut deja la Comptabilite
// si l'user n'a pas accounting.view. Sa validation cloture l'ajout (redirection).
const lastFillableTab = computed(() => tabKeys.value[tabKeys.value.length - 1])

/**
 * Apres validation d'un onglet (creation) : si c'est le dernier onglet du role,
 * l'ajout est termine -> toast final + retour au repertoire (miroir M1/M2) ; sinon
 * toast de mise a jour (l'onglet suivant a deja ete deverrouille par completeTab).
 */
function onTabSaved(key: string): void {
    if (key === lastFillableTab.value) {
        toast.success({ title: t('technique.providers.toast.addComplete') })
        router.push('/providers')
        return
    }
    toast.success({ title: t('technique.providers.toast.updateSuccess') })
}

// ── Onglet Contact ──────────────────────────────────────────────────────────
/** Valide l'onglet Contact ; redirige si c'est le dernier onglet du role. */
async function onSubmitContacts(): Promise<void> {
    const ok = await submitContacts(error => toast.error({
        title: t('technique.providers.toast.error'),
        message: apiErrorMessage(error),
    }))
    if (ok) {
        onTabSaved('contact')
    }
}

function askRemoveContact(index: number): void {
    askConfirm(t('technique.providers.form.confirmDelete.contact'), () => removeContact(index))
}

// ── Onglet Adresse ────────────────────────────────────────────────────────────
// Contacts deja persistes (IRI non nul), rattachables a une adresse (M2M). Le
// libelle reprend le nom complet, a defaut l'email.
const contactOptions = computed<RefOption[]>(() =>
    contacts.value
        .filter(c => c.iri !== null)
        .map(c => ({
            value: c.iri as string,
            label: [c.firstName, c.lastName].filter(Boolean).join(' ') || (c.email ?? ''),
        })),
)

// Pays : France garantie en tete meme si /countries echoue (resilience ERP-102),
// pour rester preselectionnable par defaut sur chaque adresse.
const countryOptions = computed<RefOption[]>(() => {
    const list = referentials.countries.value
    return list.some(c => c.value === 'France')
        ? list
        : [{ value: 'France', label: 'France' }, ...list]
})

const addressDegradedNotified = ref(false)

/** Avertit une seule fois quand l'autocompletion d'adresse bascule en degrade (RG-3.06). */
function onAddressDegraded(): void {
    if (addressDegradedNotified.value) {
        return
    }
    addressDegradedNotified.value = true
    toast.warning({
        title: t('technique.providers.toast.error'),
        message: t('technique.providers.form.address.degraded'),
    })
}

/** Valide l'onglet Adresse ; redirige si c'est le dernier onglet du role. */
async function onSubmitAddresses(): Promise<void> {
    const ok = await submitAddresses(error => toast.error({
        title: t('technique.providers.toast.error'),
        message: apiErrorMessage(error),
    }))
    if (ok) {
        onTabSaved('address')
    }
}

function askRemoveAddress(index: number): void {
    askConfirm(t('technique.providers.form.confirmDelete.address'), () => removeAddress(index))
}

// ── Onglet Comptabilite ───────────────────────────────────────────────────────
// Code stable du type de reglement selectionne (pour RG-3.07 / RG-3.08).
const selectedPaymentTypeCode = computed(() =>
    referentials.paymentTypes.value.find(p => p.value === accounting.paymentTypeIri)?.code ?? null,
)
const isBankRequired = computed(() => isBankRequiredForPaymentType(selectedPaymentTypeCode.value))
const isRibRequired = computed(() => isRibRequiredForPaymentType(selectedPaymentTypeCode.value))

// Les blocs RIB ne sont affiches que pour une LCR (RG-3.08).
const visibleRibs = computed(() => isRibRequired.value ? ribs.value : [])

/** Changement de type de reglement : propage les RG inter-champs (banque / RIB). */
function onPaymentTypeChange(value: string | number | null): void {
    const iri = value === null ? null : String(value)
    const code = referentials.paymentTypes.value.find(p => p.value === iri)?.code ?? null
    setPaymentType(iri, isBankRequiredForPaymentType(code), isRibRequiredForPaymentType(code))
}

function askRemoveRib(index: number): void {
    askConfirm(t('technique.providers.form.confirmDelete.rib'), () => removeRib(index))
}

/** Valide l'onglet Comptabilite ; redirige si c'est le dernier onglet du role. */
async function onSubmitAccounting(): Promise<void> {
    const ok = await submitAccounting(
        isBankRequired.value,
        isRibRequired.value,
        error => toast.error({
            title: t('technique.providers.toast.error'),
            message: apiErrorMessage(error),
        }),
    )
    if (ok) {
        onTabSaved('accounting')
    }
}

// ── Modal de confirmation generique ─────────────────────────────────────────
const confirmModal = reactive({
    open: false,
    message: '',
    action: null as null | (() => void),
})

function askConfirm(message: string, action: () => void): void {
    confirmModal.message = message
    confirmModal.action = action
    confirmModal.open = true
}

function runConfirm(): void {
    confirmModal.action?.()
    confirmModal.action = null
    confirmModal.open = false
}

// Icone (Iconify) affichee dans l'onglet, par cle.
const TAB_ICONS: Record<string, string> = {
    contact: 'mdi:account-box-plus-outline',
    address: 'mdi:map-marker-outline',
    accounting: 'mdi:bank-circle-outline',
}

// Onglets desactives tant que le formulaire principal n'est pas valide
// (unlockedIndex = -1 au depart) ; deverrouillage progressif ensuite.
const tabs = computed(() => tabKeys.value.map((key, index) => ({
    key,
    label: t(`technique.providers.tab.${key}`),
    icon: TAB_ICONS[key],
    disabled: index > unlockedIndex.value,
})))

onMounted(() => {
    // Echec du chargement des referentiels non bloquant : les selects restent vides.
    referentials.loadMain().catch(() => {})
    // Referentiels comptables charges uniquement si l'onglet est accessible.
    if (canAccountingView.value) {
        referentials.loadAccounting().catch(() => {})
    }
})
</script>
