import { Todo, User, UserWithTodos } from '@homeman/models.ts'
import { Signal, useSignal } from '@preact/signals'
import { TodoList } from '@homeman/islands/TodoList.tsx'
import { Dialog } from '@homeman/components/Dialog.tsx'
import { Label } from '@homeman/components/Label.tsx'
import { Input } from '@homeman/components/Input.tsx'
import { Avatar } from '@homeman/components/Avatar.tsx'
import { Button } from '@homeman/components/Button.tsx'
import { JSX } from 'preact'
import { useEffect } from 'preact/hooks'
import { excitement } from '@homeman/common.ts'

interface Props {
	users: Record<string, UserWithTodos>
	todos: Record<string, Todo>
	unassignedTodos: Todo[]
	lastUserIdUpdated: { value: string; versionstamp: string }
	lastTodoIdUpdated: { value: string; versionstamp: string }
}

const unassignedUserPlaceholder: User = {
	id: '',
	createdAt: new Date(),
	name: 'Shared',
	avatarUrl: 'http://placekitten.com/512/512',
	color: '888888',
}

interface UserSelectButtonProps extends JSX.HTMLAttributes<HTMLInputElement> {
	user: User
}

function UserSelectButton(
	{ user: { id, name, avatarUrl, color }, tabindex, ...props }:
		UserSelectButtonProps,
) {
	const eid = `assigneeUserId_${id}`
	return (
		<>
			<input
				aria-hidden='true'
				type='radio'
				class='peer sr-only'
				id={eid}
				name='assigneeUserId'
				value={id}
				{...props}
			/>
			<Label
				for={eid}
				style={`border-color: #${color};`}
				tabindex={tabindex}
				className='cursor-pointer peer-checked:border-t-2 peer-checked:bg-gray-500/20 hover:bg-gray-500/25 rounded p-2'
				role='button'
			>
				<Avatar
					className='mb-2'
					src={avatarUrl}
				/>
				<span
					style={`color: #${color};`}
					class='font-semibold text-center'
				>
					{name}
				</span>
			</Label>
		</>
	)
}

export default function Dashboard(
	props: Props,
) {
	const todoAssignUserId: Signal<string | null> = useSignal(null)
	const showAddTodoDialog = useSignal(false)

	const data = useSignal(props)

	const {
		// todos,
		users,
		unassignedTodos,
		// lastTodoIdUpdated,
		// lastUserIdUpdated,
	} = data.value

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

	useEffect(() => {
		let es = new EventSource('/api/user')

		es.addEventListener('message', async (e) => {
			console.log('user event stream message:', e)
			await reload()
			excitement()
		})

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

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

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

		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/todo')
		})
	}, [])

	const unassignedUser: UserWithTodos = {
		...unassignedUserPlaceholder,
		assignedTodos: unassignedTodos,
	}

	return (
		<main class='flex flex-col'>
			<Dialog
				headerTitle='Add todo'
				show={showAddTodoDialog.value}
				onClose={() => showAddTodoDialog.value = false}
			>
				<form
					class='p-4 gap-4 flex flex-col'
					action='/api/todo'
					method='post'
					encType='multipart/form-data'
				>
					<Label for='description'>
						Description
						<Input autofocus name='description' />
					</Label>
					<span>
						Assignee
						<ul class='flex gap-2'>
							<li>
								<UserSelectButton
									checked={todoAssignUserId.value == null}
									tabindex={0}
									user={unassignedUser}
								/>
							</li>
							{Object.values(users).map(
								(user) => {
									return (
										<li>
											<UserSelectButton
												checked={todoAssignUserId.value == user.id}
												user={user}
											/>
										</li>
									)
								},
							)}
						</ul>
					</span>
					<footer class='flex justify-end gap-2'>
						<Button
							type='button'
							onClick={() => showAddTodoDialog.value = false}
						>
							Cancel
						</Button>
						<Input type='submit' value='Save' />
					</footer>
				</form>
			</Dialog>
			<h1 class='p-5 border-b-2 border-stone-500/20 text-2xl'>
				Todos
			</h1>
			<ul class='p-4 relative flex overflow-x-scroll max-w-screen'>
				<li>
					<TodoList
						onNewButtonClicked={() => {
							console.log('shared new')
							showAddTodoDialog.value = true
							todoAssignUserId.value = null
						}}
						user={unassignedUser}
					/>
				</li>
				{Object.values(users).map((u) => (
					<li>
						<TodoList
							onNewButtonClicked={() => {
								showAddTodoDialog.value = true
								todoAssignUserId.value = u.id
							}}
							user={u}
						/>
					</li>
				))}
			</ul>
		</main>
	)
}
