<template>
    <div class="flex flex-col items-center gap-16">
<!--        @TODO voir pour séparer dans un composant au moment de l'implémentation des Bovins      -->
        <div
            v-if="receptionStore.current?.receptionType?.code === RECEPTION_TYPE_CODES.MERCHANDISES"
            class="flex flex-col gap-8 items-center w-full">
            <h1 class="text-4xl uppercase font-bold">Sélectionner des marchandises réceptionnnées</h1>
            <UiSelect
                id="merchandise-type"
                v-model="selectedMerchandiseTypeId"
                label="Type de marchandises"
                :options="merchandiseTypes.map((type) => ({ value: String(type.id), label: type.label }))"
                wrapper-class="w-[550px]"
            />

            <div
                v-if="selectedMerchandiseTypeId && isAutres"
                class="flex flex-col w-full max-w-[550px]"
            >
                <UiTextInput
                    id="merchandise-detail"
                    v-model="merchandiseDetail"
                    label="Préciser"
                    placeholder="Précisions complémentaires"
                    :maxlength="255"
                />
            </div>

            <div
                v-if="selectedMerchandiseTypeId && !isGranule"
                class="flex gap-4 w-[550px] justify-evenly"
            >
                <div
                    v-for="building in buildings"
                    :key="building.id"
                >
                    <UiCheckbox
                        v-model="selectedBuildingIds"
                        :value="String(building.id)"
                        :label="building.label"
                        label-class="text-xl"
                    />
                </div>
            </div>

            <div
                v-if="selectedMerchandiseTypeId && isGranule"
                class="flex flex-col gap-10 w-full max-w-[900px]"
            >
                <div class="grid grid-cols-1 gap-10 md:grid-cols-4">
                    <div v-for="type in pelletTypes" :key="type.id" class="flex flex-col gap-4">
                        <p class="font-bold uppercase">{{ type.label }}</p>
                        <div
                            v-for="building in buildings"
                            :key="building.id"
                            class="flex items-center gap-2 text-lg"
                        >
                            <UiCheckbox
                                v-model="selectedPelletBuildingIds[String(type.id)]"
                                :value="String(building.id)"
                                :label="building.label"
                                label-class="text-lg"
                            />
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <button
            class="text-xl uppercase bg-primary-500 text-white h-[50px] w-[272px]"
            @click="goNext"
        >Peser</button>
    </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { getBuildingList } from '~/services/building'
import { getMerchandiseTypeList } from '~/services/merchandise-type'
import type { MerchandiseTypeData } from '~/services/dto/merchandise-type-data'
import type { BuildingData } from '~/services/dto/building-data'
import type { PelletTypeData } from '~/services/dto/pellet-type-data'
import { getPelletTypeList } from '~/services/pellet-type'
import {
    createReceptionPelletBuilding,
    deleteReceptionPelletBuilding,
    getReceptionPelletBuildingList
} from '~/services/reception-pellet-building'
import { useReceptionStore } from '~/stores/reception'
import { MERCHANDISE_TYPE_CODES, RECEPTION_TYPE_CODES } from '~/utils/constants'

const receptionStore = useReceptionStore()
const merchandiseTypes = ref<MerchandiseTypeData[]>([])
const buildings = ref<BuildingData[]>([])
const pelletTypes = ref<PelletTypeData[]>([])
const selectedMerchandiseTypeId = ref('')
const selectedBuildingIds = ref<string[]>([])
const selectedPelletBuildingIds = ref<Record<string, string[]>>({})
const merchandiseDetail = ref('')

// Type de marchandise sélectionné dans le select
const selectedMerchandiseType = computed(() =>
    merchandiseTypes.value.find((type) => String(type.id) === selectedMerchandiseTypeId.value)
)
// Indique si le type est "Granulé"
const isGranule = computed(() => selectedMerchandiseType.value?.code === MERCHANDISE_TYPE_CODES.GRANULE)
// Indique si le type est "Autres"
const isAutres = computed(() => selectedMerchandiseType.value?.code === MERCHANDISE_TYPE_CODES.AUTRES)

// Charge les référentiels et hydrate le formulaire depuis la réception
onMounted(async () => {
    const [merchandiseTypeList, buildingList, pelletTypeList] = await Promise.all([
        getMerchandiseTypeList(),
        getBuildingList(),
        getPelletTypeList()
    ])
    merchandiseTypes.value = merchandiseTypeList
    buildings.value = buildingList
    pelletTypes.value = pelletTypeList

    const currentId = receptionStore.current?.merchandiseType?.id
    if (currentId) {
        selectedMerchandiseTypeId.value = String(currentId)
    }
    merchandiseDetail.value = receptionStore.current?.merchandiseDetail ?? ''

    selectedBuildingIds.value =
        receptionStore.current?.buildings?.map((building) => String(building.id)) ?? []

    const existingPelletSelections = receptionStore.current?.pelletBuildings ?? []
    const selectionMap: Record<string, string[]> = {}
    for (const selection of existingPelletSelections) {
        const pelletTypeId = String(selection.pelletType.id)
        const buildingId = String(selection.building.id)
        if (!selectionMap[pelletTypeId]) {
            selectionMap[pelletTypeId] = []
        }
        selectionMap[pelletTypeId].push(buildingId)
    }
    for (const pelletType of pelletTypes.value) {
        const key = String(pelletType.id)
        if (!selectionMap[key]) {
            selectionMap[key] = []
        }
    }
    selectedPelletBuildingIds.value = selectionMap
})

// Enregistre les sélections et passe à l'étape suivante
async function goNext() {
    if (!receptionStore.current) {
        return
    }

    const nextStep = receptionStore.current.currentStep + 1
    const receptionIri = `/api/receptions/${receptionStore.current.id}`

    await receptionStore.updateReception(receptionStore.current.id, {
        merchandiseType: selectedMerchandiseTypeId.value
            ? `/api/merchandise_types/${selectedMerchandiseTypeId.value}`
            : null,
        merchandiseDetail: isAutres.value ? merchandiseDetail.value.trim() : null,
        buildings: isGranule.value
            ? []
            : selectedBuildingIds.value.map((id) => `/api/buildings/${id}`),
        currentStep: nextStep
    })

    if (isGranule.value) {
        await syncPelletSelections(receptionIri)
    } else {
        await clearPelletSelections(receptionIri)
    }
}

// Supprime toutes les associations granulés/bâtiments existantes
async function clearPelletSelections(receptionIri: string) {
    const existing = await getReceptionPelletBuildingList(receptionIri)
    for (const selection of existing) {
        await deleteReceptionPelletBuilding(selection.id)
    }
}

// Synchronise les associations granulés/bâtiments avec l'état du formulaire
async function syncPelletSelections(receptionIri: string) {
    const existing = await getReceptionPelletBuildingList(receptionIri)
    const existingMap = new Map<string, number>()
    for (const selection of existing) {
        const key = `${selection.pelletType.id}:${selection.building.id}`
        existingMap.set(key, selection.id)
    }

    const desiredEntries: Array<{ pelletTypeId: string; buildingId: string }> = []
    for (const [pelletTypeId, buildingIds] of Object.entries(selectedPelletBuildingIds.value)) {
        for (const buildingId of buildingIds) {
            desiredEntries.push({ pelletTypeId, buildingId })
        }
    }

    const desiredKeys = new Set(desiredEntries.map(
        (entry) => `${entry.pelletTypeId}:${entry.buildingId}`
    ))

    for (const [key, id] of existingMap.entries()) {
        if (!desiredKeys.has(key)) {
            await deleteReceptionPelletBuilding(id)
        }
    }

    for (const entry of desiredEntries) {
        const key = `${entry.pelletTypeId}:${entry.buildingId}`
        if (!existingMap.has(key)) {
            await createReceptionPelletBuilding({
                reception: receptionIri,
                pelletType: `/api/pellet_types/${entry.pelletTypeId}`,
                building: `/api/buildings/${entry.buildingId}`
            })
        }
    }
}
</script>
