<template>
    <form>
        <div class="flex flex-row justify-between gap-x-12  font-bold uppercase mb-8">
            <div
                v-for="type in bovineType"
                :key="type.id"
            >
                <UiNumberInput
                    :label="type.label"
                    :code="type.code"
                    v-model="bovineQuantities[String(type.id)]"
                    :disabled="!auth.isAdmin"
                    :placeholder="0"
                    :min="0"
                    :max="10"
                    wrapperClass="w-44"
                />
            </div>

            <UiNumberInput
                label="Autres"
                v-model="otherQuantity"
                :disabled="!auth.isAdmin"
                wrapperClass="w-44"
            />
        </div>
    </form>
</template>
<script setup lang="ts">
import type {BovineTypeData} from "~/services/dto/bovine-type-data";
import {getBovineTypeList} from "~/services/bovine-type";
import {createReceptionBovine, deleteReceptionBovine, getReceptionBovineList, updateReceptionBovine} from "~/services/reception-bovine";
import {computed, onMounted, reactive, ref, watch} from "vue";
import {getReception, updateReception} from "~/services/reception";

const toast = useToast()
const isLoadingBovineType = ref(false)
const bovineType = ref<BovineTypeData[]>([])
const bovineQuantities = reactive<Record<string, number | null>>({})
const otherQuantity = ref<number | null>(0)
const initialBovineQuantities = ref<Record<string, number | null>>({})
const initialOtherQuantity = ref<number | null>(0)
const auth = useAuthStore()

const props = defineProps<{
    idReception: number
    isValidate: boolean
}>()

const receptionId = props.idReception
const reception = await getReception(receptionId)

const receptionIri = computed(() =>
    receptionId ? `/api/receptions/${receptionId}` : null
)

const totalBovines = computed(() => {
    const base = Object.values(bovineQuantities).reduce((sum, value) => {
        return sum + (value ?? 0)
    }, 0)
    return base + (otherQuantity.value ?? 0)
})

const hasBovineChanged = () => {
    if ((initialOtherQuantity.value ?? 0) !== (otherQuantity.value ?? 0)) {
        return true
    }

    for (const [key, value] of Object.entries(bovineQuantities)) {
        if ((initialBovineQuantities.value[key] ?? 0) !== (value ?? 0)) {
            return true
        }
    }

    return false
}

const loadBovineType = async () => {
    isLoadingBovineType.value = true
    try {
        bovineType.value = await getBovineTypeList()
    } finally {
        isLoadingBovineType.value = false
    }
}

onMounted(async () => {
    await loadBovineType()
})

watch(
    [() => receptionId, () => bovineType.value],
    async ([id, types]) => {
        if (!id || !receptionIri.value || types.length === 0) {
            return
        }

        const selectionMap: Record<string, number | null> = {}
        for (const type of types) {
            selectionMap[String(type.id)] = 0
        }

        const existing = await getReceptionBovineList(receptionIri.value)
        for (const selection of existing) {
            const bovineTypeId = String(selection.bovineType.id)
            selectionMap[bovineTypeId] = selection.quantity ?? 0
        }

        for (const key of Object.keys(bovineQuantities)) {
            delete bovineQuantities[key]
        }
        Object.assign(bovineQuantities, selectionMap)

        const existingOther = reception.bovineDetail
        const parsedOther =
            typeof existingOther === 'string' && existingOther.trim() !== ''
                ? Number(existingOther)
                : 0
        otherQuantity.value = Number.isFinite(parsedOther) ? parsedOther : 0
        initialBovineQuantities.value = {...selectionMap}
        initialOtherQuantity.value = otherQuantity.value ?? 0
    },
    {immediate: true}
)

async function syncBovineSelections(receptionIri: string) {
    const existing = await getReceptionBovineList(receptionIri)
    const existingMap = new Map<string, { id: number; quantity: number | null }>()

    for (const selection of existing) {
        const bovineTypeId = String(selection.bovineType.id)
        existingMap.set(bovineTypeId, {
            id: selection.id,
            quantity: selection.quantity ?? 0
        })
    }

    // Supprime les entrées supprimées ou modifiées
    for (const [bovineTypeId, entry] of existingMap.entries()) {
        const selectedQuantity = bovineQuantities[bovineTypeId] ?? 0
        if (!selectedQuantity) {
            await deleteReceptionBovine(entry.id)
            existingMap.delete(bovineTypeId)
            continue
        }

        if (selectedQuantity !== entry.quantity) {
            await updateReceptionBovine(entry.id, {quantity: selectedQuantity})
            existingMap.set(bovineTypeId, {
                id: entry.id,
                quantity: selectedQuantity
            })
        }
    }

    // Crée les entrées manquantes
    for (const [bovineTypeId, quantity] of Object.entries(bovineQuantities)) {
        if (!quantity) {
            continue
        }
        if (existingMap.has(bovineTypeId)) {
            continue
        }
        await createReceptionBovine({
            reception: receptionIri,
            bovineType: `/api/bovine_types/${bovineTypeId}`,
            quantity
        })
    }
}

watch(
    () => props.isValidate,
    async (val) => {
        if (!val) return
        await runValidate()
    }
)
const runValidate = async () => {
    if (!hasBovineChanged()) {
        return
    }
    const receptionIri = `/api/receptions/${reception.id}`
    // @TODO Ajouter un composable pour le toaster qui gère les key i18n
    if (totalBovines.value > 52) {
        toast.error({
            title: 'Erreur',
            message: ('Le total des bovins ne peut pas dépasser 52.')
        })
        return
    }

    await syncBovineSelections(receptionIri)

    await updateReception(receptionId, {
        merchandiseType: null,
        merchandiseDetail: null,
        bovineDetail: otherQuantity.value ? String(otherQuantity.value) : null,
    })

    initialBovineQuantities.value = {...bovineQuantities}
    initialOtherQuantity.value = otherQuantity.value ?? 0
}

</script>
