<script lang="ts">
  import Card from "$lib/ui/layout/Card.svelte";
  import TaskItem from "$lib/ui/data/TaskItem.svelte";
  import Pagination from "$lib/ui/layout/Pagination.svelte";

  type Task = {
    id: number;
    description: string;
    due_date: string | null;
    group_id: string | null;
    display_code: number | null;
    assignees: string[];
  };

  export let data: {
    userId: string;
    openTasks: Task[];
    recentTasks: (Task & {
      completed?: boolean;
      completed_at?: string | null;
    })[];
    unassignedOpen: Task[];
    groupNames: Record<string, string>;
    order: "due" | "group";
    page?: number | null;
    hasMore?: boolean | null;
  };

  // Estado local para permitir actualización sin recargar ni perder scroll
  let openTasks: Task[] = [...data.openTasks];
  let unassignedOpen: Task[] = [...data.unassignedOpen];
  let recentTasks: (Task & {
    completed?: boolean;
    completed_at?: string | null;
  })[] = [...data.recentTasks];

  function buildQuery(params: { order?: "due" | "group"; page?: number }) {
    const sp = new URLSearchParams();
    if (params.order) sp.set("order", params.order);
    if (params.page && params.page > 1) sp.set("page", String(params.page));
    return sp.toString();
  }

  function sortByDue(items: Task[]): Task[] {
    return [...items].sort((a, b) => {
      const ad = a.due_date,
        bd = b.due_date;
      if (ad == null && bd == null) return a.id - b.id;
      if (ad == null) return 1;
      if (bd == null) return -1;
      if (ad < bd) return -1;
      if (ad > bd) return 1;
      return a.id - b.id;
    });
  }

  function groupByGroup(
    items: Task[],
  ): { id: string; name: string; tasks: Task[] }[] {
    const map = new Map<string, Task[]>();
    for (const it of items) {
      const gid = it.group_id ? String(it.group_id) : "";
      if (!map.has(gid)) map.set(gid, []);
      map.get(gid)!.push(it);
    }
    const groups = Array.from(map.entries()).map(([gid, tasks]) => ({
      id: gid,
      name: gid ? data.groupNames[gid] || gid : "Personal",
      tasks,
    }));
    // Mantener el orden provisto por el servidor (ya ordenado alfabéticamente con "Personal" al final)
    return groups;
  }

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

  function updateTaskInLists(detail: {
    id: number;
    action: string;
    patch: Partial<
      Task & { completed?: boolean; completed_at?: string | null }
    >;
  }) {
    const { id, action, patch } = detail;

    const patchIn = (arr: Task[]) => {
      const idx = arr.findIndex((t) => t.id === id);
      if (idx >= 0) {
        arr[idx] = { ...arr[idx], ...patch };
        return true;
      }
      return false;
    };

    if (action === "complete") {
      maintainScrollWhile(() => {
        let moved = false;
        let idx = unassignedOpen.findIndex((t) => t.id === id);
        if (idx >= 0) {
          const [it] = unassignedOpen.splice(idx, 1);
          const completedItem: any = { ...it, ...patch, completed: true };
          recentTasks = [completedItem, ...recentTasks];
          moved = true;
        }
        idx = openTasks.findIndex((t) => t.id === id);
        if (idx >= 0) {
          const [it] = openTasks.splice(idx, 1);
          const completedItem: any = { ...it, ...patch, completed: true };
          recentTasks = [completedItem, ...recentTasks];
          moved = true;
        }
        if (!moved) {
          patchIn(recentTasks as any);
        }
        // Forzar reactividad en listas mutadas
        openTasks = [...openTasks];
        unassignedOpen = [...unassignedOpen];
        recentTasks = [...recentTasks];
      });
    } else if (action === "uncomplete") {
      maintainScrollWhile(() => {
        const idx = recentTasks.findIndex((t) => t.id === id);
        if (idx >= 0) {
          const [it] = recentTasks.splice(idx, 1);
          const reopened: any = { ...it, ...patch, completed: false };
          openTasks = [reopened, ...openTasks];
        } else {
          patchIn(openTasks);
        }
        openTasks = [...openTasks];
        recentTasks = [...recentTasks];
      });
    } else if (action === "claim") {
      maintainScrollWhile(() => {
        const idx = unassignedOpen.findIndex((t) => t.id === id);
        if (idx >= 0) {
          const [it] = unassignedOpen.splice(idx, 1);
          const claimed = { ...it, ...patch };
          if (!openTasks.some((x) => x.id === id)) {
            openTasks = [claimed, ...openTasks];
          } else {
            patchIn(openTasks);
          }
        } else {
          patchIn(openTasks);
        }
        openTasks = [...openTasks];
        unassignedOpen = [...unassignedOpen];
      });
    } else if (action === "unassign") {
      maintainScrollWhile(() => {
        if (!patchIn(openTasks)) patchIn(unassignedOpen);
        // Si quedó sin responsables, mover a "sin responsable"
        const idx = openTasks.findIndex((t) => t.id === id);
        if (idx >= 0 && (openTasks[idx].assignees || []).length === 0) {
          const [it] = openTasks.splice(idx, 1);
          unassignedOpen = [it, ...unassignedOpen];
        }
        openTasks = [...openTasks];
        unassignedOpen = [...unassignedOpen];
      });
    } else {
      // update_due, update_desc u otros parches ligeros
      if (!patchIn(openTasks)) {
        if (!patchIn(unassignedOpen)) {
          patchIn(recentTasks as any);
        }
      }
      openTasks = [...openTasks];
      unassignedOpen = [...unassignedOpen];
      recentTasks = [...recentTasks];
    }
  }
</script>

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

<p class="subtle">Sesión: <strong>{data.userId}</strong></p>

<div class="order-toggle">
  <span>Orden:</span>
  <a
    class:active={data.order === "due"}
    href={`/app?${buildQuery({ order: "due", page: data.page ?? 1 })}`}>Fecha</a
  >
  <a
    class:active={data.order === "group"}
    href={`/app?${buildQuery({ order: "group", page: data.page ?? 1 })}`}
    >Grupo</a
  >
</div>

<h2 class="section-title">Mis tareas</h2>
{#if openTasks.length === 0}
  <p>No tienes tareas asignadas. Crea o reclama una para empezar.</p>
{:else}
  <Card>
    <ul class="list">
      {#each openTasks as t (t.id)}
        <TaskItem
          {...t}
          currentUserId={data.userId}
          groupName={t.group_id
            ? data.groupNames[t.group_id] || t.group_id
            : "Personal"}
          groupId={t.group_id}
          on:changed={(e) => updateTaskInLists(e.detail)}
        />
      {/each}
    </ul>
  </Card>
{/if}

{#if (data.page ?? 1) > 1 || data.hasMore}
  <Pagination
    prevHref={(data.page ?? 1) > 1
      ? `/app?${buildQuery({ order: data.order, page: (data.page ?? 1) - 1 })}`
      : null}
    nextHref={data.hasMore
      ? `/app?${buildQuery({ order: data.order, page: (data.page ?? 1) + 1 })}`
      : null}
  />
{/if}

<h2 class="section-title">Sin responsable de mis grupos</h2>
{#if unassignedOpen.length === 0}
  <p>
    No hay tareas sin responsable en tus grupos. Crea una nueva o invita a
    alguien.
  </p>
{:else if data.order === "group"}
  {#each groupByGroup(unassignedOpen) as g (g.id)}
    <h3 class="group-subtitle">{g.name}</h3>
    <Card>
      <ul class="list">
        {#each g.tasks as t (t.id)}
          <TaskItem
            {...t}
            currentUserId={data.userId}
            groupName={g.name}
            groupId={t.group_id}
            on:changed={(e) => updateTaskInLists(e.detail)}
          />
        {/each}
      </ul>
    </Card>
  {/each}
{:else}
  <Card>
    <ul class="list">
      {#each unassignedOpen as t (t.id)}
        <TaskItem
          {...t}
          currentUserId={data.userId}
          groupName={t.group_id
            ? data.groupNames[t.group_id] || t.group_id
            : "Personal"}
          groupId={t.group_id}
          on:changed={(e) => updateTaskInLists(e.detail)}
        />
      {/each}
    </ul>
  </Card>
{/if}

<h2 class="section-title">Completadas (últimas 24 h)</h2>
{#if recentTasks.length === 0}
  <p>No hay tareas completadas recientemente.</p>
{:else}
  <Card>
    <ul class="list">
      {#each recentTasks as t (t.id)}
        <TaskItem
          {...t}
          currentUserId={data.userId}
          groupId={t.group_id}
          completed={true}
          completed_at={t.completed_at ?? null}
          groupName={t.group_id
            ? data.groupNames[t.group_id] || t.group_id
            : "Personal"}
          on:changed={(e) => updateTaskInLists(e.detail)}
        />
      {/each}
    </ul>
  </Card>
{/if}

<style>
  .subtle {
    color: var(--color-text-muted);
    margin: 0 0 1rem 0;
  }
  .order-toggle {
    display: inline-flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 0.5rem;
  }
  .order-toggle a {
    padding: 2px 8px;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    text-decoration: none;
    color: var(--color-text);
  }
  .order-toggle a.active {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: #fff;
  }
  .section-title {
    margin: 0.5rem 0;
  }
  .group-subtitle {
    margin: 0.5rem 0 0.25rem 0;
    font-size: 0.95rem;
  }
  .list {
    margin: 0;
    padding: 0;
    list-style: none;
  }
</style>
