<script lang="ts">
	import { onMount, onDestroy } from 'svelte';
	import { page } from '$app/stores';
	import { goto } from '$app/navigation';
	import { currentUser } from '$lib/stores/auth';
	import {
		loadNote,
		patchNote,
		pinNote,
		unpinNote,
		archiveNote,
		unarchiveNote,
		trashNote,
		restoreNote,
		duplicateNote,
		NOTE_COLORS
	} from '$lib/stores/notes';
	import type { Note, NoteColor } from '@colectivo/types';
	import { ArrowLeft, Pin, PinOff, Archive, ArchiveRestore, Trash2, Copy, Palette } from 'lucide-svelte';
	import * as m from '$lib/paraglide/messages';

	const noteId = $page.params.id!;

	let note = $state<Note | null>(null);
	let title = $state('');
	let content = $state('');
	let saving = $state(false);
	let savedAt = $state<number>(0);
	let showColorPicker = $state(false);

	let saveTimer: ReturnType<typeof setTimeout> | null = null;
	const SAVE_DEBOUNCE_MS = 500;

	onMount(async () => {
		const n = await loadNote(noteId);
		if (!n) {
			goto('/notes');
			return;
		}
		note = n;
		title = n.title ?? '';
		content = n.content;
	});

	onDestroy(() => {
		if (saveTimer) {
			clearTimeout(saveTimer);
			void flushSave();
		}
	});

	async function flushSave() {
		if (!note || !$currentUser) return;
		saving = true;
		await patchNote(note.id, $currentUser.id, {
			title: title.trim() || null,
			content
		});
		saving = false;
		savedAt = Date.now();
	}

	function scheduleSave() {
		if (saveTimer) clearTimeout(saveTimer);
		saveTimer = setTimeout(() => {
			saveTimer = null;
			void flushSave();
		}, SAVE_DEBOUNCE_MS);
	}

	function onTitleInput() {
		scheduleSave();
	}

	function onContentInput() {
		scheduleSave();
	}

	async function togglePin() {
		if (!note || !$currentUser) return;
		if (note.is_pinned) {
			await unpinNote(note.id, $currentUser.id);
			note = { ...note, is_pinned: false };
		} else {
			await pinNote(note.id, $currentUser.id);
			note = { ...note, is_pinned: true, is_archived: false };
		}
	}

	async function toggleArchive() {
		if (!note || !$currentUser) return;
		if (note.is_archived) {
			await unarchiveNote(note.id, $currentUser.id);
			note = { ...note, is_archived: false };
		} else {
			await archiveNote(note.id, $currentUser.id);
			goto('/notes');
		}
	}

	async function sendToTrash() {
		if (!note || !$currentUser) return;
		await trashNote(note.id, $currentUser.id);
		goto('/notes');
	}

	async function handleRestore() {
		if (!note || !$currentUser) return;
		await restoreNote(note.id, $currentUser.id);
		note = { ...note, deleted_at: null };
	}

	async function handleDuplicate() {
		if (!note || !$currentUser) return;
		const dup = await duplicateNote(note, $currentUser.id);
		if (dup) goto(`/notes/${dup.id}`);
	}

	async function setColor(color: NoteColor | null) {
		if (!note || !$currentUser) return;
		await patchNote(note.id, $currentUser.id, { color });
		note = { ...note, color };
		showColorPicker = false;
	}

	function colorBg(color: string | null): string {
		switch (color) {
			case 'yellow': return 'bg-yellow-50 dark:bg-yellow-900/20';
			case 'green':  return 'bg-emerald-50 dark:bg-emerald-900/20';
			case 'blue':   return 'bg-sky-50 dark:bg-sky-900/20';
			case 'pink':   return 'bg-pink-50 dark:bg-pink-900/20';
			case 'purple': return 'bg-purple-50 dark:bg-purple-900/20';
			case 'orange': return 'bg-orange-50 dark:bg-orange-900/20';
			case 'gray':   return 'bg-slate-100 dark:bg-slate-800/40';
			case 'red':    return 'bg-red-50 dark:bg-red-900/20';
			default:       return 'bg-background';
		}
	}

	function colorSwatch(color: NoteColor): string {
		switch (color) {
			case 'yellow': return 'bg-yellow-300';
			case 'green':  return 'bg-emerald-400';
			case 'blue':   return 'bg-sky-400';
			case 'pink':   return 'bg-pink-300';
			case 'purple': return 'bg-purple-400';
			case 'orange': return 'bg-orange-400';
			case 'gray':   return 'bg-slate-400';
			case 'red':    return 'bg-red-400';
		}
	}
</script>

<svelte:head><title>{title || m.notes_title()} — Colectivo</title></svelte:head>

<div class={`flex h-full flex-col overflow-hidden ${colorBg(note?.color ?? null)}`}>
	<header class="sticky top-0 z-30 flex h-14 flex-shrink-0 items-center gap-2 border-b border-black/5 bg-surface/80 px-4 backdrop-blur-xl md:px-6 dark:border-white/5">
		<a
			href="/notes"
			class="rounded p-1 text-text-secondary hover:bg-black/5 dark:hover:bg-white/5"
			aria-label={m.notes_back_to_board()}
		>
			<ArrowLeft size={18} strokeWidth={1.5} />
		</a>
		<div class="flex-1"></div>

		{#if note?.deleted_at}
			<span class="text-xs text-text-secondary">{m.notes_trash_view()}</span>
			<button
				type="button"
				onclick={handleRestore}
				class="rounded p-1.5 text-text-secondary hover:bg-black/5 dark:hover:bg-white/5"
				aria-label={m.notes_restore()}
				title={m.notes_restore()}
			>
				<ArchiveRestore size={16} strokeWidth={1.5} />
			</button>
		{:else}
			<span class="text-xs text-text-secondary">
				{saving ? m.notes_saving() : savedAt ? m.notes_saved() : ''}
			</span>

			<!-- Color picker -->
			<div class="relative">
				<button
					type="button"
					onclick={() => (showColorPicker = !showColorPicker)}
					class="rounded p-1.5 text-text-secondary hover:bg-black/5 dark:hover:bg-white/5"
					aria-label={m.notes_color()}
					title={m.notes_color()}
				>
					<Palette size={16} strokeWidth={1.5} />
				</button>
				{#if showColorPicker}
					<div class="absolute right-0 top-full z-50 mt-1 flex gap-1 rounded-md bg-surface-raised p-2 shadow-lg">
						<button
							type="button"
							onclick={() => setColor(null)}
							class="h-6 w-6 rounded-full border-2 border-black/20 bg-background"
							aria-label="default"
						></button>
						{#each NOTE_COLORS as c}
							<button
								type="button"
								onclick={() => setColor(c)}
								class={`h-6 w-6 rounded-full border-2 border-transparent hover:border-black/30 ${colorSwatch(c)}`}
								aria-label={c}
							></button>
						{/each}
					</div>
				{/if}
			</div>

			<button
				type="button"
				onclick={togglePin}
				class="rounded p-1.5 text-text-secondary hover:bg-black/5 dark:hover:bg-white/5"
				aria-label={note?.is_pinned ? m.notes_unpin() : m.notes_pin()}
				title={note?.is_pinned ? m.notes_unpin() : m.notes_pin()}
			>
				{#if note?.is_pinned}<PinOff size={16} strokeWidth={1.5} />{:else}<Pin size={16} strokeWidth={1.5} />{/if}
			</button>

			<button
				type="button"
				onclick={toggleArchive}
				class="rounded p-1.5 text-text-secondary hover:bg-black/5 dark:hover:bg-white/5"
				aria-label={note?.is_archived ? m.notes_unarchive() : m.notes_archive()}
				title={note?.is_archived ? m.notes_unarchive() : m.notes_archive()}
			>
				{#if note?.is_archived}<ArchiveRestore size={16} strokeWidth={1.5} />{:else}<Archive size={16} strokeWidth={1.5} />{/if}
			</button>

			<button
				type="button"
				onclick={handleDuplicate}
				class="rounded p-1.5 text-text-secondary hover:bg-black/5 dark:hover:bg-white/5"
				aria-label={m.notes_duplicate()}
				title={m.notes_duplicate()}
			>
				<Copy size={16} strokeWidth={1.5} />
			</button>

			<button
				type="button"
				onclick={sendToTrash}
				class="rounded p-1.5 text-text-secondary hover:bg-black/5 dark:hover:bg-white/5"
				aria-label={m.notes_send_to_trash()}
				title={m.notes_send_to_trash()}
			>
				<Trash2 size={16} strokeWidth={1.5} />
			</button>
		{/if}
	</header>

	<div class="flex-1 overflow-y-auto px-8 py-6">
		<input
			bind:value={title}
			oninput={onTitleInput}
			placeholder={m.notes_title_placeholder()}
			class="mb-4 w-full bg-transparent text-2xl font-semibold text-text-primary placeholder:text-text-secondary focus:outline-none"
		/>
		<textarea
			bind:value={content}
			oninput={onContentInput}
			placeholder={m.notes_content_placeholder()}
			aria-label={m.notes_content_aria()}
			class="h-[calc(100%-4rem)] w-full resize-none bg-transparent text-base text-text-primary placeholder:text-text-secondary focus:outline-none"
		></textarea>
	</div>
</div>
