<script lang="ts">
	import TaskItem from "$lib/ui/data/TaskItem.svelte";
	import Card from "$lib/ui/layout/Card.svelte";
	import { onMount } from "svelte";
	import { slide } from "svelte/transition";

	type GroupItem = {
		id: string;
		name: string | null;
		counts: { open: number; unassigned: number };
	};
	type Task = {
		id: number;
		description: string;
		due_date: string | null;
		display_code: number | null;
		group_id?: string | null;
		assignees?: string[];
	};

	export let data: {
		userId: string | null;
		groups: GroupItem[];
		itemsByGroup: Record<string, Task[]>;
		unassignedFirst?: boolean;
	};
	const groups = data.groups || [];
	let itemsByGroup: Record<string, Task[]> = {};
	for (const [gid, arr] of Object.entries(data.itemsByGroup || {})) {
		itemsByGroup[gid] = Array.isArray(arr as any) ? [...(arr as any)] : [];
	}

	function buildQuery(params: { unassignedFirst?: boolean }) {
		const sp = new URLSearchParams();
		if (params.unassignedFirst) sp.set("unassignedFirst", "true");
		return sp.toString();
	}

	const storageKey = `groupsCollapsed:v1:${data.userId ?? "anon"}`;
	let collapsed: Record<string, boolean> = {};

	function hasTasks(groupId: string): boolean {
		const arr = itemsByGroup[groupId] || [];
		return Array.isArray(arr) && arr.length > 0;
	}

	function defaultCollapsedFor(groupId: string): boolean {
		// Por defecto, colapsado si no tiene tareas abiertas
		return !hasTasks(groupId);
	}

	function isOpen(groupId: string): boolean {
		const v = collapsed[groupId];
		if (typeof v === "boolean") return !v;
		return !defaultCollapsedFor(groupId);
	}

	function saveCollapsed() {
		try {
			const currentIds = new Set(groups.map((g) => g.id));
			const pruned: Record<string, boolean> = {};
			for (const id of Object.keys(collapsed)) {
				if (currentIds.has(id)) pruned[id] = !!collapsed[id];
			}
			localStorage.setItem(storageKey, JSON.stringify(pruned));
		} catch {}
	}

	function handleToggle(groupId: string, e: Event) {
		const open = (e.currentTarget as HTMLDetailsElement).open;
		collapsed = { ...collapsed, [groupId]: !open };
		saveCollapsed();
	}

	onMount(() => {
		try {
			const raw = localStorage.getItem(storageKey);
			const saved = raw ? JSON.parse(raw) : {};
			const map: Record<string, boolean> = {};
			const currentIds = new Set(groups.map((g) => g.id));
			for (const g of groups) {
				map[g.id] =
					typeof saved?.[g.id] === "boolean"
						? !!saved[g.id]
						: defaultCollapsedFor(g.id);
			}
			// Limpieza de claves obsoletas en storage
			const cleaned: Record<string, boolean> = {};
			for (const k of Object.keys(saved || {})) {
				if (currentIds.has(k)) cleaned[k] = !!saved[k];
			}
			collapsed = map;
			localStorage.setItem(storageKey, JSON.stringify(cleaned || map));
		} catch {
			// si falla, dejamos los defaults (basados en tareas)
			collapsed = {};
		}
	});

	function maintainScrollWhile(mutate: () => void) {
		const y = window.scrollY;
		mutate();
		queueMicrotask(() => window.scrollTo({ top: y }));
	}

	function updateGroupTask(
		groupId: string,
		detail: {
			id: number;
			action: string;
			patch: Partial<
				Task & { completed?: boolean; completed_at?: string | null }
			>;
		},
	) {
		const { id, action, patch } = detail;
		const arr = itemsByGroup[groupId] || [];
		const idx = arr.findIndex((t) => t.id === id);

		if (action === "complete") {
			if (idx >= 0) {
				maintainScrollWhile(() => {
					arr.splice(idx, 1);
					itemsByGroup = { ...itemsByGroup, [groupId]: [...arr] };
				});
			}
			return;
		}

		if (idx >= 0) {
			arr[idx] = { ...arr[idx], ...patch };
			itemsByGroup = { ...itemsByGroup, [groupId]: [...arr] };
		}
	}
</script>

<svelte:head>
	<title>Grupos</title>
	<meta name="robots" content="noindex,nofollow" />
</svelte:head>

{#if groups.length === 0}
	<p>No perteneces a ningún grupo permitido.</p>
{:else}
	<h1 class="title">Grupos</h1>

	<div class="toolbar">
		<label class="toggle">
			<input
				type="checkbox"
				checked={!!data.unassignedFirst}
				on:change={(e) => {
					const checked = (e.currentTarget as HTMLInputElement).checked;
					const q = buildQuery({ unassignedFirst: checked });
					location.href = q ? `/app/groups?${q}` : `/app/groups`;
				}}
			/>
			Sin responsable primero
		</label>
	</div>

	{#each groups as g (g.id)}
		<details
			class="group"
			open={isOpen(g.id)}
			on:toggle={(e) => handleToggle(g.id, e)}
		>
			<summary class="group-header">
				<span class="name">{g.name ?? g.id}</span>
				<span class="counts">
					<span class="badge">tareas: {g.counts.open}</span>
					<span class="badge warn">🙅‍♂️: {g.counts.unassigned}</span>
				</span>
			</summary>
			{#if isOpen(g.id)}
				<div in:slide={{ duration: 180 }} out:slide={{ duration: 180 }}>
					<Card>
						<ul class="list">
							{#each itemsByGroup[g.id] || [] as t (t.id)}
								<TaskItem
									id={t.id}
									description={t.description}
									due_date={t.due_date}
									display_code={t.display_code}
									assignees={t.assignees || []}
									currentUserId={data.userId}
									groupName={g.name ?? g.id}
									groupId={t.group_id ?? g.id}
									on:changed={(e) => updateGroupTask(g.id, e.detail)}
								/>
							{/each}
						</ul>
					</Card>
				</div>
			{/if}
		</details>
	{/each}
{/if}

<style>
	.title {
		margin-bottom: 0.75rem;
	}
	.toolbar {
		display: flex;
		justify-content: flex-end;
		margin-bottom: 0.5rem;
	}
	.toggle {
		display: inline-flex;
		gap: 6px;
		align-items: center;
	}
	.group {
		margin: 0.5rem 0;
		border: 1px solid var(--color-border);
		border-radius: 8px;
		background: var(--color-surface);
	}
	.group-header {
		display: flex;
		justify-content: space-between;
		padding: 0.5rem 0.75rem;
		cursor: pointer;
		list-style: none;
		user-select: none;
	}
	.group-header .name {
		font-weight: 600;
	}
	.counts {
		display: inline-flex;
		gap: 0.5rem;
	}
	.badge {
		padding: 2px 8px;
		border: 1px solid var(--color-border);
		border-radius: 999px;
		font-size: 12px;
		align-self: center;
		white-space: nowrap;
	}
	.badge.warn {
		border-color: var(--color-warning);
	}
	.list {
		margin: 0;
		padding: 0.25rem 0.5rem 0.5rem 0.5rem;
		list-style: none;
	}
</style>
