<template>
    <div>
        <div class="flex flex-wrap items-center justify-between gap-4 pb-10">
            <h1 class="text-4xl font-bold text-primary-500">Calendrier des absences</h1>
            <div class="flex items-center gap-3">
                <div class="flex flex-wrap items-center gap-4 rounded-md border border-neutral-300 px-3 py-2">
                    <div v-for="site in sites" :key="site.id" class="flex items-center gap-2">
                        <div :style="{ backgroundColor: site.color }" class="h-4 w-4 rounded"></div>
                        <label class="text-md" :for="`site-${site.id}`">{{ site.name }}</label>
                        <input
                            :id="`site-${site.id}`"
                            v-model="selectedSiteIds"
                            :value="site.id"
                            type="checkbox"
                            class="h-4 w-4"
                        />
                    </div>
                </div>
                <select
                    v-model="selectedMonth"
                    class="rounded-md border border-neutral-300 bg-white px-3 py-2 text-md text-neutral-900"
                >
                    <option v-for="month in months" :key="month.value" :value="month.value">
                        {{ month.label }}
                    </option>
                </select>
                <select
                    v-model="selectedYear"
                    class="rounded-md border border-neutral-300 bg-white px-3 py-2 text-md text-neutral-900"
                >
                    <option v-for="year in years" :key="year" :value="year">
                        {{ year }}
                    </option>
                </select>
                <button
                    type="button"
                    class="rounded-lg bg-primary-500 px-4 py-2 text-md font-semibold text-white hover:bg-secondary-500"
                    @click="openCreateFromToday"
                >
                    Ajouter une absence
                </button>
            </div>
        </div>

        <div class="max-h-[80vh] overflow-auto rounded-lg border border-neutral-200 bg-white">
            <div class="min-w-[900px]">
                <div class="grid" :style="gridStyle">
                    <div
                        class="sticky left-0 z-20 border-b border-neutral-200 bg-tertiary-500 px-4 py-3 text-md font-semibold text-neutral-700">
                        Employés
                    </div>
                    <div
                        v-for="day in daysInMonth"
                        :key="day.date"
                        class="border-b border-neutral-200 bg-tertiary-500 px-2 py-3 text-center text-xs font-semibold text-neutral-700"
                    >
                        <div>{{ day.label }}</div>
                        <div class="text-[10px] text-neutral-500">{{ day.weekday }}</div>
                    </div>

                    <template v-for="employee in visibleEmployees" :key="employee.id">
                        <div
                            class="sticky left-0 z-10 border-b border-neutral-100 px-4 py-3 text-md font-semibold text-black"
                            :style="{ backgroundColor: employee.site?.color ?? '#304998' }"
                        >
                            {{ formatEmployeeName(employee) }}
                        </div>
                        <div
                            v-for="day in daysInMonth"
                            :key="employee.id + '-' + day.date"
                            class="border-b border-neutral-100 px-2 py-2 text-center text-xs text-neutral-800"
                        >
                            <button
                                type="button"
                                class="flex h-8 w-full items-center justify-center rounded-md border border-neutral-200 text-[11px] font-semibold text-neutral-800 hover:border-primary-500/40"
                                :style="getCellStyle(employee.id, day.date)"
                                @click="openCreate(employee, day.date)"
                            >
                <span v-if="getCellCode(employee.id, day.date)">
                  {{ getCellCode(employee.id, day.date) }}
                </span>
                            </button>
                        </div>
                    </template>
                </div>
            </div>
        </div>


        <AppDrawer v-model="isDrawerOpen" title="Nouvelle absence">
            <form class="space-y-4" @submit.prevent="handleSubmit">
                <div>
                    <label class="text-md font-semibold text-neutral-700" for="employee">Employé</label>
                    <select
                        id="employee"
                        v-model="form.employeeId"
                        class="mt-2 w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-md text-neutral-900"
                    >
                        <option value="" disabled>Choisir un employé</option>
                        <option v-for="employee in employees" :key="employee.id" :value="employee.id">
                            {{ employee.firstName }} {{ employee.lastName }}
                        </option>
                    </select>
                </div>

                <div>
                    <label class="text-md font-semibold text-neutral-700" for="type">Type d'absence</label>
                    <select
                        id="type"
                        v-model="form.typeId"
                        class="mt-2 w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-md text-neutral-900"
                    >
                        <option value="" disabled>Choisir un type</option>
                        <option v-for="type in absenceTypes" :key="type.id" :value="type.id">
                            {{ type.label }} ({{ type.code }})
                        </option>
                    </select>
                </div>

                <div class="grid grid-cols-2 gap-4">
                    <div>
                        <label class="text-md font-semibold text-neutral-700" for="start-date">Date de début</label>
                        <input
                            id="start-date"
                            v-model="form.startDate"
                            type="date"
                            class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-md text-neutral-900"
                        />
                    </div>
                    <div>
                        <label class="text-md font-semibold text-neutral-700" for="end-date">Date de fin</label>
                        <input
                            id="end-date"
                            v-model="form.endDate"
                            type="date"
                            class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-md text-neutral-900"
                        />
                    </div>
                </div>

                <div>
                    <label class="text-md font-semibold text-neutral-700" for="comment">Commentaire</label>
                    <textarea
                        id="comment"
                        v-model="form.comment"
                        rows="3"
                        class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-md text-neutral-900"
                    />
                </div>

                <div class="flex justify-end gap-3 pt-2">
                    <button
                        v-if="editingAbsence"
                        type="button"
                        class="rounded-lg border border-red-200 px-4 py-2 text-md font-semibold text-red-600 hover:bg-red-50"
                        @click="handleDelete"
                    >
                        Supprimer
                    </button>
                    <button
                        type="button"
                        class="rounded-lg border border-neutral-200 px-4 py-2 text-md font-semibold text-neutral-700 hover:bg-neutral-100"
                        @click="closeDrawer"
                    >
                        Annuler
                    </button>
                    <button
                        type="submit"
                        class="rounded-lg bg-primary-500 px-4 py-2 text-md font-semibold text-white hover:bg-secondary-500"
                        :disabled="isSubmitting"
                    >
                        Enregistrer
                    </button>
                </div>
            </form>
        </AppDrawer>
    </div>
</template>

<script setup lang="ts">
import type {Employee} from '~/services/dto/employee'
import type {AbsenceType} from '~/services/dto/absence-type'
import type {Absence} from '~/services/dto/absence'
import {listEmployees} from '~/services/employees'
import {listAbsenceTypes} from '~/services/absence-types'
import {createAbsence, deleteAbsence, listAbsences, updateAbsence} from '~/services/absences'
import {getDaysInMonth, normalizeDate, toYmd} from '~/utils/date'

const employees = ref<Employee[]>([])
const sites = computed(() => {
    const map = new Map<number, { id: number; name: string; color: string }>()
    for (const employee of employees.value) {
        if (employee.site) {
            map.set(employee.site.id, employee.site)
        }
    }
    return Array.from(map.values()).sort((a, b) => a.name.localeCompare(b.name, 'fr'))
})

const selectedSiteIds = ref<number[]>([])
const sitesInitialized = ref(false)

watch(sites, (next) => {
    if (sitesInitialized.value || next.length === 0) return
    selectedSiteIds.value = next.map((site) => site.id)
    sitesInitialized.value = true
}, { immediate: true })

const sortedEmployees = computed(() => {
  return [...employees.value].sort((a, b) => {
    const siteA = a.site?.name ?? ''
    const siteB = b.site?.name ?? ''
    if (siteA !== siteB) return siteA.localeCompare(siteB, 'fr')
        const lastA = a.lastName ?? ''
        const lastB = b.lastName ?? ''
        if (lastA !== lastB) return lastA.localeCompare(lastB, 'fr')
        const firstA = a.firstName ?? ''
        const firstB = b.firstName ?? ''
    return firstA.localeCompare(firstB, 'fr')
  })
})

const visibleEmployees = computed(() => {
    if (selectedSiteIds.value.length === 0) return []
    return sortedEmployees.value.filter((employee) => {
        return employee.site?.id && selectedSiteIds.value.includes(employee.site.id)
    })
})
const absenceTypes = ref<AbsenceType[]>([])
const absences = ref<Absence[]>([])

const isDrawerOpen = ref(false)
const isSubmitting = ref(false)
const editingAbsence = ref<Absence | null>(null)

const now = new Date()
const selectedMonth = ref(now.getMonth())
const selectedYear = ref(now.getFullYear())

const months = [
    {value: 0, label: 'Janvier'},
    {value: 1, label: 'Février'},
    {value: 2, label: 'Mars'},
    {value: 3, label: 'Avril'},
    {value: 4, label: 'Mai'},
    {value: 5, label: 'Juin'},
    {value: 6, label: 'Juillet'},
    {value: 7, label: 'Août'},
    {value: 8, label: 'Septembre'},
    {value: 9, label: 'Octobre'},
    {value: 10, label: 'Novembre'},
    {value: 11, label: 'Décembre'}
]

const years = Array.from({length: 5}, (_, i) => now.getFullYear() - 2 + i)


const daysInMonth = computed(() => getDaysInMonth(selectedYear.value, selectedMonth.value))

const gridStyle = computed(() => ({
    gridTemplateColumns: `220px repeat(${daysInMonth.value.length}, minmax(44px, 1fr))`
}))

const form = reactive({
    employeeId: '' as number | '',
    typeId: '' as number | '',
    startDate: '',
    endDate: '',
    comment: ''
})


const resetForm = () => {
    form.employeeId = ''
    form.typeId = ''
    form.startDate = ''
    form.endDate = ''
    form.comment = ''
}

const closeDrawer = () => {
    isDrawerOpen.value = false
    editingAbsence.value = null
    resetForm()
}

const loadEmployees = async () => {
    employees.value = await listEmployees()
}

const loadAbsenceTypes = async () => {
    absenceTypes.value = await listAbsenceTypes()
}

const loadAbsences = async () => {
    absences.value = await listAbsences()
}

onMounted(async () => {
    await Promise.all([loadEmployees(), loadAbsenceTypes(), loadAbsences()])
})

watch([selectedMonth, selectedYear], async () => {
    await loadAbsences()
})

const getCellAbsence = (employeeId: number, date: string) => {
    const match = absences.value.find((absence) => {
        const employee = absence.employee?.id
        const start = normalizeDate(absence.startDate)
        const end = normalizeDate(absence.endDate)
        return Number(employee) === employeeId && date >= start && date <= end
    })

    if (!match) return null

    return {
        id: match.id,
        code: match.type?.code ?? '',
        color: match.type?.color ?? '#222783'
    }
}

const getCellStyle = (employeeId: number, date: string) => {
    const absence = getCellAbsence(employeeId, date)
    if (!absence) return undefined

    return {
        backgroundColor: absence.color,
        color: '#fff'
    }
}

const getCellCode = (employeeId: number, date: string) => {
    return getCellAbsence(employeeId, date)?.code ?? ''
}

const openCreate = (employee: Employee, date: string) => {
    const existing = absences.value.find((absence) => {
        const start = normalizeDate(absence.startDate)
        const end = normalizeDate(absence.endDate)
        return absence.employee?.id === employee.id && date >= start && date <= end
    })

    if (existing) {
        editingAbsence.value = existing
        form.employeeId = existing.employee.id
        form.typeId = existing.type.id
        form.startDate = normalizeDate(existing.startDate)
        form.endDate = normalizeDate(existing.endDate)
        form.comment = existing.comment ?? ''
    } else {
        editingAbsence.value = null
        form.employeeId = employee.id
        form.startDate = date
        form.endDate = date
        form.typeId = ''
        form.comment = ''
    }

    isDrawerOpen.value = true
}

const openCreateFromToday = () => {
    editingAbsence.value = null
    form.employeeId = ''
    form.typeId = ''
    const now = new Date()
    const today = toYmd(now.getFullYear(), now.getMonth(), now.getDate())
    form.startDate = today
    form.endDate = today
    form.comment = ''
    isDrawerOpen.value = true
}

const handleSubmit = async () => {
    if (isSubmitting.value) return

    isSubmitting.value = true
    try {
        const start = normalizeDate(form.startDate)
        const end = normalizeDate(form.endDate)
        const overlaps = absences.value.filter((absence) => {
            if (absence.employee?.id !== Number(form.employeeId)) return false
            if (editingAbsence.value && absence.id === editingAbsence.value.id) return false
            const aStart = normalizeDate(absence.startDate)
            const aEnd = normalizeDate(absence.endDate)
            return start <= aEnd && end >= aStart
        })

        for (const overlap of overlaps) {
            await deleteAbsence(overlap.id)
        }

        if (editingAbsence.value) {
            await updateAbsence({
                id: editingAbsence.value.id,
                employeeId: Number(form.employeeId),
                typeId: Number(form.typeId),
                startDate: form.startDate,
                endDate: form.endDate,
                comment: form.comment
            })
        } else {
            await createAbsence({
                employeeId: Number(form.employeeId),
                typeId: Number(form.typeId),
                startDate: form.startDate,
                endDate: form.endDate,
                comment: form.comment
            })
        }

        closeDrawer()
        await loadAbsences()
    } finally {
        isSubmitting.value = false
    }
}

const handleDelete = async () => {
    if (!editingAbsence.value) return

    const ok = window.confirm('Supprimer cette absence ?')
    if (!ok) return

    await deleteAbsence(editingAbsence.value.id)
    closeDrawer()
    await loadAbsences()
}

const formatEmployeeName = (employee: Employee) => {
    const initial = employee.lastName ? `${employee.lastName[0].toUpperCase()}.` : ''
    return `${employee.firstName} ${initial}`.trim()
}

</script>
