<template>
    <div>
        <!-- En-tete : retour consultation + nom du prestataire. -->
        <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.edit.back') }"
                @click="goBack"
            />
            <h1 class="text-[30px] font-semibold text-m-primary">{{ headerTitle }}</h1>
        </div>

        <!-- Etats de chargement / introuvable. -->
        <p v-if="loading" class="mt-12 text-center text-black/60">{{ t('technique.providers.edit.loading') }}</p>
        <p v-else-if="error" class="mt-12 text-center text-m-danger">{{ t('technique.providers.edit.notFound') }}</p>

        <template v-else-if="provider">
            <!-- ── Bloc principal (pre-rempli, editable si `manage`) ──────────── -->
            <div class="mt-[48px] grid grid-cols-3 xl:grid-cols-4 gap-x-[44px] gap-y-4">
                <MalioInputText
                    :model-value="main.companyName"
                    :label="t('technique.providers.form.main.companyName')"
                    :required="true"
                    :disabled="businessReadonly"
                    :error="mainErrors.errors.companyName"
                    @update:model-value="(v: string) => main.companyName = sanitizeFreeText(v)"
                />
                <MalioSelectCheckbox
                    :model-value="main.categoryIris"
                    :options="referentials.categories.value"
                    :label="t('technique.providers.form.main.categories')"
                    :display-tag="true"
                    :disabled="businessReadonly"
                    :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"
                    :disabled="businessReadonly"
                    :required="true"
                    :error="mainErrors.errors.sites"
                    @update:model-value="(v: (string | number)[]) => main.siteIris = v.map(String)"
                />
            </div>

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

            <!-- ── Onglets : navigation LIBRE, edition independante par onglet ──── -->
            <MalioTabList v-model="activeTab" :tabs="tabs" :max-visible-tabs="5" :max-width="1100" class="mt-[60px]">
                <!-- Onglet Contact -->
                <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)"
                            :disabled="businessReadonly"
                            :errors="contactErrors[index]"
                            @update:model-value="(v) => contacts[index] = v"
                            @remove="askRemoveContact(index)"
                        />
                        <div v-if="!businessReadonly" 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.edit.save')"
                                :disabled="tabSubmitting"
                                @click="onSubmitContacts"
                            />
                        </div>
                    </div>
                </template>

                <!-- Onglet Adresse -->
                <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)"
                            :disabled="businessReadonly"
                            :errors="addressErrors[index]"
                            @update:model-value="(v) => addresses[index] = v"
                            @remove="askRemoveAddress(index)"
                            @degraded="onAddressDegraded"
                        />
                        <div v-if="!businessReadonly" 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.edit.save')"
                                :disabled="tabSubmitting"
                                @click="onSubmitAddresses"
                            />
                        </div>
                    </div>
                </template>

                <!-- Onglet Comptabilite (present 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"
                                    :disabled="accountingReadonly"
                                    :required="true"
                                    :error="accountingErrors.errors.siren"
                                />
                                <MalioInputText
                                    :model-value="accounting.accountNumber"
                                    :label="t('technique.providers.form.accounting.accountNumber')"
                                    :disabled="accountingReadonly"
                                    :required="true"
                                    :error="accountingErrors.errors.accountNumber"
                                    @update:model-value="(v: string) => accounting.accountNumber = sanitizeCodeAlnum(v)"
                                />
                                <MalioSelect
                                    :model-value="accounting.tvaModeIri"
                                    :options="referentials.tvaModes.value"
                                    :label="t('technique.providers.form.accounting.tvaMode')"
                                    :disabled="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
                                    :model-value="accounting.nTva"
                                    :label="t('technique.providers.form.accounting.nTva')"
                                    :disabled="accountingReadonly"
                                    :required="true"
                                    :error="accountingErrors.errors.nTva"
                                    @update:model-value="(v: string) => accounting.nTva = sanitizeCodeAlnum(v)"
                                />
                                <MalioSelect
                                    :model-value="accounting.paymentDelayIri"
                                    :options="referentials.paymentDelays.value"
                                    :label="t('technique.providers.form.accounting.paymentDelay')"
                                    :disabled="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')"
                                    :disabled="accountingReadonly"
                                    empty-option-label=""
                                    :required="true"
                                    :error="accountingErrors.errors.paymentType"
                                    @update:model-value="onPaymentTypeChange"
                                />
                                <MalioSelect
                                    v-if="isBankRequired"
                                    :model-value="accounting.bankIri"
                                    :options="referentials.banks.value"
                                    :label="t('technique.providers.form.accounting.bank')"
                                    :disabled="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')"
                                    :disabled="accountingReadonly"
                                    :required="true"
                                    :error="ribErrors[index]?.label"
                                />
                                <MalioInputText
                                    :model-value="rib.bic"
                                    :label="t('technique.providers.form.accounting.ribBic')"
                                    :disabled="accountingReadonly"
                                    :required="true"
                                    :error="ribErrors[index]?.bic"
                                    @update:model-value="(v: string) => rib.bic = sanitizeCodeAlnum(v)"
                                />
                                <MalioInputText
                                    :model-value="rib.iban"
                                    :label="t('technique.providers.form.accounting.ribIban')"
                                    :disabled="accountingReadonly"
                                    :required="true"
                                    :error="ribErrors[index]?.iban"
                                    @update:model-value="(v: string) => rib.iban = sanitizeCodeAlnum(v)"
                                />
                            </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.edit.save')"
                                :disabled="tabSubmitting"
                                @click="onSubmitAccounting"
                            />
                        </div>
                    </div>
                </template>
            </MalioTabList>
        </template>

        <!-- Modal de confirmation generique (suppression contact / adresse / RIB). -->
        <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 { useProvider } from '~/modules/technique/composables/useProvider'
import { useProviderReferentials, type RefOption } from '~/modules/technique/composables/useProviderReferentials'
import { useProviderForm } from '~/modules/technique/composables/useProviderForm'
import {
    canEditProvider,
    irisOf,
    mapAccountingDraft,
    mapAddressToDraft,
    mapContactToDraft,
    mapRibToDraft,
    paymentTypeCodeOf,
} from '~/modules/technique/utils/forms/providerDetail'
import {
    isBankRequiredForPaymentType,
    isRibRequiredForPaymentType,
} from '~/modules/technique/utils/forms/providerAccounting'
import {
    emptyProviderAddress,
    emptyProviderContact,
    emptyProviderRib,
} from '~/modules/technique/types/providerForm'
import { extractApiErrorMessage } from '~/shared/utils/api'
import { isRowRemovable } from '~/shared/utils/collectionRow'
import { sanitizeCodeAlnum, sanitizeFreeText } from '~/shared/utils/textSanitize'

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

const { t } = useI18n()
const route = useRoute()
const router = useRouter()
const toast = useToast()
const { can, canAny } = usePermissions()

const providerId = route.params.id as string

// Acces : l'edition exige `manage` OU `accounting.manage` (le role Compta edite
// son onglet). Sinon retour consultation.
if (!canEditProvider(canAny)) {
    await navigateTo(`/providers/${providerId}`)
}

const businessReadonly = computed(() => !can('technique.providers.manage'))

const referentials = useProviderReferentials()
const { provider, loading, error, load } = useProvider(providerId)

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

// Modification : navigation libre + pas de verrouillage a la validation.
editMode.value = true
activeTab.value = 'contact'

const headerTitle = computed(() => provider.value?.companyName || t('technique.providers.edit.title'))
useHead({ title: t('technique.providers.edit.title') })

// ── Onglets (navigation libre ; Comptabilite si accounting.view) ───────────────
const TAB_ICONS: Record<string, string> = {
    contact: 'mdi:account-box-plus-outline',
    address: 'mdi:map-marker-outline',
    accounting: 'mdi:bank-circle-outline',
}
const tabs = computed(() => tabKeys.value.map(key => ({
    key,
    label: t(`technique.providers.tab.${key}`),
    icon: TAB_ICONS[key],
})))

/** Pre-remplit les brouillons depuis la SEULE reponse detail. */
function prefill(): void {
    const d = provider.value
    if (!d) return

    // Indispensable : pilote les URLs des PATCH/POST par onglet (sinon les submits no-op).
    formProviderId.value = d.id

    main.companyName = d.companyName ?? null
    main.categoryIris = irisOf(d.categories)
    main.siteIris = irisOf(d.sites)

    const mappedContacts = (d.contacts ?? []).map(mapContactToDraft)
    contacts.value = mappedContacts.length > 0 ? mappedContacts : [emptyProviderContact()]

    const mappedAddresses = (d.addresses ?? []).map(mapAddressToDraft)
    addresses.value = mappedAddresses.length > 0 ? mappedAddresses : [emptyProviderAddress()]

    if (canAccountingView.value) {
        Object.assign(accounting, mapAccountingDraft(d))
        ribs.value = (d.ribs ?? []).map(mapRibToDraft)
        // Garantit un bloc RIB visible si le type de reglement est LCR.
        if (isRibRequiredForPaymentType(paymentTypeCodeOf(d.paymentType)) && ribs.value.length === 0) {
            ribs.value.push(emptyProviderRib())
        }
    }
}

// ── Comptabilite : RG-3.07 / RG-3.08 pilotees par le code du type de reglement ──
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))
const visibleRibs = computed(() => isRibRequired.value ? ribs.value : [])

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))
}

// ── Options adresses ──────────────────────────────────────────────────────────
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 ?? ''),
        })),
)

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)
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'),
    })
}

// ── Navigation + helpers ──────────────────────────────────────────────────────
function goBack(): void {
    router.push(`/providers/${providerId}`)
}

function apiErrorMessage(err: unknown): string {
    const data = (err as { response?: { _data?: unknown } })?.response?._data
    return extractApiErrorMessage(data) || t('technique.providers.toast.error')
}

/** PATCH du bloc principal (groupe provider:write:main). */
async function onUpdateMain(): Promise<void> {
    if (await updateMain()) {
        toast.success({ title: t('technique.providers.toast.updateSuccess') })
    }
}

async function onSubmitContacts(): Promise<void> {
    const ok = await submitContacts(err => toast.error({
        title: t('technique.providers.toast.error'),
        message: apiErrorMessage(err),
    }))
    if (ok) toast.success({ title: t('technique.providers.toast.updateSuccess') })
}

async function onSubmitAddresses(): Promise<void> {
    const ok = await submitAddresses(err => toast.error({
        title: t('technique.providers.toast.error'),
        message: apiErrorMessage(err),
    }))
    if (ok) toast.success({ title: t('technique.providers.toast.updateSuccess') })
}

async function onSubmitAccounting(): Promise<void> {
    const ok = await submitAccounting(
        isBankRequired.value,
        isRibRequired.value,
        err => toast.error({ title: t('technique.providers.toast.error'), message: apiErrorMessage(err) }),
    )
    if (ok) toast.success({ title: t('technique.providers.toast.updateSuccess') })
}

// ── 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
}

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

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

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

onMounted(async () => {
    referentials.loadMain().catch(() => {})
    if (canAccountingView.value) {
        referentials.loadAccounting().catch(() => {})
    }
    await load()
    prefill()
})
</script>
