<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"
                    :label="t('transport.carriers.form.main.name')"
                    :required="true"
                    :error="mainErrors.errors.name"
                />
                <MalioInputText
                    v-if="isLiot"
                    v-model="main.liotPlates"
                    :label="t('transport.carriers.form.main.liotPlates')"
                    :hint="t('transport.carriers.form.main.liotPlatesHint')"
                    :required="true"
                    :error="mainErrors.errors.liotPlates"
                />
                <template v-if="!isLiot">
                    <MalioSelect
                        :model-value="main.certificationType"
                        :options="certificationOptions"
                        :label="t('transport.carriers.form.main.certificationType')"
                        empty-option-label=""
                        :required="true"
                        :readonly="certificationReadonly"
                        :error="mainErrors.errors.certificationType"
                        @update:model-value="(v: string | number | null) => main.certificationType = v === null ? null : String(v)"
                    />
                    <MalioInputUpload
                        v-if="showDischarge"
                        :label="t('transport.carriers.form.main.discharge')"
                        accept="application/pdf,image/*"
                        :required="true"
                        :clearable="true"
                        :error="mainErrors.errors.dischargeDocument"
                        @clear="main.dischargeDocumentIri = null"
                    />
                    <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
                            :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="(v: string) => main.indexationRate = clampPercent(v)"
                        />
                        <MalioSelect
                            :model-value="main.containerType"
                            :options="containerOptions"
                            :label="t('transport.carriers.form.main.containerType')"
                            empty-option-label=""
                            :required="true"
                            :error="mainErrors.errors.containerType"
                            @update:model-value="(v: string | number | null) => main.containerType = v === null ? null : String(v)"
                        />
                        <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]">
                <template #addresses>
                    <div class="mt-12 flex flex-col gap-6">
                        <CarrierAddressBlock
                            v-for="(address, index) in addresses"
                            :key="index"
                            :model-value="address"
                            :country-options="countryOptions"
                            :removable="isRowRemovable(addresses, index)"
                            :errors="addressErrors[index]"
                            @update:model-value="(v) => addresses[index] = v"
                            @remove="askRemoveAddress(index)"
                            @degraded="onAddressDegraded"
                        />
                        <div class="flex justify-center gap-6">
                            <MalioButton variant="secondary" icon-name="mdi:add-bold" icon-position="left" :label="t('transport.carriers.form.address.add')" :disabled="!canAddAddress" @click="addAddress" />
                            <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 { useCarrierForm } from '~/modules/transport/composables/useCarrierForm'
import { useCarrier } from '~/modules/transport/composables/useCarrier'
import { clampPercent, sanitizeDecimal } from '~/modules/transport/utils/forms/numberInput'

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,
    isLiot,
    certificationReadonly,
    showCharteredFields,
    showDischarge,
    addresses,
    addressErrors,
    canAddAddress,
    addAddress,
    removeAddress,
    submitAddresses,
    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 CONTAINER_TYPES = ['BENNE', 'FOND_MOUVANT'] as const
const containerOptions = computed<SelectOption[]>(() =>
    CONTAINER_TYPES.map(code => ({ value: code, label: t(`transport.carriers.containerType.${code}`) })),
)

const TAB_ICONS: Record<string, string> = {
    addresses: 'mdi:map-marker-outline',
    contacts: 'mdi:account-box-plus-outline',
    prices: 'mdi:currency-eur',
}
const activeTab = ref('addresses')
const tabs = computed(() => ['addresses', 'contacts', 'prices'].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)
    }
    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')
}

function goBack(): void {
    router.push(`/carriers/${carrierId}`)
}

/** 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') })
    }
}

async function onSubmitAddresses(): Promise<void> {
    const ok = await submitAddresses(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 askRemoveAddress(index: number): void {
    deleteConfirm.action = () => { void removeAddress(index) }
    deleteConfirm.open = true
}
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>
