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

<script setup lang="ts">
import { onMounted, reactive, ref, watch } from 'vue'
import { getBovineTypeList } from '~/services/bovine-type'
import type { BovineTypeData } from '~/services/dto/bovine-type-data'
import type { ReceptionBovineTypeData } from '~/services/dto/reception-bovine-data'

const props = defineProps<{
    modelValue: ReceptionBovineTypeData[]
    otherQuantity: number | null
    isAdmin: boolean
}>()

const emit = defineEmits<{
    (event: 'update:modelValue', value: ReceptionBovineTypeData[]): void
    (event: 'update:otherQuantity', value: number | null): void
}>()

const bovineTypes = ref<BovineTypeData[]>([])
const localQuantities = reactive<Record<string, number | null>>({})
const localOtherQuantity = ref<number | null>(props.otherQuantity ?? 0)
const isSyncing = ref(false)

function buildEntriesFromLocal(): ReceptionBovineTypeData[] {
    return bovineTypes.value.map((type) => {
        const existing = props.modelValue.find((entry) => entry.bovineType.id === type.id)
        return {
            id: existing?.id ?? 0,
            bovineType: type,
            quantity: localQuantities[String(type.id)] ?? 0
        }
    })
}

function syncLocalFromProps() {
    isSyncing.value = true
    try {
        for (const key of Object.keys(localQuantities)) {
            delete localQuantities[key]
        }

        for (const type of bovineTypes.value) {
            const existing = props.modelValue.find((entry) => entry.bovineType.id === type.id)
            localQuantities[String(type.id)] = existing?.quantity ?? 0
        }
    } finally {
        isSyncing.value = false
    }
}

watch(
    () => props.otherQuantity,
    (value) => {
        localOtherQuantity.value = value ?? 0
    }
)

watch(localOtherQuantity, (value) => {
    emit('update:otherQuantity', value ?? 0)
})

watch(
    () => props.modelValue,
    () => {
        syncLocalFromProps()
    },
    { deep: true }
)

watch(
    localQuantities,
    () => {
        if (isSyncing.value) {
            return
        }
        emit('update:modelValue', buildEntriesFromLocal())
    },
    { deep: true }
)

onMounted(async () => {
    bovineTypes.value = await getBovineTypeList()
    syncLocalFromProps()
    emit('update:modelValue', buildEntriesFromLocal())
})
</script>
