<script lang="ts">
  import { onMount } from "svelte";
  import * as db from "$lib/db";
  import { addDays, formatShort, todayISO } from "$lib/dates";
  import type { Cabin, Reservation } from "$lib/types";

  const DAYS_AHEAD = 14;

  interface Task {
    kind: "cleaning" | "prep";
    r: Reservation;
  }

  let cabins = $state<Cabin[]>([]);
  let overdue = $state<Reservation[]>([]);
  let upcoming = $state<Reservation[]>([]);
  let preps = $state<Reservation[]>([]);
  let sameDayArrivals = $state<Set<string>>(new Set());
  let loading = $state(true);
  let error = $state<string | null>(null);

  const today = todayISO();

  async function reload() {
    loading = true;
    error = null;
    try {
      const until = addDays(today, DAYS_AHEAD);
      const [c, over, upc, firstArrivals, arrivals] = await Promise.all([
        db.listCabins(),
        db.overdueCleanings(today),
        db.upcomingCleanings(today, until),
        db.firstArrivalsNeedingPrep(today, until),
        db.arrivalsInRange(today, until)
      ]);
      cabins = c;
      overdue = over;
      upcoming = upc;
      preps = firstArrivals;
      sameDayArrivals = new Set(arrivals.map((a) => `${a.cabin_id}|${a.arrival}`));
    } catch (e) {
      error = `Nie udało się wczytać sprzątań: ${e}`;
    } finally {
      loading = false;
    }
  }

  onMount(() => {
    void reload();
  });

  let byDay = $derived.by(() => {
    const map = new Map<string, Task[]>();
    const push = (date: string, task: Task) => {
      const list = map.get(date);
      if (list) {
        list.push(task);
      } else {
        map.set(date, [task]);
      }
    };
    for (const r of upcoming) push(r.departure, { kind: "cleaning", r });
    for (const r of preps) push(r.arrival, { kind: "prep", r });
    return [...map.entries()].sort(([a], [b]) => (a < b ? -1 : 1));
  });

  function cabinName(id: number): string {
    return cabins.find((c) => c.id === id)?.name ?? `Domek #${id}`;
  }

  function dayLabel(iso: string): string {
    const weekday = new Date(iso + "T00:00:00").toLocaleDateString("pl-PL", { weekday: "long" });
    const prefix = iso === today ? "Dziś — " : iso === addDays(today, 1) ? "Jutro — " : "";
    return `${prefix}${weekday}, ${formatShort(iso)}`;
  }

  function hasSameDayArrival(r: Reservation): boolean {
    return sameDayArrivals.has(`${r.cabin_id}|${r.departure}`);
  }

  async function toggleCleaned(r: Reservation, cleaned: boolean) {
    error = null;
    try {
      await db.setReservationCleaned(r.id, cleaned);
      r.cleaned = cleaned;
      // zaległe znikają z listy dopiero po odświeżeniu — od razu, żeby lista była aktualna
      if (overdue.some((o) => o.id === r.id)) {
        await reload();
      }
    } catch (e) {
      error = `Nie udało się zapisać: ${e}`;
    }
  }

  async function togglePrepared(r: Reservation, prepared: boolean) {
    error = null;
    try {
      await db.setReservationPrepared(r.id, prepared);
      r.prepared = prepared;
    } catch (e) {
      error = `Nie udało się zapisać: ${e}`;
    }
  }
</script>

<svelte:head>
  <title>Słoneczko — sprzątanie</title>
</svelte:head>

<main>
  <header class="toolbar">
    <h1>Sprzątanie</h1>
    <span class="hint">wyjazdy z najbliższych {DAYS_AHEAD} dni</span>
  </header>

  {#if error}
    <p class="error">{error}</p>
  {/if}

  {#if overdue.length > 0}
    <section class="overdue">
      <h2>Zaległe</h2>
      {#each overdue as r (r.id)}
        <label class="task">
          <input
            type="checkbox"
            checked={r.cleaned}
            onchange={(e) => toggleCleaned(r, e.currentTarget.checked)}
          />
          <span class="cabin">{cabinName(r.cabin_id)}</span>
          <span class="muted">wyjazd {formatShort(r.departure)} · {r.guest_name}</span>
        </label>
      {/each}
    </section>
  {/if}

  {#if !loading && byDay.length === 0 && overdue.length === 0}
    <div class="empty">
      <p>Brak sprzątań w najbliższych dniach.</p>
    </div>
  {/if}

  {#each byDay as [day, tasks] (day)}
    <section class:today={day === today}>
      <h2>{dayLabel(day)}</h2>
      {#each tasks as task (`${task.kind}-${task.r.id}`)}
        {#if task.kind === "cleaning"}
          <label class="task">
            <input
              type="checkbox"
              checked={task.r.cleaned}
              onchange={(e) => toggleCleaned(task.r, e.currentTarget.checked)}
            />
            <span class="cabin" class:done={task.r.cleaned}>{cabinName(task.r.cabin_id)}</span>
            <span class="muted">po pobycie: {task.r.guest_name}</span>
            {#if hasSameDayArrival(task.r)}
              <span class="urgent">przyjazd tego samego dnia</span>
            {/if}
          </label>
        {:else}
          <label class="task">
            <input
              type="checkbox"
              checked={task.r.prepared}
              onchange={(e) => togglePrepared(task.r, e.currentTarget.checked)}
            />
            <span class="cabin" class:done={task.r.prepared}>{cabinName(task.r.cabin_id)}</span>
            <span class="muted">przygotować — przyjeżdża: {task.r.guest_name}</span>
            <span class="prep">pierwszy gość w domku</span>
          </label>
        {/if}
      {/each}
    </section>
  {/each}
</main>

<style>
  main {
    padding: 14px 16px;
    max-width: 640px;
  }
  .toolbar {
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 14px;
  }
  h1 {
    margin: 0;
    font-size: 18px;
  }
  .hint {
    color: var(--muted);
    font-size: 12px;
  }
  .error {
    color: var(--danger);
  }
  .empty {
    padding: 60px 20px;
    text-align: center;
    border: 1px dashed var(--border);
    border-radius: 10px;
    color: var(--muted);
  }
  section {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 12px 14px;
    margin-bottom: 12px;
  }
  section.today {
    border-color: var(--accent);
  }
  section.overdue {
    border-color: var(--danger);
  }
  section.overdue h2 {
    color: var(--danger);
  }
  h2 {
    margin: 0 0 8px;
    font-size: 13px;
    font-weight: 600;
  }
  h2::first-letter {
    text-transform: uppercase;
  }
  .task {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 4px;
    border-top: 1px solid var(--border);
    font-size: 14px;
    cursor: pointer;
  }
  .task input {
    width: 17px;
    height: 17px;
    flex: none;
    cursor: pointer;
  }
  .cabin {
    font-weight: 600;
    min-width: 110px;
  }
  .cabin.done {
    text-decoration: line-through;
    color: var(--muted);
    font-weight: 400;
  }
  .muted {
    color: var(--muted);
    font-size: 12px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .urgent {
    margin-left: auto;
    flex: none;
    font-size: 11px;
    font-weight: 600;
    color: var(--warn-text);
    background: var(--bar-option-bg);
    border-radius: 5px;
    padding: 2px 8px;
  }
  .prep {
    margin-left: auto;
    flex: none;
    font-size: 11px;
    font-weight: 600;
    color: var(--bar-confirmed-text);
    background: var(--bar-confirmed-bg);
    border-radius: 5px;
    padding: 2px 8px;
  }
</style>
