<script lang="ts">
	import type { DocumentWithChildren } from "$lib/api/documents";

	interface Props {
		items: DocumentWithChildren[];
		selectedId?: string | null;
		onSelect: (doc: DocumentWithChildren) => void;
		onDoubleClick?: (doc: DocumentWithChildren) => void;
		onAdd?: (parentId: string | null) => void;
		onMove?: (docId: string, newParentId: string | null) => void;
		onEdit?: (doc: DocumentWithChildren) => void;
		onDelete?: (doc: DocumentWithChildren) => void;
		level?: number;
	}

	let {
		items,
		selectedId = null,
		onSelect,
		onDoubleClick,
		onAdd,
		onMove,
		onEdit,
		onDelete,
		level = 0,
	}: Props = $props();

	let expandedFolders = $state<Set<string>>(new Set());
	let dragOverId = $state<string | null>(null);

	function toggleFolder(id: string, e?: MouseEvent) {
		e?.stopPropagation();
		const newSet = new Set(expandedFolders);
		if (newSet.has(id)) {
			newSet.delete(id);
		} else {
			newSet.add(id);
		}
		expandedFolders = newSet;
	}

	function handleSelect(doc: DocumentWithChildren) {
		onSelect(doc);
	}

	function handleAdd(e: MouseEvent, parentId: string | null) {
		e.stopPropagation();
		onAdd?.(parentId);
	}

	function handleDragStart(e: DragEvent, doc: DocumentWithChildren) {
		if (!e.dataTransfer) return;
		e.dataTransfer.effectAllowed = "move";
		e.dataTransfer.setData("text/plain", doc.id);
	}

	function handleDragOver(
		e: DragEvent,
		targetId: string | null,
		isFolder: boolean,
	) {
		if (!isFolder && targetId !== null) return;
		e.preventDefault();
		dragOverId = targetId;
	}

	function handleDragLeave() {
		dragOverId = null;
	}

	function handleDrop(e: DragEvent, targetFolderId: string | null) {
		e.preventDefault();
		dragOverId = null;
		const docId = e.dataTransfer?.getData("text/plain");
		if (docId && docId !== targetFolderId) {
			onMove?.(docId, targetFolderId);
		}
	}
</script>

<div
	class="space-y-0.5"
	ondragover={(e) => level === 0 && handleDragOver(e, null, true)}
	ondragleave={handleDragLeave}
	ondrop={(e) => level === 0 && handleDrop(e, null)}
	role="tree"
>
	{#each items as item}
		<div role="treeitem">
			<div
				class="group w-full flex items-center gap-2 px-3 py-2 rounded-lg text-left transition-colors cursor-pointer
					{selectedId === item.id
					? 'bg-primary/20 text-primary'
					: 'text-light/80 hover:bg-light/5'}
					{dragOverId === item.id ? 'ring-2 ring-primary bg-primary/10' : ''}"
				onclick={() => handleSelect(item)}
				ondblclick={() => onDoubleClick?.(item)}
				draggable="true"
				ondragstart={(e) => handleDragStart(e, item)}
				ondragover={(e) =>
					handleDragOver(e, item.id, item.type === "folder")}
				ondragleave={handleDragLeave}
				ondrop={(e) => item.type === "folder" && handleDrop(e, item.id)}
				role="button"
				tabindex="0"
			>
				{#if item.type === "folder"}
					<button
						class="p-0.5 hover:bg-light/10 rounded"
						onclick={(e) => toggleFolder(item.id, e)}
						aria-label="Toggle folder"
					>
						<svg
							class="w-4 h-4 transition-transform {expandedFolders.has(
								item.id,
							)
								? 'rotate-90'
								: ''}"
							viewBox="0 0 24 24"
							fill="none"
							stroke="currentColor"
							stroke-width="2"
						>
							<path d="m9 18 6-6-6-6" />
						</svg>
					</button>
					<svg
						class="w-4 h-4 text-warning"
						viewBox="0 0 24 24"
						fill="currentColor"
					>
						<path
							d="M3 7V17C3 18.1046 3.89543 19 5 19H19C20.1046 19 21 18.1046 21 17V9C21 7.89543 20.1046 7 19 7H12L10 5H5C3.89543 5 3 5.89543 3 7Z"
						/>
					</svg>
				{:else}
					<div class="w-5"></div>
					<svg
						class="w-4 h-4 text-light/50"
						viewBox="0 0 24 24"
						fill="none"
						stroke="currentColor"
						stroke-width="2"
					>
						<path
							d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
						/>
						<polyline points="14,2 14,8 20,8" />
						<line x1="16" y1="13" x2="8" y2="13" />
						<line x1="16" y1="17" x2="8" y2="17" />
					</svg>
				{/if}
				<span class="flex-1 truncate text-sm">{item.name}</span>

				<div
					class="opacity-0 group-hover:opacity-100 flex items-center gap-0.5 transition-opacity"
				>
					{#if item.type === "folder" && onAdd}
						<button
							class="p-1 hover:bg-light/10 rounded"
							onclick={(e) => handleAdd(e, item.id)}
							aria-label="Add to folder"
						>
							<svg
								class="w-4 h-4"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								stroke-width="2"
							>
								<line x1="12" y1="5" x2="12" y2="19" />
								<line x1="5" y1="12" x2="19" y2="12" />
							</svg>
						</button>
					{/if}
					{#if onEdit}
						<button
							class="p-1 hover:bg-light/10 rounded"
							onclick={(e) => {
								e.stopPropagation();
								onEdit(item);
							}}
							aria-label="Rename"
						>
							<svg
								class="w-4 h-4"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								stroke-width="2"
							>
								<path
									d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"
								/>
								<path
									d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"
								/>
							</svg>
						</button>
					{/if}
					{#if onDelete}
						<button
							class="p-1 hover:bg-error/20 hover:text-error rounded"
							onclick={(e) => {
								e.stopPropagation();
								onDelete(item);
							}}
							aria-label="Delete"
						>
							<svg
								class="w-4 h-4"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								stroke-width="2"
							>
								<polyline points="3,6 5,6 21,6" />
								<path
									d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
								/>
							</svg>
						</button>
					{/if}
				</div>
			</div>

			{#if item.type === "folder" && expandedFolders.has(item.id)}
				<div class="ml-4 border-l border-light/10 pl-2">
					{#if item.children?.length}
						<svelte:self
							items={item.children}
							{selectedId}
							{onSelect}
							{onAdd}
							{onMove}
							{onEdit}
							{onDelete}
							level={level + 1}
						/>
					{:else}
						<p class="text-light/30 text-xs px-3 py-2 italic">
							Empty folder
						</p>
					{/if}
				</div>
			{/if}
		</div>
	{/each}

	{#if items.length === 0 && level === 0}
		<p class="text-light/40 text-sm px-3 py-2">No documents yet</p>
	{/if}
</div>
