<template>
    <div>
        <!-- En-tête : retour consultation + 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('transport.carriers.edit.back') }"
                @click="goBack"
            />
            <h1 class="text-[30px] font-semibold text-m-primary">{{ t('transport.carriers.edit.title') }}</h1>
        </div>

        <p v-if="loading" class="mt-12 text-center text-black/60">{{ t('transport.carriers.edit.loading') }}</p>
        <p v-else-if="error" class="mt-12 text-center text-m-danger">{{ t('transport.carriers.edit.notFound') }}</p>

        <template v-else>
            <!-- ── Formulaire principal (éditable, PATCH partiel) ─────────────── -->
            <div class="mt-[48px] grid grid-cols-3 xl:grid-cols-4 gap-x-[44px] gap-y-4">
                <MalioInputText
                    v-model="main.name"
                    :mask="FREE_TEXT_MASK"
                    :label="t('transport.carriers.form.main.name')"
                    :required="true"
                    :error="mainErrors.errors.name"
                />
                <!-- Cas LIOT : le champ immatriculations occupe les colonnes restantes
                     de la ligne (3 en xl, 2 sinon). Wrapper pour le col-span car
                     MalioInputText (inheritAttrs:false) renvoie `class` sur l'input. -->
                <div v-if="isLiot" class="col-span-2 xl:col-span-3">
                    <MalioInputText
                        v-model="main.liotPlates"
                        :mask="LIOT_PLATES_MASK"
                        :label="t('transport.carriers.form.main.liotPlates')"
                        :hint="t('transport.carriers.form.main.liotPlatesHint')"
                        :required="true"
                        :error="mainErrors.errors.liotPlates"
                    />
                </div>
                <template v-if="!isLiot">
                    <MalioSelect
                        :model-value="main.certificationType"
                        :options="certificationOptions"
                        :label="t('transport.carriers.form.main.certificationType')"
                        empty-option-label=""
                        :required="true"
                        :disabled="certificationReadonly"
                        :error="mainErrors.errors.certificationType"
                        @update:model-value="(v: string | number | null) => setCertification(v === null ? null : String(v))"
                    />
                    <MalioInputUpload
                        v-if="showDischarge"
                        :model-value="dischargeFileName"
                        :label="t('transport.carriers.form.main.discharge')"
                        accept="application/pdf,image/*"
                        :required="true"
                        :disabled="dischargeUploading"
                        :clearable="true"
                        :error="mainErrors.errors.dischargeDocument"
                        @update:model-value="(v: string) => dischargeFileName = v"
                        @file-selected="selectDischarge"
                        @clear="onClearDischarge"
                    />
                    <div v-else class="hidden xl:block"></div>
                    <div class="flex h-12 items-center">
                        <MalioCheckbox
                            id="carrier-edit-chartered"
                            :label="t('transport.carriers.form.main.isChartered')"
                            :model-value="main.isChartered"
                            :reserve-message-space="false"
                            @update:model-value="(val: boolean) => main.isChartered = val"
                        />
                    </div>
                    <template v-if="showCharteredFields">
                        <MalioInputAmount
                            :key="indexationKey"
                            :model-value="main.indexationRate"
                            :label="t('transport.carriers.form.main.indexationRate')"
                            icon-name="mdi:percent"
                            icon-position="right"
                            :required="true"
                            :error="mainErrors.errors.indexationRate"
                            @update:model-value="onIndexationInput"
                        />
                        <!-- Contenant : Benne / Fond mouvant en radios, centrés (h-12) comme
                             à l'onglet Prix (Benne par défaut). -->
                        <div>
                            <div class="flex h-12 items-center gap-4">
                                <MalioRadioButton
                                    :model-value="main.containerType"
                                    name="carrier-main-container"
                                    value="BENNE"
                                    :label="t('transport.carriers.containerType.BENNE')"
                                    group-class="mt-0"
                                    @update:model-value="(v: string | number | boolean | null) => main.containerType = v === null ? null : String(v)"
                                />
                                <MalioRadioButton
                                    :model-value="main.containerType"
                                    name="carrier-main-container"
                                    value="FOND_MOUVANT"
                                    :label="t('transport.carriers.containerType.FOND_MOUVANT')"
                                    group-class="mt-0"
                                    @update:model-value="(v: string | number | boolean | null) => main.containerType = v === null ? null : String(v)"
                                />
                            </div>
                            <p v-if="mainErrors.errors.containerType" class="ml-[2px] text-xs text-m-danger">{{ mainErrors.errors.containerType }}</p>
                        </div>
                        <MalioInputText
                            :model-value="main.volumeM3"
                            :label="t('transport.carriers.form.main.volumeM3')"
                            :required="true"
                            :error="mainErrors.errors.volumeM3"
                            @update:model-value="(v: string) => main.volumeM3 = sanitizeDecimal(v)"
                        />
                    </template>
                </template>
            </div>

            <div class="mt-12 flex justify-center">
                <MalioButton
                    variant="primary"
                    :label="t('transport.carriers.edit.save')"
                    :disabled="mainSubmitting"
                    @click="onUpdateMain"
                />
            </div>

            <!-- ── Onglets éditables (navigation libre, PATCH partiel par onglet) ── -->
            <MalioTabList v-model="activeTab" :tabs="tabs" class="mt-[60px]">
                <!-- Qualimat : actualiser nom + certification depuis le référentiel (ERP-172). -->
                <template #qualimat>
                    <CarrierQualimatTab
                        :search-name="main.name"
                        :selected-iri="main.qualimatCarrierIri"
                        @integrate="onIntegrateQualimat"
                    />
                </template>

                <template #addresses>
                    <div class="mt-12 flex flex-col gap-6">
                        <!-- Adresse UNIQUE (ERP-172) : un seul bloc, sans ajouter/supprimer. -->
                        <CarrierAddressBlock
                            :model-value="address"
                            :country-options="countryOptions"
                            :errors="addressErrors"
                            @update:model-value="(v) => address = v"
                            @degraded="onAddressDegraded"
                        />
                        <div class="flex justify-center gap-6">
                            <MalioButton variant="primary" :label="t('transport.carriers.edit.save')" :disabled="tabSubmitting" @click="onSubmitAddresses" />
                        </div>
                    </div>
                </template>

                <template #contacts>
                    <div class="mt-12 flex flex-col gap-6">
                        <CarrierContactBlock
                            v-for="(contact, index) in contacts"
                            :key="index"
                            :model-value="contact"
                            :removable="isRowRemovable(contacts, index)"
                            :errors="contactErrors[index]"
                            @update:model-value="(v) => contacts[index] = v"
                            @remove="askRemoveContact(index)"
                        />
                        <div class="flex justify-center gap-6">
                            <MalioButton variant="secondary" icon-name="mdi:add-bold" icon-position="left" :label="t('transport.carriers.form.contact.add')" :disabled="!canAddContact" @click="addContact" />
                            <MalioButton variant="primary" :label="t('transport.carriers.edit.save')" :disabled="tabSubmitting" @click="onSubmitContacts" />
                        </div>
                    </div>
                </template>

                <template #prices>
                    <div class="mt-12 flex flex-col gap-6">
                        <CarrierPriceBlock
                            v-for="(price, index) in prices"
                            :key="index"
                            :model-value="price"
                            :client-options="clientOptions"
                            :supplier-options="supplierOptions"
                            :site-options="siteOptions"
                            removable
                            :errors="priceErrors[index]"
                            @update:model-value="(v) => prices[index] = v"
                            @remove="askRemovePrice(index)"
                        />
                        <div class="flex justify-center gap-6">
                            <MalioButton variant="secondary" icon-name="mdi:add-bold" icon-position="left" :label="t('transport.carriers.form.price.add')" :disabled="!canAddPrice" @click="addPrice" />
                            <MalioButton variant="primary" :label="t('transport.carriers.edit.save')" :disabled="tabSubmitting" @click="onSubmitPrices" />
                        </div>
                    </div>
                </template>
            </MalioTabList>
        </template>

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

<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { extractApiErrorMessage } from '~/shared/utils/api'
import { isRowRemovable } from '~/shared/utils/collectionRow'
import CarrierAddressBlock from '~/modules/transport/components/CarrierAddressBlock.vue'
import CarrierContactBlock from '~/modules/transport/components/CarrierContactBlock.vue'
import CarrierPriceBlock from '~/modules/transport/components/CarrierPriceBlock.vue'
import CarrierQualimatTab from '~/modules/transport/components/CarrierQualimatTab.vue'
import { useCarrierForm } from '~/modules/transport/composables/useCarrierForm'
import { useCarrier } from '~/modules/transport/composables/useCarrier'
import type { QualimatCarrierRow } from '~/modules/transport/composables/useQualimatSearch'
import { clampPercent, LIOT_PLATES_MASK, sanitizeDecimal } from '~/modules/transport/utils/forms/numberInput'
import { FREE_TEXT_MASK } from '~/shared/utils/textSanitize'

interface SelectOption {
    value: string
    label: string
}

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

const carrierId = route.params.id as string
useHead({ title: t('transport.carriers.edit.title') })

// Gating route : l'édition est réservée à `manage` ; sinon retour consultation.
if (!can('transport.carriers.manage')) {
    await navigateTo(`/carriers/${carrierId}`)
}

const { carrier, loading, error, load } = useCarrier(carrierId)

const {
    main,
    mainSubmitting,
    tabSubmitting,
    mainErrors,
    dischargeUploading,
    selectDischarge,
    clearDischarge,
    setCertification,
    isLiot,
    certificationReadonly,
    showCharteredFields,
    showDischarge,
    applyQualimatSelection,
    address,
    addressErrors,
    submitAddress,
    contacts,
    contactErrors,
    canAddContact,
    addContact,
    removeContact,
    submitContacts,
    prices,
    priceErrors,
    canAddPrice,
    addPrice,
    removePrice,
    submitPrices,
    updateMain,
    prefillFrom,
} = useCarrierForm()

const SELECTABLE_CERTIFICATIONS = ['GMP_PLUS', 'OVOCOM', 'COMPTE_PROPRE', 'AUTRE'] as const
const certificationOptions = computed<SelectOption[]>(() => {
    const codes: string[] = [...SELECTABLE_CERTIFICATIONS]
    if (main.certificationType === 'QUALIMAT') codes.unshift('QUALIMAT')
    return codes.map(code => ({ value: code, label: t(`transport.carriers.certification.${code}`) }))
})


const TAB_ICONS: Record<string, string> = {
    qualimat: 'mdi:truck-fast-outline',
    addresses: 'mdi:map-marker-outline',
    contacts: 'mdi:account-box-plus-outline',
    prices: 'mdi:payment',
}
// Onglet Qualimat disponible en modif (ERP-172) : « actualiser » nom + certification.
const TAB_KEYS = ['qualimat', 'addresses', 'contacts', 'prices']
// ERP-193 : on honore l'onglet demande via `?tab=` (navigation depuis la
// consultation) pour retomber sur le meme onglet ; defaut « addresses ».
const requestedTab = typeof route.query.tab === 'string' ? route.query.tab : ''
const activeTab = ref(TAB_KEYS.includes(requestedTab) ? requestedTab : 'addresses')
const tabs = computed(() => TAB_KEYS.map(key => ({
    key,
    label: t(`transport.carriers.tab.${key}`),
    icon: TAB_ICONS[key],
})))

// ── Référentiels (pays + clients / fournisseurs / sites pour l'onglet Prix) ───
const countryOptions = ref<SelectOption[]>([{ value: 'France', label: 'France' }])
const clientOptions = ref<SelectOption[]>([])
const supplierOptions = ref<SelectOption[]>([])
const siteOptions = ref<SelectOption[]>([])

async function loadOptions(url: string, target: typeof clientOptions, labelOf: (m: Record<string, unknown>) => string): Promise<void> {
    try {
        const data = await api.get<{ member?: Record<string, unknown>[] }>(url, { pagination: 'false' }, { headers: { Accept: 'application/ld+json' }, toast: false })
        target.value = (data.member ?? []).map(m => ({ value: String(m['@id']), label: labelOf(m) }))
    }
    catch {
        target.value = []
    }
}

async function loadCountries(): Promise<void> {
    try {
        const data = await api.get<{ member?: { name: string }[] }>('/countries', { pagination: 'false' }, { headers: { Accept: 'application/ld+json' }, toast: false })
        const list = (data.member ?? []).map(c => ({ value: c.name, label: c.name }))
        countryOptions.value = list.some(c => c.value === 'France') ? list : [{ value: 'France', label: 'France' }, ...list]
    }
    catch { /* fallback France */ }
}

// ── Chargement + préremplissage ──────────────────────────────────────────────
onMounted(async () => {
    await load()
    if (carrier.value) {
        prefillFrom(carrier.value)
        // Pré-affiche le nom du fichier de décharge déjà rattaché (s'il existe).
        const doc = carrier.value.dischargeDocument
        if (doc && typeof doc !== 'string') {
            const meta = doc as Record<string, unknown>
            dischargeFileName.value = String(meta.originalFilename ?? meta.name ?? '')
        }
    }
    loadCountries().catch(() => {})
    void loadOptions('/clients', clientOptions, m => String(m.companyName ?? m['@id']))
    void loadOptions('/suppliers', supplierOptions, m => String(m.companyName ?? m['@id']))
    void loadOptions('/sites', siteOptions, m => String(m.name ?? m['@id']))
})

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

// Nom de fichier affiché dans le champ Décharge (alimenté à la sélection ou au
// chargement d'un transporteur ayant déjà une décharge).
const dischargeFileName = ref('')

/** Vidage du champ Décharge : oublie le fichier en attente / l'IRI + le nom affiché. */
function onClearDischarge(): void {
    clearDischarge()
    dischargeFileName.value = ''
}

// Indexation plafonnée à 100 % : la clé force le ré-affichage du MalioInputAmount
// (contrôlé) quand le plafonnement laisse le modelValue inchangé.
const indexationKey = ref(0)

/** Saisie de l'indexation : plafonne à 100 et re-synchronise le champ si plafonné. */
function onIndexationInput(value: string): void {
    const clamped = clampPercent(value)
    main.indexationRate = clamped
    if (clamped !== value) {
        indexationKey.value += 1
    }
}

function goBack(): void {
    // ERP-193 : on transmet l'onglet courant pour retomber dessus en consultation.
    router.push({ path: `/carriers/${carrierId}`, query: { tab: activeTab.value } })
}

/** PATCH du formulaire principal (pas de re-POST). */
async function onUpdateMain(): Promise<void> {
    const ok = await updateMain()
    if (ok) {
        toast.success({ title: t('transport.carriers.toast.updateSuccess') })
    }
}

/** Intégration d'une ligne QUALIMAT (onglet Qualimat) : actualise nom + certification
 *  + FK via PATCH (applyQualimatSelection). L'adresse existante n'est pas touchée. */
async function onIntegrateQualimat(row: QualimatCarrierRow): Promise<void> {
    const ok = await applyQualimatSelection(row)
    if (ok) {
        toast.success({ title: t('transport.carriers.toast.integrateSuccess') })
    }
}

async function onSubmitAddresses(): Promise<void> {
    const ok = await submitAddress(err => toast.error({ title: t('transport.carriers.toast.error'), message: apiErrorMessage(err) }))
    if (ok) toast.success({ title: t('transport.carriers.toast.addressSaved') })
}
async function onSubmitContacts(): Promise<void> {
    const ok = await submitContacts(err => toast.error({ title: t('transport.carriers.toast.error'), message: apiErrorMessage(err) }))
    if (ok) toast.success({ title: t('transport.carriers.toast.contactSaved') })
}
async function onSubmitPrices(): Promise<void> {
    const ok = await submitPrices(err => toast.error({ title: t('transport.carriers.toast.error'), message: apiErrorMessage(err) }))
    if (ok) toast.success({ title: t('transport.carriers.toast.priceSaved') })
}

// ── Suppression de bloc (modal de confirmation générique) ────────────────────
const deleteConfirm = reactive({ open: false, action: null as null | (() => void) })

function askRemoveContact(index: number): void {
    deleteConfirm.action = () => { void removeContact(index) }
    deleteConfirm.open = true
}
function askRemovePrice(index: number): void {
    deleteConfirm.action = () => { void removePrice(index) }
    deleteConfirm.open = true
}
function runDeleteConfirm(): void {
    deleteConfirm.action?.()
    deleteConfirm.action = null
    deleteConfirm.open = false
}

function onAddressDegraded(): void {
    toast.warning({ title: t('transport.carriers.toast.error'), message: t('transport.carriers.form.address.degraded') })
}
</script>
