<script lang="ts">
  import { onMount } from "svelte";
  import { ScheduleState } from "$lib/schedule.svelte";
  import { formatShort, MONTH_NAMES, todayISO } from "$lib/dates";
  import ScheduleGrid from "$lib/components/ScheduleGrid.svelte";
  import ReservationDialog from "$lib/components/ReservationDialog.svelte";
  import CabinsDialog from "$lib/components/CabinsDialog.svelte";
  import InvoiceDialog from "$lib/components/InvoiceDialog.svelte";
  import InvoicePreview from "$lib/components/InvoicePreview.svelte";
  import { formatMoney } from "$lib/money";
  import * as db from "$lib/db";
  import type {
    Invoice,
    InvoiceDialogParams,
    InvoiceItem,
    Reservation,
    ReservationDialogParams
  } from "$lib/types";

  const schedule = new ScheduleState();

  let dialogParams = $state<ReservationDialogParams | null>(null);
  let cabinsOpen = $state(false);
  let invoiceParams = $state<InvoiceDialogParams | null>(null);
  let preview = $state<{ invoice: Invoice; items: InvoiceItem[] } | null>(null);

  async function openPreview(invoiceId: number) {
    const [invoice, items] = await Promise.all([
      db.getInvoice(invoiceId),
      db.getInvoiceItems(invoiceId)
    ]);
    if (invoice) {
      preview = { invoice, items };
    }
  }

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

  function newReservation(cabinId?: number, date?: string) {
    const cid = cabinId ?? schedule.cabins[0]?.id;
    if (cid == null) {
      cabinsOpen = true;
      return;
    }
    dialogParams = { cabin_id: cid, arrival: date ?? todayISO() };
  }

  function editReservation(r: Reservation) {
    dialogParams = { reservation: r };
  }

  let moveError = $state<string | null>(null);

  async function moveReservation(
    r: Reservation,
    cabinId: number,
    arrival: string,
    departure: string
  ) {
    moveError = null;
    try {
      const conflicts = await db.findConflicts(cabinId, arrival, departure, r.id);
      if (conflicts.length > 0) {
        const c = conflicts[0];
        moveError = `Nie można przenieść — termin koliduje z rezerwacją: ${c.guest_name} (${formatShort(c.arrival)} → ${formatShort(c.departure)}).`;
        setTimeout(() => (moveError = null), 5000);
        return;
      }
      await db.updateReservation(r.id, { ...r, cabin_id: cabinId, arrival, departure });
      await schedule.reload();
    } catch (e) {
      moveError = `Nie udało się przenieść rezerwacji: ${e}`;
    }
  }
</script>

<svelte:head>
  <title>Słoneczko — grafik rezerwacji</title>
</svelte:head>

<main>
  <header class="toolbar">
    <button type="button" class="icon" onclick={() => schedule.prevMonth()} aria-label="Poprzedni miesiąc">‹</button>
    <span class="month">{MONTH_NAMES[schedule.month]} {schedule.year}</span>
    <button type="button" class="icon" onclick={() => schedule.nextMonth()} aria-label="Następny miesiąc">›</button>
    <button type="button" onclick={() => schedule.goToday()}>Dziś</button>
    <span class="spacer"></span>
    <button type="button" onclick={() => (cabinsOpen = true)}>Domki</button>
    <button type="button" class="primary" onclick={() => newReservation()}>+ Nowa rezerwacja</button>
  </header>

  {#if schedule.monthStats && schedule.yearStats}
    <div class="stats">
      <span>
        <strong>{MONTH_NAMES[schedule.month]}:</strong>
        {Math.round(schedule.monthStats.nights_total)} dób ·
        {formatMoney(schedule.monthStats.revenue_total)} zł
        <span class="confirmed">(potwierdzone: {formatMoney(schedule.monthStats.revenue_confirmed)} zł)</span>
      </span>
      <span>
        <strong>Rok {schedule.year}:</strong>
        {Math.round(schedule.yearStats.nights_total)} dób ·
        {formatMoney(schedule.yearStats.revenue_total)} zł
        <span class="confirmed">(potwierdzone: {formatMoney(schedule.yearStats.revenue_confirmed)} zł)</span>
      </span>
    </div>
  {/if}

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

  {#if schedule.error}
    <p class="error">{schedule.error}</p>
  {:else if !schedule.loading && schedule.cabins.length === 0}
    <div class="empty">
      <p>Nie ma jeszcze żadnych domków. Dodaj je, aby zacząć planować rezerwacje.</p>
      <button type="button" class="primary" onclick={() => (cabinsOpen = true)}>Dodaj domki</button>
    </div>
  {:else}
    <ScheduleGrid
      cabins={schedule.cabins}
      days={schedule.days}
      reservations={schedule.reservations}
      onCellClick={(cabinId, date) => newReservation(cabinId, date)}
      onReservationClick={editReservation}
      onReservationMove={moveReservation}
    />
    <footer class="legend">
      <span><span class="sw confirmed"></span>Potwierdzona</span>
      <span><span class="sw option"></span>Opcja (niepotwierdzona)</span>
      <span><span class="sw ok"></span>Rozliczony</span>
      <span class="hint">✓ = zaliczka · klik w pustą komórkę dodaje · przeciąganie paska przenosi pobyt</span>
    </footer>
  {/if}
</main>

{#if dialogParams}
  <ReservationDialog
    params={dialogParams}
    cabins={schedule.cabins}
    onclose={() => (dialogParams = null)}
    onsaved={() => {
      dialogParams = null;
      void schedule.reload();
    }}
    oninvoice={(reservation) => {
      dialogParams = null;
      invoiceParams = { reservation };
      void schedule.reload();
    }}
  />
{/if}

{#if invoiceParams}
  <InvoiceDialog
    params={invoiceParams}
    onclose={() => (invoiceParams = null)}
    onsaved={(id) => {
      invoiceParams = null;
      void openPreview(id);
    }}
  />
{/if}

{#if preview}
  <InvoicePreview invoice={preview.invoice} items={preview.items} onclose={() => (preview = null)} />
{/if}

{#if cabinsOpen}
  <CabinsDialog
    cabins={schedule.cabins}
    onclose={() => (cabinsOpen = false)}
    onchanged={() => void schedule.reload()}
  />
{/if}

<style>
  main {
    padding: 14px 16px;
  }
  .toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
  }
  .toolbar .month {
    min-width: 150px;
    text-align: center;
    font-size: 16px;
    font-weight: 600;
  }
  .toolbar .spacer {
    flex: 1;
  }
  .toolbar button {
    font: inherit;
    font-size: 14px;
    padding: 7px 14px;
    border-radius: 7px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    cursor: pointer;
  }
  .toolbar button.icon {
    width: 34px;
    padding: 7px 0;
    font-size: 16px;
    line-height: 1;
  }
  .toolbar button.primary {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
  }
  .toolbar button:hover:not(.primary) {
    background: var(--bg);
  }
  .error {
    color: var(--danger);
  }
  .stats {
    display: flex;
    gap: 24px;
    flex-wrap: wrap;
    margin-bottom: 10px;
    font-size: 12px;
    color: var(--muted);
  }
  .stats strong {
    color: var(--text);
  }
  .stats .confirmed {
    color: var(--muted);
  }
  .empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 60px 20px;
    border: 1px dashed var(--border);
    border-radius: 10px;
    color: var(--muted);
  }
  .empty button.primary {
    font: inherit;
    padding: 8px 16px;
    border-radius: 7px;
    border: 1px solid var(--accent);
    background: var(--accent);
    color: #fff;
    cursor: pointer;
  }
  .legend {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-top: 10px;
    font-size: 12px;
    color: var(--muted);
  }
  .legend .sw {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 3px;
    vertical-align: -2px;
    margin-right: 6px;
  }
  .legend .sw.confirmed {
    background: var(--bar-confirmed-bg);
  }
  .legend .sw.option {
    background: var(--bar-option-bg);
  }
  .legend .sw.ok {
    background: var(--ok);
  }
  .legend .hint {
    margin-left: auto;
  }
</style>
