<template>
    <div class="relative grid grid-cols-4 gap-x-[44px] gap-y-4 bg-white py-4 pl-[28px] pr-[60px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]">
        <!-- Suppression : modal de confirmation côté parent. -->
        <MalioButtonIcon
            v-if="removable && !readonly"
            icon="mdi:delete-outline"
            variant="ghost"
            button-class="absolute top-3 right-3"
            v-bind="{ ariaLabel: t('transport.carriers.form.price.remove') }"
            @click="$emit('remove')"
        />

        <!-- RG-4.09 : sens du prix (CLIENT / FOURNISSEUR) en colonne 1 / ligne 1, radios
             EN LIGNE (horizontaux), centrés sur la hauteur de champ (h-12) comme la
             case « Affréter ». Pas de label de groupe. -->
        <div>
            <div class="flex h-12 items-center gap-6">
                <MalioRadioButton
                    :model-value="model.direction"
                    :name="`price-direction-${uid}`"
                    value="CLIENT"
                    :label="t('transport.carriers.form.price.directionClient')"
                    :disabled="readonly"
                    group-class="mt-0"
                    @update:model-value="onDirectionChange"
                />
                <MalioRadioButton
                    :model-value="model.direction"
                    :name="`price-direction-${uid}`"
                    value="FOURNISSEUR"
                    :label="t('transport.carriers.form.price.directionSupplier')"
                    :disabled="readonly"
                    group-class="mt-0"
                    @update:model-value="onDirectionChange"
                />
            </div>
            <p v-if="errors?.direction" class="ml-[2px] text-xs text-m-danger">{{ errors.direction }}</p>
        </div>

        <!-- Branche CLIENT (RG-4.10). -->
        <template v-if="model.direction === 'CLIENT'">
            <MalioSelect
                :model-value="model.clientIri"
                :options="clientOptions"
                :label="t('transport.carriers.form.price.client')"
                empty-option-label=""
                :required="true"
                :readonly="readonly"
                :error="errors?.client"
                @update:model-value="onClientChange"
            />
            <MalioSelect
                :model-value="model.clientDeliveryAddressIri"
                :options="clientAddressOptions"
                :label="t('transport.carriers.form.price.clientDeliveryAddress')"
                empty-option-label=""
                :required="true"
                :readonly="readonly"
                :error="errors?.clientDeliveryAddress"
                @update:model-value="(v: string | number | null) => update('clientDeliveryAddressIri', v === null ? null : String(v))"
            />
            <MalioSelect
                :model-value="model.departureSiteIri"
                :options="siteOptions"
                :label="t('transport.carriers.form.price.departureSite')"
                empty-option-label=""
                :required="true"
                :readonly="readonly"
                :error="errors?.departureSite"
                @update:model-value="(v: string | number | null) => update('departureSiteIri', v === null ? null : String(v))"
            />
        </template>

        <!-- Branche FOURNISSEUR (RG-4.11). -->
        <template v-else-if="model.direction === 'FOURNISSEUR'">
            <MalioSelect
                :model-value="model.supplierIri"
                :options="supplierOptions"
                :label="t('transport.carriers.form.price.supplier')"
                empty-option-label=""
                :required="true"
                :readonly="readonly"
                :error="errors?.supplier"
                @update:model-value="onSupplierChange"
            />
            <MalioSelect
                :model-value="model.supplierSupplyAddressIri"
                :options="supplierAddressOptions"
                :label="t('transport.carriers.form.price.supplierSupplyAddress')"
                empty-option-label=""
                :required="true"
                :readonly="readonly"
                :error="errors?.supplierSupplyAddress"
                @update:model-value="(v: string | number | null) => update('supplierSupplyAddressIri', v === null ? null : String(v))"
            />
            <MalioSelect
                :model-value="model.deliverySiteIri"
                :options="siteOptions"
                :label="t('transport.carriers.form.price.deliverySite')"
                empty-option-label=""
                :required="true"
                :readonly="readonly"
                :error="errors?.deliverySite"
                @update:model-value="(v: string | number | null) => update('deliverySiteIri', v === null ? null : String(v))"
            />
        </template>

        <!-- Communs (visibles dès qu'un sens est choisi). -->
        <template v-if="model.direction !== null">
            <!-- Contenant : Benne / Fond mouvant (radios centrés h-12, pas de label). -->
            <div>
                <div class="flex h-12 items-center gap-4">
                    <MalioRadioButton
                        :model-value="model.containerType"
                        :name="`price-container-${uid}`"
                        value="BENNE"
                        :label="t('transport.carriers.containerType.BENNE')"
                        :disabled="readonly"
                        group-class="mt-0"
                        @update:model-value="(v: string | number | boolean | null) => update('containerType', v === null ? null : String(v))"
                    />
                    <MalioRadioButton
                        :model-value="model.containerType"
                        :name="`price-container-${uid}`"
                        value="FOND_MOUVANT"
                        :label="t('transport.carriers.containerType.FOND_MOUVANT')"
                        :disabled="readonly"
                        group-class="mt-0"
                        @update:model-value="(v: string | number | boolean | null) => update('containerType', v === null ? null : String(v))"
                    />
                </div>
                <p v-if="errors?.containerType" class="ml-[2px] text-xs text-m-danger">{{ errors.containerType }}</p>
            </div>

            <!-- Tarification : Forfait / Tonne (radios centrés h-12, pas de label). -->
            <div>
                <div class="flex h-12 items-center gap-4">
                    <MalioRadioButton
                        :model-value="model.pricingUnit"
                        :name="`price-unit-${uid}`"
                        value="FORFAIT"
                        :label="t('transport.carriers.form.price.pricingForfait')"
                        :disabled="readonly"
                        group-class="mt-0"
                        @update:model-value="(v: string | number | boolean | null) => update('pricingUnit', v === null ? null : String(v))"
                    />
                    <MalioRadioButton
                        :model-value="model.pricingUnit"
                        :name="`price-unit-${uid}`"
                        value="TONNE"
                        :label="t('transport.carriers.form.price.pricingTonne')"
                        :disabled="readonly"
                        group-class="mt-0"
                        @update:model-value="(v: string | number | boolean | null) => update('pricingUnit', v === null ? null : String(v))"
                    />
                </div>
                <p v-if="errors?.pricingUnit" class="ml-[2px] text-xs text-m-danger">{{ errors.pricingUnit }}</p>
            </div>

            <MalioInputAmount
                :model-value="model.price"
                :label="t('transport.carriers.form.price.price')"
                :required="true"
                :readonly="readonly"
                :error="errors?.price"
                @update:model-value="(v: string) => update('price', v)"
            />

            <MalioSelect
                :model-value="model.priceState"
                :options="priceStateOptions"
                :label="t('transport.carriers.form.price.priceState')"
                empty-option-label=""
                :required="true"
                :readonly="readonly"
                :error="errors?.priceState"
                @update:model-value="(v: string | number | null) => update('priceState', v === null ? null : String(v))"
            />
        </template>
    </div>
</template>

<script setup lang="ts">
import { computed, ref, useId, watch } from 'vue'
import type { CarrierPriceFormDraft } from '~/modules/transport/types/carrierForm'

interface SelectOption {
    value: string
    label: string
}

const props = defineProps<{
    /** Brouillon du prix (v-model). */
    modelValue: CarrierPriceFormDraft
    /** Clients disponibles (IRI en value). */
    clientOptions: SelectOption[]
    /** Fournisseurs disponibles (IRI en value). */
    supplierOptions: SelectOption[]
    /** Sites Starseed (3 sites — IRI en value). */
    siteOptions: SelectOption[]
    removable?: boolean
    readonly?: boolean
    /** Erreurs serveur 422 de cette ligne, indexées par champ (ERP-101). */
    errors?: Record<string, string>
}>()

const emit = defineEmits<{
    'update:modelValue': [value: CarrierPriceFormDraft]
    'remove': []
}>()

const { t } = useI18n()
const api = useApi()

// Identifiant unique par instance : les groupes de radios (sens / contenant / tarif)
// doivent avoir un `name` PROPRE à chaque bloc prix, sinon plusieurs blocs partagent
// le même groupe HTML et leurs radios se désélectionnent mutuellement.
const uid = useId()

const model = computed(() => props.modelValue)

const priceStateOptions = computed<SelectOption[]>(() => [
    { value: 'EN_COURS', label: t('transport.carriers.form.price.stateEnCours') },
    { value: 'VALIDE', label: t('transport.carriers.form.price.stateValide') },
    { value: 'NON_VALIDE', label: t('transport.carriers.form.price.stateNonValide') },
])

// Adresses chargées à la volée pour le client / fournisseur sélectionné (par bloc).
const clientAddressOptions = ref<SelectOption[]>([])
const supplierAddressOptions = ref<SelectOption[]>([])

/** Émet un nouveau brouillon avec le champ modifié (immutabilité). */
function update<K extends keyof CarrierPriceFormDraft>(field: K, value: CarrierPriceFormDraft[K]): void {
    emit('update:modelValue', { ...props.modelValue, [field]: value })
}

/** Changement de sens : réinitialise les DEUX branches (cohérence CHECK BDD). */
function onDirectionChange(value: string | number | boolean | null): void {
    const direction = value === 'CLIENT' || value === 'FOURNISSEUR' ? value : null
    emit('update:modelValue', {
        ...props.modelValue,
        direction,
        clientIri: null,
        clientDeliveryAddressIri: null,
        departureSiteIri: null,
        supplierIri: null,
        supplierSupplyAddressIri: null,
        deliverySiteIri: null,
    })
}

/** Sélection d'un client → maj IRI + reset de l'adresse de livraison (autre client). */
function onClientChange(value: string | number | null): void {
    emit('update:modelValue', {
        ...props.modelValue,
        clientIri: value === null ? null : String(value),
        clientDeliveryAddressIri: null,
    })
}

/** Sélection d'un fournisseur → maj IRI + reset de l'adresse d'appro. */
function onSupplierChange(value: string | number | null): void {
    emit('update:modelValue', {
        ...props.modelValue,
        supplierIri: value === null ? null : String(value),
        supplierSupplyAddressIri: null,
    })
}

/** Réponse détail (client / fournisseur) embarquant ses adresses. */
interface ParentWithAddresses {
    addresses?: { '@id': string, street?: string | null, postalCode?: string | null, city?: string | null }[]
}

/** Mappe les adresses embarquées en options (IRI en value, voie · CP · ville en label). */
function toAddressOptions(parent: ParentWithAddresses): SelectOption[] {
    return (parent.addresses ?? []).map(a => ({
        value: a['@id'],
        label: [a.street, a.postalCode, a.city].filter(Boolean).join(' · ') || a['@id'],
    }))
}

/**
 * Charge les adresses d'un parent (client/fournisseur) à la volée via son détail
 * (GET de l'IRI, qui embarque `addresses`). Échec → liste vide (non bloquant).
 */
async function loadAddresses(iri: string | null, target: typeof clientAddressOptions): Promise<void> {
    if (!iri) {
        target.value = []
        return
    }
    try {
        // L'IRI est absolue (/api/clients/5) ; useApi préfixe déjà /api → on le retire.
        const path = iri.replace(/^\/api/, '')
        const data = await api.get<ParentWithAddresses>(path, {}, { headers: { Accept: 'application/ld+json' }, toast: false })
        target.value = toAddressOptions(data)
    }
    catch {
        target.value = []
    }
}

// Recharge les adresses quand le client / fournisseur change (immediate pour le
// pré-remplissage en édition).
watch(() => props.modelValue.clientIri, iri => loadAddresses(iri, clientAddressOptions), { immediate: true })
watch(() => props.modelValue.supplierIri, iri => loadAddresses(iri, supplierAddressOptions), { immediate: true })
</script>
