import { DailyPhase, DailyPhaseModel, Task, toPhase } from '@homeman/models.ts'
import { signal, useSignal } from '@preact/signals'
import { excitement } from '@homeman/common.ts'
import { IS_BROWSER } from '$fresh/runtime.ts'
import { useEffect } from 'preact/hooks'

export interface Props {
	tasks: Task[]
}

interface TaskWithIndex extends Task {
	index: number
}

const phaseEmoji: Record<DailyPhase, string> = {
	Morning: '🌄',
	Midday: '🌞',
	Evening: '🌆',
	Bedtime: '🛌',
	Night: '🌙',
}

type TaskGroups = Record<DailyPhase, TaskWithIndex[]>
let lastPhaseSelection = new Date()

export function Routine(
	props: Props,
) {
	const tasks = useSignal(props.tasks)
	const currentPhase = useSignal(toPhase())

	const reload = async () => {
		console.log('reloading...')
		const newData = await (await fetch(location.href, {
			headers: { accept: 'application/json' },
		})).json()
		tasks.value = newData
		console.log('new tasks:', newData)
	}

	useEffect(() => {
		let es = new EventSource('/api/tasks')
		console.log('Streaming task events...')

		es.addEventListener('message', (e) => {
			console.log('task event from server:', e)
			reload()
		})

		es.addEventListener('error', async (e) => {
			// try and reconnect
			console.log('Streaming todo events error:', e)
			es.close()
			const backoff = 10000 + Math.random() * 5000
			await new Promise((resolve) => setTimeout(resolve, backoff))
			es = new EventSource('/api/tasks')
		})
	}, [])

	useEffect(() => {
		if (IS_BROWSER) {
			setInterval(() => {
				const delta = (new Date()).getTime() - lastPhaseSelection.getTime()
				const nowPhase = toPhase()
				if (nowPhase != currentPhase.value && delta >= 1000 * 60 * 10) {
					currentPhase.value = nowPhase
					lastPhaseSelection = new Date()
				}
			}, 5_000)
		}
	}, [])

	const taskGroups: TaskGroups = {
		Morning: [],
		Midday: [],
		Evening: [],
		Bedtime: [],
		Night: [],
	}
	tasks.value.forEach((t, i) => taskGroups[t.phase].push({ ...t, index: i }))
	return (
		<>
			<nav class='flex overflow-x-scroll'>
				{DailyPhaseModel.options.map((phase) => (
					<button
						onClick={() => {
							currentPhase.value = phase
							lastPhaseSelection = new Date()
						}}
						class={`p-4 shrink-0 grow border-b-2 text-lg ${
							currentPhase.value == phase
								? 'border-purple-500'
								: 'border-gray-500/20 hover:border-gray-500'
						}`}
					>
						{phaseEmoji[phase]} {phase}
					</button>
				))}
			</nav>
			<main class='flex flex-col overflow-x-scroll'>
				<ul>
					{taskGroups[currentPhase.value].map((
						task: TaskWithIndex,
					) => {
						const { emoji, description, doneAt, index } = task
						return (
							<li
								role='button'
								class={`text-lg cursor-pointer p-4 hover:bg-gray-500/20 ${
									doneAt ? 'line-through opacity-30 hover:bg-gray-500' : ''
								}`}
								onClick={async () => {
									tasks.value[index].doneAt = tasks.value[index].doneAt
										? null
										: new Date()
									tasks.value = [...tasks.value]
									if (tasks.value[index].doneAt) {
										excitement()
									}
									await (await fetch('/api/tasks', {
										method: 'PUT',
										body: JSON.stringify({
											...task,
											done: !!tasks.value[index].doneAt,
										}),
									})).json()
								}}
							>
								{emoji ? `${emoji.trim()} ` : ''}
								{description.trim()}
							</li>
						)
					})}
				</ul>
			</main>
		</>
	)
}
