<template>
    <section class="flex h-full min-h-0 flex-col overflow-hidden pt-8">
        <div class="grid grid-cols-4 rounded-md bg-tertiary-500 text-primary-500 text-[18px] border border-primary-500">
            <p class="col-start-1 p-[10px] border-b border-r border-primary-500"><strong class="uppercase font-semibold">Année acquis :</strong> {{
                    formatCount(summary?.acquiredDays)
                }} Jours
            </p>
            <p class="col-start-2 p-[10px] border-b border-r border-primary-500"><strong class="uppercase font-semibold">Pris :</strong>
                {{ formatCount(isForfaitRule ? currentYearTakenDays : summary?.takenDays) }} Jours
            </p>
            <p class="col-start-3 p-[10px] border-b border-r border-b-white border-r-primary-500 bg-primary-500 text-white"><strong class="uppercase font-semibold">Reste à prendre :</strong>
                {{ formatCount(summary?.remainingDays) }} Jours
            </p>
            <p class="col-start-4 p-[10px] border-b border-primary-500"><strong class="uppercase font-semibold">En cours d'acquisition :</strong>
                {{ isForfaitRule ? formatCount(summary?.accruingDays) : `${formatCount(summary?.accruingDays)} / ${formatCount(summary?.accruingDaysTotal)}` }}
            </p>
            <p v-if="!isForfaitRule" class="col-start-1 p-[10px] border-r border-primary-500"><span class="uppercase font-semibold">Samedi acquis :</span>
                {{ formatCount(summary?.acquiredSaturdays) }} Jours
            </p>
            <p v-else class="col-start-1 p-[10px] border-r border-primary-500"><span class="uppercase font-semibold">Année N-1 acquis :</span>
                {{ formatCount(summary?.previousYearAcquiredDays) }} Jours
            </p>
            <p v-if="!isForfaitRule" class="col-start-2 p-[10px] border-r border-primary-500"><span class="uppercase font-semibold">Pris :</span>
                {{ formatCount(summary?.takenSaturdays) }} Jours
            </p>
            <p v-if="!isForfaitRule" class="col-start-3 p-[10px] border-r border-r-primary-500 bg-primary-500 text-white"><span class="uppercase font-semibold">Reste à prendre :</span>
                {{ formatCount(summary?.remainingSaturdays) }} Jours
            </p>
            <p v-else class="col-start-2 p-[10px] border-r border-primary-500"><span class="uppercase font-semibold">Pris :</span>
                {{ formatCount(summary?.previousYearTakenDays) }} Jours
            </p>
            <p v-if="isForfaitRule" class="col-start-3 p-[10px] border-r-primary-500 bg-primary-500 text-white"><span class="uppercase font-semibold">Reste à prendre :</span>
                {{ formatCount(summary?.previousYearRemainingDays) }} Jours
            </p>
            <div v-if="isForfaitRule" class="col-start-4 p-[10px] flex gap-7 items-center">
                <div>
                    <span class="uppercase font-semibold">Année n-1 payés : </span>
                    <span> {{ formatCount(summary?.previousYearPaidDays) }} Jours</span>
                </div>
                <button
                    class="flex items-center"
                    :class="isHistoricalYear ? 'opacity-40 cursor-not-allowed' : ''"
                    :disabled="isHistoricalYear"
                    @click="openPaidLeaveDrawer"
                >
                    <Icon name="mdi:edit-box" size="24"/>
                </button>
            </div>
            <div v-if="!isForfaitRule" class="col-start-4 p-[10px] flex gap-7 items-center">
                <div>
                    <span class="uppercase font-semibold">Fractionné acquis : </span>
                    <span>{{ formatCount(summary?.fractionedDays) }} Jours</span>
                </div>
                <button
                    class="flex items-center"
                    :class="isHistoricalYear ? 'opacity-40 cursor-not-allowed' : ''"
                    :disabled="isHistoricalYear"
                    @click="openFractionedDrawer"
                >
                    <Icon name="mdi:edit-box" size="24"/>
                </button>
            </div>
        </div>
        <div class="mt-8 min-h-0 flex-1 overflow-y-auto pr-2">
            <div class="grid grid-cols-4 gap-10">
                <div v-for="month in months" :key="month.label"
                     class="rounded-md bg-tertiary-500 text-primary-500 flex flex-col justify-between">
                    <div class="flex justify-center rounded-t-md bg-primary-500 py-1 font-bold uppercase text-white">
                        {{ month.label }}
                    </div>
                    <div class="grid grid-cols-7 gap-1 px-2 py-2 text-center text-md font-bold">
                        <p v-for="weekday in weekDayLabels" :key="weekday">{{ weekday }}</p>
                    </div>
                    <div class="grid grid-cols-7 gap-4 px-2 pb-2 text-center text-md">
                        <template v-for="(day, index) in month.cells" :key="`${month.label}-${index}`">
                            <div v-if="!day" class="h-6"/>
                            <div
                                v-else
                                class="flex items-center justify-center"
                            >
                                <div
                                    class="h-6 w-6"
                                    :class="getDayClass(day)"
                                    :style="getDayStyle(day)"
                                    :title="getDayTitle(day)"
                                >
                                    {{ getDayText(day) }}
                                </div>
                            </div>
                        </template>
                    </div>
                    <div class="px-2 py-2 text-center border-t border-primary-500">Jours de présence :
                        {{ summary?.presenceDaysByMonth?.[month.monthKey] ?? 0 }}
                    </div>
                </div>
            </div>
            <div class="mt-6 flex items-center gap-3">
                <label for="leave-year-select" class="text-md font-semibold text-primary-500 uppercase">
                    {{ isForfaitRule ? 'Année :' : 'Exercice :' }}
                </label>
                <select
                    id="leave-year-select"
                    :value="selectedYear ?? ''"
                    :disabled="!availableYears.length"
                    class="border border-primary-500 rounded-md px-3 py-1 text-md font-semibold text-primary-500 bg-white focus:outline-none focus:ring-2 focus:ring-secondary-500/20 disabled:opacity-50"
                    @change="handleYearChange"
                >
                    <option v-for="option in availableYears" :key="option.value" :value="option.value">
                        {{ option.label }}
                    </option>
                </select>
            </div>
        </div>
        <MalioDrawer v-model="isFractionedDrawerOpen">
            <template #header>
                <h2 class="text-[32px] font-semibold text-primary-500">Jours fractionnés</h2>
            </template>
            <form class="space-y-4" @submit.prevent="handleSubmitFractioned">
                <div>
                    <label class="text-md font-semibold text-neutral-700" for="fractioned-days">
                        Nombre de jours <span class="text-red-600">*</span>
                    </label>
                    <input
                        id="fractioned-days"
                        v-model="fractionedForm.days"
                        type="number"
                        step="0.5"
                        min="0"
                        class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-md text-neutral-900 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-secondary-500/20"
                    />
                </div>

                <div class="grid grid-cols-2 gap-3 pt-2">
                    <MalioButton
                        label="Annuler"
                        variant="tertiary"
                        button-class="w-full"
                        @click="isFractionedDrawerOpen = false"
                    />
                    <MalioButton
                        label="Enregistrer"
                        button-class="w-full"
                        @click="handleSubmitFractioned"
                    />
                </div>
            </form>
        </MalioDrawer>
        <MalioDrawer v-model="isPaidLeaveDrawerOpen">
            <template #header>
                <h2 class="text-[32px] font-semibold text-primary-500">Congés N-1 payés</h2>
            </template>
            <form class="space-y-4" @submit.prevent="handleSubmitPaidLeave">
                <div>
                    <label class="text-md font-semibold text-neutral-700" for="paid-leave-days">
                        Nombre de jours <span class="text-red-600">*</span>
                    </label>
                    <input
                        id="paid-leave-days"
                        v-model="paidLeaveForm.days"
                        type="number"
                        step="0.5"
                        min="0"
                        class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-md text-neutral-900 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-secondary-500/20"
                    />
                </div>

                <div class="grid grid-cols-2 gap-3 pt-2">
                    <MalioButton
                        label="Annuler"
                        variant="tertiary"
                        button-class="w-full"
                        @click="isPaidLeaveDrawerOpen = false"
                    />
                    <MalioButton
                        label="Enregistrer"
                        button-class="w-full"
                        @click="handleSubmitPaidLeave"
                    />
                </div>
            </form>
        </MalioDrawer>
    </section>
</template>

<script setup lang="ts">
import type {Absence} from '~/services/dto/absence'
import type {EmployeeLeaveSummary} from '~/services/dto/employee-leave-summary'
import {normalizeDate, toYmd} from '~/utils/date'

type DayLeaveState = {
    am: boolean
    pm: boolean
    labels: string[]
    colors: string[]
}

type LeaveYearOption = {
    value: number
    label: string
}

const props = defineProps<{
    absences: Absence[]
    summary: EmployeeLeaveSummary | null
    publicHolidays: Record<string, string>
    selectedYear: number | null
    availableYears: LeaveYearOption[]
    currentYear: number | null
}>()

const emit = defineEmits<{
    (event: 'update-fractioned-days', days: number): void
    (event: 'update-paid-leave-days', days: number): void
    (event: 'update-selected-year', year: number): void
}>()

const isHistoricalYear = computed(() =>
    props.selectedYear !== null
    && props.currentYear !== null
    && props.selectedYear !== props.currentYear
)

const handleYearChange = (event: Event) => {
    const target = event.target as HTMLSelectElement
    const value = Number(target.value)
    if (Number.isNaN(value)) return
    emit('update-selected-year', value)
}

const isFractionedDrawerOpen = ref(false)
const fractionedForm = reactive({days: 0})

const isPaidLeaveDrawerOpen = ref(false)
const paidLeaveForm = reactive({days: 0})

const openFractionedDrawer = () => {
    fractionedForm.days = props.summary?.fractionedDays ?? 0
    isFractionedDrawerOpen.value = true
}

const handleSubmitFractioned = () => {
    const value = Number(fractionedForm.days)
    if (Number.isNaN(value) || value < 0) return
    emit('update-fractioned-days', value)
    isFractionedDrawerOpen.value = false
}

const openPaidLeaveDrawer = () => {
    paidLeaveForm.days = props.summary?.previousYearPaidDays ?? 0
    isPaidLeaveDrawerOpen.value = true
}

const handleSubmitPaidLeave = () => {
    const value = Number(paidLeaveForm.days)
    if (Number.isNaN(value) || value < 0) return
    emit('update-paid-leave-days', value)
    isPaidLeaveDrawerOpen.value = false
}

const monthLabels = [
    'Janvier',
    'Fevrier',
    'Mars',
    'Avril',
    'Mai',
    'Juin',
    'Juillet',
    'Aout',
    'Septembre',
    'Octobre',
    'Novembre',
    'Decembre'
] as const

const weekDayLabels = ['L', 'M', 'M', 'J', 'V', 'S', 'D'] as const

const isForfaitRule = computed(() => props.summary?.ruleCode === 'FORFAIT_218')

const currentYearTakenDays = computed(() => {
    if (!props.summary) return null
    return props.summary.takenDays - (props.summary.previousYearTakenDays ?? 0)
})

const displayedYear = computed(() => {
    if (props.selectedYear) return props.selectedYear
    if (props.summary?.year) return props.summary.year
    const today = new Date()
    const year = today.getFullYear()
    const month = today.getMonth() + 1
    return month >= 6 ? year + 1 : year
})

const orderedMonthIndexes = computed(() => {
    if (isForfaitRule.value) return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    return [5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4]
})

const buildDateFromYmd = (value: string) => new Date(`${value}T00:00:00`)

const dayLeaveMap = computed(() => {
    const map = new Map<string, DayLeaveState>()

    for (const absence of props.absences) {
        const startYmd = normalizeDate(absence.startDate)
        const endYmd = normalizeDate(absence.endDate)
        const start = buildDateFromYmd(startYmd)
        const end = buildDateFromYmd(endYmd)
        if (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime())) continue

        for (const cursor = new Date(start); cursor <= end; cursor.setDate(cursor.getDate() + 1)) {
            const ymd = toYmd(cursor.getFullYear(), cursor.getMonth(), cursor.getDate())
            const existing = map.get(ymd) ?? {
                am: false,
                pm: false,
                labels: [] as string[],
                colors: [] as string[]
            }

            const isStart = ymd === startYmd
            const isEnd = ymd === endYmd
            const isSingleDay = startYmd === endYmd

            let am = false
            let pm = false

            if (isSingleDay) {
                am = absence.startHalf === 'AM'
                pm = absence.endHalf === 'PM'
            } else if (isStart) {
                am = absence.startHalf === 'AM'
                pm = true
            } else if (isEnd) {
                am = true
                pm = absence.endHalf === 'PM'
            } else {
                am = true
                pm = true
            }

            const typeLabel = absence.type?.label ?? absence.type?.code ?? 'Absence'
            const typeColor = absence.type?.color ?? '#222783'
            const halfSuffix = am && !pm ? ' (Matin)' : (!am && pm ? ' (Apres-midi)' : '')
            const hoverLabel = `${typeLabel}${halfSuffix}`

            const colors = existing.colors.includes(typeColor)
                ? existing.colors
                : [...existing.colors, typeColor]

            map.set(ymd, {
                am: existing.am || am,
                pm: existing.pm || pm,
                labels: existing.labels.includes(hoverLabel)
                    ? existing.labels
                    : [...existing.labels, hoverLabel],
                colors
            })
        }
    }

    return map
})

const months = computed(() => {
    return orderedMonthIndexes.value.map((monthIndex) => {
        const label = monthLabels[monthIndex]
        const monthYear = isForfaitRule.value
            ? displayedYear.value
            : (monthIndex >= 5 ? displayedYear.value - 1 : displayedYear.value)

        const first = new Date(monthYear, monthIndex, 1)
        const daysInMonth = new Date(monthYear, monthIndex + 1, 0).getDate()
        const mondayBasedFirstDay = (first.getDay() + 6) % 7

        const cells: Array<{ ymd: string; label: string; leave: DayLeaveState | null; isHoliday: boolean } | null> = []

        for (let i = 0; i < mondayBasedFirstDay; i += 1) {
            cells.push(null)
        }

        for (let day = 1; day <= daysInMonth; day += 1) {
            const ymd = toYmd(monthYear, monthIndex, day)
            cells.push({
                ymd,
                label: String(day),
                leave: dayLeaveMap.value.get(ymd) ?? null,
                isHoliday: ymd in props.publicHolidays
            })
        }

        while (cells.length % 7 !== 0) {
            cells.push(null)
        }

        const monthKey = `${monthYear}-${String(monthIndex + 1).padStart(2, '0')}`

        return {
            label,
            cells,
            monthKey
        }
    })
})

const getDayClass = (day: { leave: DayLeaveState | null; isHoliday: boolean }) => {
    if (day.leave) {
        return 'rounded font-semibold text-white'
    }
    if (day.isHoliday) return 'text-primary-500 rounded font-semibold'
    return 'text-primary-500'
}

const getDayStyle = (day: { leave: DayLeaveState | null; isHoliday: boolean }) => {
    if (day.leave) {
        const color = day.leave.colors[0] ?? '#222783'
        if (day.leave.am && day.leave.pm) {
            return {backgroundColor: color}
        }
        const colorFaded = `${color}60`
        const backgroundImage = day.leave.am
            ? `linear-gradient(180deg, ${color} 0 50%, ${colorFaded} 50% 100%)`
            : `linear-gradient(180deg, ${colorFaded} 0 50%, ${color} 50% 100%)`
        return {backgroundImage, backgroundColor: 'transparent'}
    }
    if (day.isHoliday) return {backgroundColor: 'rgb(179, 229, 252)'}
    return undefined
}

const getDayText = (day: { label: string; leave: DayLeaveState | null }) => {
    return day.label
}

const getDayTitle = (day: { leave: DayLeaveState | null; isHoliday: boolean; ymd: string }) => {
    if (day.leave && day.leave.labels.length > 0) return day.leave.labels.join(' / ')
    if (day.isHoliday) return props.publicHolidays[day.ymd] ?? 'Jour férié'
    return ''
}

const formatCount = (value: number | null | undefined) => {
    if (value === null || value === undefined) return '-'
    const rounded = Math.round(value * 100) / 100
    if (Number.isInteger(rounded)) return String(rounded)
    return rounded.toFixed(2).replace('.', ',')
}
</script>
