<template>
    <div class="relative overflow-auto rounded-lg border border-neutral-200 bg-white" style="max-height: calc(100vh - 220px);">
        <!-- Day headers -->
        <div class="sticky top-0 z-20 flex border-b border-neutral-200 bg-white">
            <div class="w-16 shrink-0 border-r border-neutral-200" />
            <div
                v-for="day in days"
                :key="day.dateStr"
                class="flex-1 border-r border-neutral-100 py-2 text-center"
            >
                <div class="text-lg font-bold" :class="isToday(day.date) ? 'text-orange-500' : 'text-neutral-900'">
                    {{ day.dayNum }}
                </div>
                <div class="text-xs" :class="isToday(day.date) ? 'text-orange-500' : 'text-neutral-500'">
                    {{ day.label }}
                </div>
                <div class="text-[10px] text-neutral-400">{{ day.totalFormatted }}</div>
            </div>
        </div>

        <!-- Grid body -->
        <div class="relative flex">
            <!-- Hour labels -->
            <div class="w-16 shrink-0">
                <div
                    v-for="hour in hours"
                    :key="hour"
                    class="flex items-start justify-end border-r border-neutral-200 pr-2 text-xs text-neutral-400"
                    :style="{ height: `${hourHeight}px` }"
                >
                    {{ String(hour).padStart(2, '0') }} : 00
                </div>
            </div>

            <!-- Day columns -->
            <div
                v-for="day in days"
                :key="day.dateStr"
                class="relative flex-1 border-r border-neutral-100"
                @dragover.prevent
                @drop="onDropOnDay($event, day)"
                @click="onClickGrid($event, day)"
                @contextmenu.prevent="onContextMenuGrid($event, day)"
            >
                <!-- Hour row lines -->
                <div
                    v-for="hour in hours"
                    :key="hour"
                    class="border-b border-neutral-100"
                    :style="{ height: `${hourHeight}px` }"
                />

                <!-- Time entry blocks -->
                <TimeEntryBlock
                    v-for="entry in entriesForDay(day.dateStr)"
                    :key="entry.id"
                    :entry="entry"
                    :hour-height="hourHeight"
                    :day-start-hour="0"
                    @click="emit('editEntry', $event)"
                    @contextmenu="(ev, ent) => emit('contextmenu', ev, ent)"
                    @resize="(ent, newStop) => emit('resizeEntry', ent, newStop)"
                />
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import type { TimeEntry } from '~/services/dto/time-entry'

const props = defineProps<{
    entries: TimeEntry[]
    startDate: Date
    viewMode: 'week' | 'day'
}>()

const emit = defineEmits<{
    (e: 'editEntry', entry: TimeEntry): void
    (e: 'createEntry', startedAt: string): void
    (e: 'moveEntry', entry: TimeEntry, newStartedAt: string, newStoppedAt: string): void
    (e: 'resizeEntry', entry: TimeEntry, newStoppedAt: string): void
    (e: 'contextmenu', event: MouseEvent, entry: TimeEntry | null): void
}>()

const hourHeight = 60
const hours = Array.from({ length: 24 }, (_, i) => i)

const dayLabels = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam']

const days = computed(() => {
    const count = props.viewMode === 'week' ? 7 : 1
    const result = []
    for (let i = 0; i < count; i++) {
        const d = new Date(props.startDate)
        d.setDate(d.getDate() + i)
        const dateStr = toDateStr(d)
        const dayEntries = props.entries.filter((e) => toDateStr(new Date(e.startedAt)) === dateStr)
        const totalMs = dayEntries.reduce((sum, e) => {
            if (!e.stoppedAt) return sum
            return sum + (new Date(e.stoppedAt).getTime() - new Date(e.startedAt).getTime())
        }, 0)
        const totalH = Math.floor(totalMs / 3600000)
        const totalM = Math.floor((totalMs % 3600000) / 60000)
        const totalS = Math.floor((totalMs % 60000) / 1000)

        result.push({
            date: new Date(d),
            dateStr,
            dayNum: d.getDate(),
            label: dayLabels[d.getDay()],
            totalFormatted: `${String(totalH).padStart(2, '0')}:${String(totalM).padStart(2, '0')}:${String(totalS).padStart(2, '0')}`,
        })
    }
    return result
})

function toDateStr(d: Date): string {
    return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
}

function isToday(d: Date): boolean {
    return toDateStr(d) === toDateStr(new Date())
}

function entriesForDay(dateStr: string): TimeEntry[] {
    return props.entries.filter((e) => toDateStr(new Date(e.startedAt)) === dateStr)
}

function getHourFromY(event: MouseEvent, dayEl: HTMLElement): number {
    const rect = dayEl.getBoundingClientRect()
    const y = event.clientY - rect.top
    const minutes = Math.round((y / hourHeight) * 60 / 15) * 15
    return minutes / 60
}

function onClickGrid(event: MouseEvent, day: { date: Date; dateStr: string }) {
    const target = event.currentTarget as HTMLElement
    const hourDecimal = getHourFromY(event, target)
    const h = Math.floor(hourDecimal)
    const m = Math.round((hourDecimal - h) * 60)
    const d = new Date(day.date)
    d.setHours(h, m, 0, 0)
    emit('createEntry', d.toISOString())
}

function onContextMenuGrid(event: MouseEvent, day: { date: Date; dateStr: string }) {
    emit('contextmenu', event, null)
}

function onDropOnDay(event: DragEvent, day: { date: Date; dateStr: string }) {
    const entryId = event.dataTransfer?.getData('application/time-entry-id')
    const startStr = event.dataTransfer?.getData('application/time-entry-start')
    const stopStr = event.dataTransfer?.getData('application/time-entry-stop')

    if (!entryId || !startStr) return

    const entry = props.entries.find((e) => e.id === Number(entryId))
    if (!entry) return

    const target = event.currentTarget as HTMLElement
    const hourDecimal = getHourFromY(event as unknown as MouseEvent, target)
    const h = Math.floor(hourDecimal)
    const m = Math.round((hourDecimal - h) * 60)

    const originalStart = new Date(startStr)
    const originalStop = stopStr ? new Date(stopStr) : null
    const durationMs = originalStop ? originalStop.getTime() - originalStart.getTime() : 3600000

    const newStart = new Date(day.date)
    newStart.setHours(h, m, 0, 0)
    const newStop = new Date(newStart.getTime() + durationMs)

    emit('moveEntry', entry, newStart.toISOString(), newStop.toISOString())
}
</script>
