<script lang="ts">
	import { onMount } from 'svelte';

	interface Project {
		id: string;
		name: string;
		isInbox?: boolean;
		isShared?: boolean;
	}

	interface Task {
		id: string;
		title: string;
		content?: string;
		projectId: string;
		_projectName: string;
		_projectId: string;
		dueDate?: string;
		startDate?: string;
		isAllDay?: boolean;
		priority: number;
		status: number;
		repeatFlag?: string;
	}

	type TabType = 'today' | 'all' | 'completed' | 'project';

	let loading = $state(true);
	let activeTab = $state<TabType>('today');
	let tasks = $state<Task[]>([]);
	let todayTasks = $state<Task[]>([]);
	let overdueTasks = $state<Task[]>([]);
	let projects = $state<Project[]>([]);
	let selectedProjectId = $state('');
	let completing = $state<Set<string>>(new Set());
	let deleting = $state<Set<string>>(new Set());

	// Add task form
	let showAdd = $state(false);
	let newTitle = $state('');
	let newProjectId = $state('');
	let newDueDate = $state('');
	let newDueTime = $state('');
	let newAllDay = $state(true);
	let newPriority = $state(0);
	let newRepeat = $state('');
	let saving = $state(false);

	// Edit
	let editingTask = $state<Task | null>(null);
	let editTitle = $state('');
	let editDueDate = $state('');
	let editDueTime = $state('');
	let editAllDay = $state(true);
	let editPriority = $state(0);
	let editRepeat = $state('');
	let editProjectId = $state('');

	// New project
	let showNewProject = $state(false);
	let newProjectName = $state('');

	async function api(path: string, opts: RequestInit = {}) {
		const res = await fetch(`/api/tasks${path}`, { credentials: 'include', ...opts });
		if (!res.ok) throw new Error(`${res.status}`);
		return res.json();
	}

	function formatDate(task: Task): string {
		const d = task.startDate || task.dueDate;
		if (!d) return 'No date';
		try {
			const date = new Date(d);
			const now = new Date();
			const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
			const taskDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
			const diff = Math.round((taskDate.getTime() - today.getTime()) / 86400000);

			let dateStr = '';
			if (diff === 0) dateStr = 'Today';
			else if (diff === 1) dateStr = 'Tomorrow';
			else if (diff === -1) dateStr = 'Yesterday';
			else if (diff < -1) dateStr = `${Math.abs(diff)}d ago`;
			else dateStr = date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });

			if (!task.isAllDay) {
				const h = date.getHours();
				const m = date.getMinutes();
				if (h !== 0 || m !== 0) {
					const ampm = h >= 12 ? 'PM' : 'AM';
					const hour = h % 12 || 12;
					const timeStr = m > 0 ? `${hour}:${String(m).padStart(2, '0')} ${ampm}` : `${hour} ${ampm}`;
					return `${dateStr} · ${timeStr}`;
				}
			}
			return dateStr;
		} catch { return ''; }
	}

	function isOverdue(task: Task): boolean {
		const d = task.startDate || task.dueDate;
		if (!d) return false;
		const taskDate = new Date(d);
		const now = new Date();
		return taskDate < new Date(now.getFullYear(), now.getMonth(), now.getDate()) && task.status === 0;
	}

	function priorityLabel(p: number): string {
		if (p >= 5) return 'high';
		if (p >= 3) return 'medium';
		if (p >= 1) return 'low';
		return '';
	}

	function repeatLabel(flag: string): string {
		if (!flag) return '';
		if (flag.includes('DAILY')) return 'Daily';
		if (flag.includes('WEEKLY')) {
			const m = flag.match(/BYDAY=([A-Z,]+)/);
			if (m) return `Weekly (${m[1]})`;
			return 'Weekly';
		}
		if (flag.includes('MONTHLY')) return 'Monthly';
		if (flag.includes('YEARLY')) return 'Yearly';
		return 'Repeating';
	}

	async function loadProjects() {
		try {
			const data = await api('/projects');
			projects = data.projects || [];
			if (projects.length > 0 && !newProjectId) {
				newProjectId = projects[0].id;
			}
		} catch { /* silent */ }
	}

	async function loadToday() {
		try {
			const data = await api('/today');
			todayTasks = data.today || [];
			overdueTasks = data.overdue || [];
		} catch { /* silent */ }
	}

	async function loadAll() {
		try {
			const data = await api('/tasks');
			tasks = (data.tasks || []).filter((t: Task) => t.status === 0);
		} catch { /* silent */ }
	}

	async function loadCompleted() {
		try {
			const data = await api('/tasks/completed');
			tasks = data.tasks || [];
		} catch { /* silent */ }
	}

	async function loadProject(projectId: string) {
		try {
			const data = await api(`/tasks?project_id=${projectId}`);
			tasks = (data.tasks || []).filter((t: Task) => t.status === 0);
		} catch { /* silent */ }
	}

	async function loadData() {
		loading = true;
		if (activeTab === 'today') await loadToday();
		else if (activeTab === 'all') await loadAll();
		else if (activeTab === 'completed') await loadCompleted();
		else if (activeTab === 'project' && selectedProjectId) await loadProject(selectedProjectId);
		loading = false;
	}

	async function addTask() {
		if (!newTitle.trim() || !newProjectId) return;
		saving = true;
		try {
			const payload: any = {
				title: newTitle.trim(),
				projectId: newProjectId,
				isAllDay: newAllDay,
				priority: newPriority,
			};
			if (newDueDate) {
				if (newAllDay) {
					payload.dueDate = `${newDueDate}T00:00:00+0000`;
				} else {
					payload.startDate = `${newDueDate}T${newDueTime || '09:00'}:00+0000`;
					payload.dueDate = `${newDueDate}T${newDueTime || '09:00'}:00+0000`;
				}
			}
			if (newRepeat) payload.repeatFlag = newRepeat;
			await api('/tasks', {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify(payload)
			});
			newTitle = '';
			newDueDate = '';
			newDueTime = '';
			newPriority = 0;
			newRepeat = '';
			showAdd = false;
			await loadData();
		} catch (e) { console.error('Failed to add task', e); }
		saving = false;
	}

	async function completeTask(task: Task) {
		completing = new Set([...completing, task.id]);
		try {
			await api(`/tasks/${task.id}/complete`, {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ projectId: task.projectId || task._projectId })
			});
			setTimeout(loadData, 400);
		} catch {
			completing = new Set([...completing].filter(id => id !== task.id));
		}
	}

	async function deleteTask(task: Task) {
		if (!confirm(`Delete "${task.title}"?`)) return;
		deleting = new Set([...deleting, task.id]);
		try {
			await api(`/tasks/${task.id}?projectId=${task.projectId || task._projectId}`, {
				method: 'DELETE',
			});
			setTimeout(loadData, 300);
		} catch {
			deleting = new Set([...deleting].filter(id => id !== task.id));
		}
	}

	function startEdit(task: Task) {
		editingTask = task;
		editTitle = task.title;
		editAllDay = task.isAllDay ?? true;
		editPriority = task.priority || 0;
		editRepeat = task.repeatFlag || '';
		editProjectId = task.projectId || task._projectId;
		const d = task.startDate || task.dueDate || '';
		if (d) {
			try {
				const date = new Date(d);
				editDueDate = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
				editDueTime = `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
			} catch { editDueDate = ''; editDueTime = ''; }
		} else {
			editDueDate = '';
			editDueTime = '';
		}
	}

	async function saveEdit() {
		if (!editingTask || !editTitle.trim()) return;
		saving = true;
		try {
			const payload: any = {
				title: editTitle.trim(),
				projectId: editProjectId,
				isAllDay: editAllDay,
				priority: editPriority,
				repeatFlag: editRepeat || null,
			};
			if (editDueDate) {
				if (editAllDay) {
					payload.dueDate = `${editDueDate}T00:00:00+0000`;
					payload.startDate = `${editDueDate}T00:00:00+0000`;
				} else {
					payload.startDate = `${editDueDate}T${editDueTime || '09:00'}:00+0000`;
					payload.dueDate = `${editDueDate}T${editDueTime || '09:00'}:00+0000`;
				}
			} else {
				payload.dueDate = null;
				payload.startDate = null;
			}
			await api(`/tasks/${editingTask.id}`, {
				method: 'PATCH',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify(payload)
			});
			editingTask = null;
			await loadData();
		} catch (e) { console.error('Failed to update task', e); }
		saving = false;
	}

	async function createProject() {
		if (!newProjectName.trim()) return;
		try {
			await api('/projects', {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ name: newProjectName.trim() })
			});
			newProjectName = '';
			showNewProject = false;
			await loadProjects();
		} catch (e) { console.error('Failed to create project', e); }
	}

	function selectProject(projectId: string) {
		selectedProjectId = projectId;
		activeTab = 'project';
		loadData();
	}

	onMount(async () => {
		await loadProjects();
		await loadData();
	});
</script>

<div class="page">
	<div class="page-header">
		<h1 class="page-title">Tasks</h1>
		<div class="header-actions">
			<button class="btn-secondary" onclick={() => { showNewProject = !showNewProject; }}>
				{showNewProject ? 'Cancel' : '+ List'}
			</button>
			<button class="btn-primary" onclick={() => { showAdd = !showAdd; }}>
				{showAdd ? 'Cancel' : '+ Add task'}
			</button>
		</div>
	</div>

	{#if showNewProject}
		<div class="module add-form">
			<div class="add-row">
				<input class="input" style="flex:1" placeholder="New list name" bind:value={newProjectName}
					onkeydown={(e) => e.key === 'Enter' && createProject()} />
				<button class="btn-primary" onclick={createProject} disabled={!newProjectName.trim()}>Create</button>
			</div>
		</div>
	{/if}

	{#if showAdd}
		<div class="module add-form">
			<input class="input" placeholder="What needs to be done?" bind:value={newTitle}
				onkeydown={(e) => e.key === 'Enter' && addTask()} />
			<div class="add-row">
				<select class="input add-select" bind:value={newProjectId}>
					{#each projects as proj}
						<option value={proj.id}>{proj.name}</option>
					{/each}
				</select>
				<input class="input add-date" type="date" bind:value={newDueDate} />
				{#if !newAllDay}
					<input class="input add-time" type="time" bind:value={newDueTime} />
				{/if}
			</div>
			<div class="add-row">
				<label class="add-toggle">
					<input type="checkbox" bind:checked={newAllDay} /> All day
				</label>
				<select class="input add-priority" bind:value={newPriority}>
					<option value={0}>No priority</option>
					<option value={1}>Low</option>
					<option value={3}>Medium</option>
					<option value={5}>High</option>
				</select>
				<select class="input add-repeat" bind:value={newRepeat}>
					<option value="">No repeat</option>
					<option value="FREQ=DAILY">Daily</option>
					<option value="FREQ=WEEKLY">Weekly</option>
					<option value="FREQ=WEEKLY;BYDAY=MO,WE,FR">Mon/Wed/Fri</option>
					<option value="FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR">Weekdays</option>
					<option value="FREQ=MONTHLY">Monthly</option>
					<option value="FREQ=YEARLY">Yearly</option>
				</select>
			</div>
			<button class="btn-primary full" onclick={addTask} disabled={saving || !newTitle.trim()}>
				{saving ? 'Adding...' : 'Add task'}
			</button>
		</div>
	{/if}

	<div class="tab-bar tasks-tabs">
		<button class="tab" class:active={activeTab === 'today'} onclick={() => { activeTab = 'today'; loadData(); }}>Today</button>
		<button class="tab" class:active={activeTab === 'all'} onclick={() => { activeTab = 'all'; loadData(); }}>All</button>
		{#each projects as proj}
			<button class="tab" class:active={activeTab === 'project' && selectedProjectId === proj.id} onclick={() => selectProject(proj.id)}>
				{proj.name}
			</button>
		{/each}
		<button class="tab" class:active={activeTab === 'completed'} onclick={() => { activeTab = 'completed'; loadData(); }}>Done</button>
	</div>

	{#if loading}
		<div class="module"><div class="skeleton" style="height: 200px"></div></div>
	{:else}

		{#if activeTab === 'today'}
			{#if overdueTasks.length > 0}
				<div class="section-label overdue-label">Overdue · {overdueTasks.length}</div>
				<div class="module flush">
					{#each overdueTasks as task (task.id)}
						<div class="data-row task-item" class:fading={completing.has(task.id) || deleting.has(task.id)}>
							<button class="task-check" onclick={() => completeTask(task)}>
								<svg width="22" height="22" viewBox="0 0 22 22" fill="none">
									<rect x="1.5" y="1.5" width="19" height="19" rx="4" stroke="var(--error)" stroke-width="2"/>
								</svg>
							</button>
							<div class="task-body" onclick={() => startEdit(task)}>
								<div class="task-name">{task.title}</div>
								<div class="task-sub">
									{formatDate(task)} · {task._projectName}
									{#if task.repeatFlag}<span class="badge muted">{repeatLabel(task.repeatFlag)}</span>{/if}
								</div>
							</div>
							<button class="btn-icon task-delete" onclick={() => deleteTask(task)} title="Delete">×</button>
						</div>
					{/each}
				</div>
			{/if}

			{#if todayTasks.length > 0}
				<div class="section-label">Today · {todayTasks.length}</div>
				<div class="module flush">
					{#each todayTasks as task (task.id)}
						<div class="data-row task-item" class:fading={completing.has(task.id) || deleting.has(task.id)}>
							<button class="task-check" onclick={() => completeTask(task)}>
								<svg width="22" height="22" viewBox="0 0 22 22" fill="none">
									<rect x="1.5" y="1.5" width="19" height="19" rx="4" stroke="var(--border-strong)" stroke-width="2"/>
								</svg>
							</button>
							<div class="task-body" onclick={() => startEdit(task)}>
								<div class="task-name">{task.title}</div>
								<div class="task-sub">
									{formatDate(task)} · {task._projectName}
									{#if task.repeatFlag}<span class="badge muted">{repeatLabel(task.repeatFlag)}</span>{/if}
								</div>
							</div>
							<button class="btn-icon task-delete" onclick={() => deleteTask(task)} title="Delete">×</button>
						</div>
					{/each}
				</div>
			{/if}

			{#if todayTasks.length === 0 && overdueTasks.length === 0}
				<div class="module">
					<div class="empty-state">All clear for today</div>
				</div>
			{/if}

		{:else if activeTab === 'completed'}
			{#if tasks.length > 0}
				<div class="module flush">
					{#each tasks as task (task.id)}
						<div class="data-row task-item completed-item">
							<svg width="22" height="22" viewBox="0 0 22 22" fill="none" style="flex-shrink:0">
								<rect x="1.5" y="1.5" width="19" height="19" rx="4" stroke="var(--success)" stroke-width="2" fill="var(--success-dim)"/>
								<polyline points="7,11 10,14 15,8" stroke="var(--success)" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
							</svg>
							<div class="task-body">
								<div class="task-name completed-name">{task.title}</div>
								<div class="task-sub">{task._projectName}{#if task.completedAt} · {new Date(task.completedAt).toLocaleDateString()}{/if}</div>
							</div>
						</div>
					{/each}
				</div>
			{:else}
				<div class="module"><div class="empty-state">No completed tasks</div></div>
			{/if}

		{:else}
			{#if tasks.length > 0}
				<div class="module flush">
					{#each tasks as task (task.id)}
						<div class="data-row task-item" class:fading={completing.has(task.id) || deleting.has(task.id)}>
							<button class="task-check" onclick={() => completeTask(task)}>
								<svg width="22" height="22" viewBox="0 0 22 22" fill="none">
									<rect x="1.5" y="1.5" width="19" height="19" rx="4" stroke="{isOverdue(task) ? 'var(--error)' : 'var(--border-strong)'}" stroke-width="2"/>
								</svg>
							</button>
							<div class="task-body" onclick={() => startEdit(task)}>
								<div class="task-name" class:overdue-text={isOverdue(task)}>{task.title}</div>
								<div class="task-sub">
									{formatDate(task)}
									{#if activeTab === 'all'} · {task._projectName}{/if}
									{#if task.repeatFlag}<span class="badge muted">{repeatLabel(task.repeatFlag)}</span>{/if}
									{#if priorityLabel(task.priority)}
										<span class="badge {priorityLabel(task.priority) === 'high' ? 'error' : priorityLabel(task.priority) === 'medium' ? 'warning' : 'muted'}">{priorityLabel(task.priority)}</span>
									{/if}
								</div>
							</div>
							<button class="btn-icon task-delete" onclick={() => deleteTask(task)} title="Delete">×</button>
						</div>
					{/each}
				</div>
			{:else}
				<div class="module">
					<div class="empty-state">No tasks</div>
				</div>
			{/if}
		{/if}
	{/if}
</div>

<!-- Edit modal -->
{#if editingTask}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="modal-overlay" onclick={(e) => { if (e.target === e.currentTarget) editingTask = null; }} onkeydown={() => {}}>
		<div class="modal">
			<div class="modal-header">
				<h3 class="modal-title">Edit task</h3>
				<button class="btn-icon" onclick={() => editingTask = null}>×</button>
			</div>
			<div class="modal-body">
				<input class="input" bind:value={editTitle} placeholder="Task title" />
				<select class="input" bind:value={editProjectId}>
					{#each projects as proj}
						<option value={proj.id}>{proj.name}</option>
					{/each}
				</select>
				<input class="input" type="date" bind:value={editDueDate} />
				<label class="add-toggle">
					<input type="checkbox" bind:checked={editAllDay} /> All day
				</label>
				{#if !editAllDay}
					<input class="input" type="time" bind:value={editDueTime} />
				{/if}
				<select class="input" bind:value={editPriority}>
					<option value={0}>No priority</option>
					<option value={1}>Low</option>
					<option value={3}>Medium</option>
					<option value={5}>High</option>
				</select>
				<select class="input" bind:value={editRepeat}>
					<option value="">No repeat</option>
					<option value="FREQ=DAILY">Daily</option>
					<option value="FREQ=WEEKLY">Weekly</option>
					<option value="FREQ=WEEKLY;BYDAY=MO,WE,FR">Mon/Wed/Fri</option>
					<option value="FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR">Weekdays</option>
					<option value="FREQ=MONTHLY">Monthly</option>
					<option value="FREQ=YEARLY">Yearly</option>
				</select>
			</div>
			<div class="modal-actions">
				<button class="btn-secondary" onclick={() => editingTask = null}>Cancel</button>
				<button class="btn-primary" onclick={saveEdit} disabled={saving}>{saving ? 'Saving...' : 'Save'}</button>
			</div>
		</div>
	</div>
{/if}

<style>
	/* ═══ Tasks page — Zinc/Emerald design ═══ */

	.page-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
	}

	.header-actions {
		display: flex;
		gap: 8px;
	}

	/* ── Tab bar ── */
	.tasks-tabs {
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		padding-bottom: 8px;
		margin-bottom: 12px;
		gap: 6px;
	}
	.tasks-tabs::-webkit-scrollbar { display: none; }
	.tasks-tabs > :global(.tab) {
		white-space: nowrap;
		flex-shrink: 0;
		padding: 4px 12px;
		font-size: 13px;
		font-weight: 500;
		color: var(--text-4);
		border: 1px solid var(--border);
		border-radius: 6px;
		transition: all 0.2s cubic-bezier(0.16,1,0.3,1);
	}
	.tasks-tabs > :global(.tab:hover) {
		color: var(--text-2);
		background: rgba(0,0,0,0.03);
	}
	.tasks-tabs > :global(.tab.active) {
		background: var(--accent);
		color: white;
		border-color: var(--accent);
		font-weight: 600;
	}

	/* ── Add form ── */
	.add-form {
		display: flex;
		flex-direction: column;
		gap: 12px;
		margin-bottom: 24px;
	}

	.add-row {
		display: flex;
		gap: 8px;
		flex-wrap: wrap;
		align-items: center;
	}

	.add-select { flex: 1; min-width: 120px; }
	.add-date { width: 160px; }
	.add-time { width: 120px; }
	.add-priority { width: 130px; }
	.add-repeat { width: 150px; }
	.add-toggle {
		font-size: 13px;
		color: var(--text-3);
		display: flex;
		align-items: center;
		gap: 4px;
		cursor: pointer;
	}

	/* ── Task rows ── */
	.task-item {
		display: flex;
		align-items: flex-start;
		gap: 12px;
		transition: opacity 0.3s;
	}

	.task-item.fading { opacity: 0.15; }

	.task-check {
		flex-shrink: 0;
		padding: 0;
		margin-top: 2px;
		background: none;
		border: none;
		cursor: pointer;
		opacity: 0.5;
		transition: opacity 0.15s;
	}
	.task-item:hover .task-check { opacity: 1; }

	.task-check:hover svg rect {
		stroke: var(--accent);
		fill: var(--accent-dim);
	}

	.task-body {
		flex: 1;
		min-width: 0;
		cursor: pointer;
	}

	.task-name {
		font-size: 14px;
		font-weight: 500;
		color: var(--text-1);
		line-height: 1.35;
	}

	.task-name.overdue-text { color: var(--error); }
	.task-name.completed-name {
		text-decoration: line-through;
		color: var(--text-4);
		font-weight: 400;
	}

	.completed-item { opacity: 0.6; }

	.task-sub {
		font-size: 12px;
		color: var(--text-4);
		margin-top: 2px;
		display: flex;
		align-items: center;
		gap: 6px;
		flex-wrap: wrap;
	}

	.task-delete {
		flex-shrink: 0;
		opacity: 0;
		transition: opacity 0.15s;
		color: var(--text-4);
		font-size: 16px;
	}

	.task-item:hover .task-delete { opacity: 1; }

	.overdue-label { color: var(--error) !important; }

	.empty-state {
		padding: 48px 16px;
		text-align: center;
		color: var(--text-4);
		font-size: 13px;
	}

	/* ── Modal ── */
	.modal-overlay {
		position: fixed;
		inset: 0;
		background: var(--overlay);
		display: flex;
		align-items: center;
		justify-content: center;
		z-index: 100;
	}

	.modal {
		background: var(--card);
		border-radius: 16px;
		box-shadow: var(--shadow-xl);
		width: 90%;
		max-width: 420px;
		overflow: hidden;
	}

	.modal-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 22px 24px 0;
	}

	.modal-title {
		font-size: 17px;
		font-weight: 700;
		color: var(--text-1);
		letter-spacing: -0.02em;
	}

	.modal-body {
		padding: 16px 24px;
		display: flex;
		flex-direction: column;
		gap: 12px;
	}

	.modal-actions {
		display: flex;
		gap: 8px;
		justify-content: flex-end;
		padding: 0 24px 22px;
	}
</style>
