import { defineStore } from 'pinia'
import type { TimeEntry } from '~/modules/time-tracking/services/dto/time-entry'
import type { Task } from '~/modules/project-management/services/dto/task'
import { useTimeEntryService } from '~/modules/time-tracking/services/time-entries'

export const useTimerStore = defineStore('timer', () => {
    const activeEntry = ref<TimeEntry | null>(null)
    const pendingCompleteEntry = ref<TimeEntry | null>(null)
    const now = ref(Date.now())
    let intervalId: ReturnType<typeof setInterval> | null = null

    const isRunning = computed(() => activeEntry.value !== null)

    const elapsed = computed(() => {
        if (!activeEntry.value) return 0
        const start = new Date(activeEntry.value.startedAt).getTime()
        return Math.floor((now.value - start) / 1000)
    })

    const elapsedFormatted = computed(() => {
        const total = elapsed.value
        const h = Math.floor(total / 3600)
        const m = Math.floor((total % 3600) / 60)
        const s = total % 60
        return [h, m, s].map((v) => String(v).padStart(2, '0')).join(':')
    })

    function startTicking() {
        stopTicking()
        now.value = Date.now()
        intervalId = setInterval(() => {
            now.value = Date.now()
        }, 1000)
    }

    function stopTicking() {
        if (intervalId) {
            clearInterval(intervalId)
            intervalId = null
        }
    }

    async function fetchActive() {
        const { getActive } = useTimeEntryService()
        activeEntry.value = await getActive()
        if (activeEntry.value) {
            startTicking()
        } else {
            stopTicking()
        }
    }

    async function start() {
        const authStore = useAuthStore()
        if (!authStore.user) return

        if (isRunning.value) {
            await stop()
        }

        const { create } = useTimeEntryService()
        activeEntry.value = await create({
            startedAt: new Date().toISOString(),
            user: `/api/users/${authStore.user.id}`,
        })
        startTicking()
    }

    function toIri<T extends { '@id'?: string; id: number }>(entity: T | string, prefix: string): string {
        if (typeof entity === 'string') return entity
        return entity['@id'] ?? `${prefix}/${entity.id}`
    }

    async function startFromTask(task: Task) {
        const authStore = useAuthStore()
        if (!authStore.user) return

        if (isRunning.value) {
            await stop()
        }

        const { create } = useTimeEntryService()
        activeEntry.value = await create({
            startedAt: new Date().toISOString(),
            user: `/api/users/${authStore.user.id}`,
            title: task.title,
            project: task.project ? toIri(task.project, '/api/projects') : null,
            task: toIri(task, '/api/tasks'),
            tags: task.tags?.map(t => toIri(t, '/api/task_tags')) ?? [],
        })
        startTicking()
    }

    async function stop() {
        if (!activeEntry.value) return

        const wasEmpty = !activeEntry.value.task

        const { update } = useTimeEntryService()
        const stoppedEntry = await update(activeEntry.value.id, {
            stoppedAt: new Date().toISOString(),
        })
        activeEntry.value = null
        stopTicking()

        if (wasEmpty) {
            pendingCompleteEntry.value = stoppedEntry
        }
    }

    function clearPendingEntry() {
        pendingCompleteEntry.value = null
    }

    return {
        activeEntry,
        pendingCompleteEntry,
        isRunning,
        elapsed,
        elapsedFormatted,
        fetchActive,
        start,
        startFromTask,
        stop,
        clearPendingEntry,
    }
})
