<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, fade } 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 }} in:fade={{ duration: 120 }} out:fade={{ duration: 120 }}>
          <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;
  }
  .badge.warn {
    border-color: var(--color-warning);
  }
  .list {
    margin: 0;
    padding: 0.25rem 0.5rem 0.5rem 0.5rem;
    list-style: none;
  }
</style>
