<template>
    <div
        ref="blockEl"
        class="absolute left-1 right-1 cursor-pointer overflow-hidden rounded-md px-2 py-1 text-xs text-white shadow-sm select-none"
        :style="blockStyle"
        draggable="true"
        @click.stop="emit('click', entry)"
        @contextmenu.prevent="emit('contextmenu', $event, entry)"
        @dragstart="onDragStart"
        @dragend="onDragEnd"
    >
        <div class="font-semibold truncate">{{ entry.title || 'Sans titre' }}</div>
        <div v-if="entry.project" class="truncate text-[10px] opacity-80">{{ entry.project.name }}</div>
        <div class="mt-0.5 flex items-center gap-1">
            <span
                v-for="type in entry.types"
                :key="type.id"
                class="rounded-full px-1.5 py-0.5 text-[9px] font-semibold"
                :style="{ backgroundColor: type.color }"
            >
                {{ type.label }}
            </span>
            <span class="ml-auto text-[10px] opacity-80">{{ duration }}</span>
        </div>

        <!-- Resize handle -->
        <div
            class="absolute bottom-0 left-0 right-0 h-2 cursor-s-resize"
            @mousedown.stop.prevent="onResizeStart"
        />
    </div>
</template>

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

const props = defineProps<{
    entry: TimeEntry
    hourHeight: number
    dayStartHour: number
}>()

const emit = defineEmits<{
    (e: 'click', entry: TimeEntry): void
    (e: 'contextmenu', event: MouseEvent, entry: TimeEntry): void
    (e: 'resize', entry: TimeEntry, newStoppedAt: string): void
    (e: 'move', entry: TimeEntry, newStartedAt: string, newStoppedAt: string): void
}>()

const blockEl = ref<HTMLElement | null>(null)

const startDate = computed(() => new Date(props.entry.startedAt))
const endDate = computed(() => props.entry.stoppedAt ? new Date(props.entry.stoppedAt) : new Date())

const duration = computed(() => {
    const diff = endDate.value.getTime() - startDate.value.getTime()
    const h = Math.floor(diff / 3600000)
    const m = Math.floor((diff % 3600000) / 60000)
    const s = Math.floor((diff % 60000) / 1000)
    return [h, m, s].map((v) => String(v).padStart(2, '0')).join(' : ')
})

const blockStyle = computed(() => {
    const startMinutes = startDate.value.getHours() * 60 + startDate.value.getMinutes()
    const endMinutes = endDate.value.getHours() * 60 + endDate.value.getMinutes()
    const topPx = ((startMinutes - props.dayStartHour * 60) / 60) * props.hourHeight
    const heightPx = Math.max(((endMinutes - startMinutes) / 60) * props.hourHeight, 20)
    const bgColor = props.entry.project?.color ?? '#94a3b8'

    return {
        top: `${topPx}px`,
        height: `${heightPx}px`,
        backgroundColor: bgColor,
    }
})

function onDragStart(event: DragEvent) {
    event.dataTransfer!.effectAllowed = 'move'
    event.dataTransfer!.setData('application/time-entry-id', String(props.entry.id))
    event.dataTransfer!.setData('application/time-entry-start', props.entry.startedAt)
    event.dataTransfer!.setData('application/time-entry-stop', props.entry.stoppedAt ?? '')
    ;(event.target as HTMLElement).classList.add('opacity-50')
}

function onDragEnd(event: DragEvent) {
    ;(event.target as HTMLElement).classList.remove('opacity-50')
}

function onResizeStart(event: MouseEvent) {
    const startY = event.clientY
    const originalHeight = blockEl.value?.offsetHeight ?? 0

    function onMouseMove(e: MouseEvent) {
        const delta = e.clientY - startY
        const newHeight = Math.max(originalHeight + delta, 20)
        if (blockEl.value) {
            blockEl.value.style.height = `${newHeight}px`
        }
    }

    function onMouseUp(e: MouseEvent) {
        document.removeEventListener('mousemove', onMouseMove)
        document.removeEventListener('mouseup', onMouseUp)

        const delta = e.clientY - startY
        const deltaMinutes = Math.round((delta / props.hourHeight) * 60 / 15) * 15
        const originalEnd = endDate.value
        const newEnd = new Date(originalEnd.getTime() + deltaMinutes * 60000)
        emit('resize', props.entry, newEnd.toISOString())
    }

    document.addEventListener('mousemove', onMouseMove)
    document.addEventListener('mouseup', onMouseUp)
}
</script>
