<script lang="ts">
  import { api } from '$lib/api';
  import { clientSession } from '$lib/session';
  import { canPlaceOrders } from '$lib/workspace-access';
  import { toast } from '$lib/toast';
  import type { CatalogueProduct, Order } from '$lib/types';

  let { data } = $props();

  // Catalogue is read-only from the loader; orders is a mutable copy that
  // refreshOrders() reassigns, seeded from `data` via an effect.
  const catalogue = $derived<CatalogueProduct[]>(data.catalogue ?? []);
  let orders = $state<Order[]>([]);
  $effect(() => {
    orders = data.orders ?? [];
  });
  let category = $state<string>('all');
  let search = $state('');

  // Cart: product_id -> quantity
  let cart = $state<Record<number, number>>({});
  let editingOrderId = $state<number | null>(null);
  let poNumber = $state('');
  let deliveryNotes = $state('');
  let requestedDate = $state('');
  let fulfilment = $state<'delivery' | 'pickup'>('delivery');
  let busy = $state(false);

  const canOrder = $derived(canPlaceOrders($clientSession));

  const categories = $derived(['all', ...Array.from(new Set(catalogue.map((p) => p.category)))]);
  const productById = $derived(Object.fromEntries(catalogue.map((p) => [p.id, p])) as Record<number, CatalogueProduct>);

  const filtered = $derived(
    catalogue.filter((p) => {
      if (category !== 'all' && p.category !== category) return false;
      if (search) {
        const n = search.toLowerCase();
        return p.name.toLowerCase().includes(n) || p.sku.toLowerCase().includes(n);
      }
      return true;
    })
  );

  const cartLines = $derived(
    Object.entries(cart)
      .map(([id, qty]) => ({ product: productById[Number(id)], qty }))
      .filter((l) => l.product)
  );
  const cartCount = $derived(cartLines.length);
  const cartSubtotal = $derived(
    cartLines.reduce((sum, l) => sum + (l.product.price?.unit_price != null ? l.product.price.unit_price * l.qty : 0), 0)
  );
  const cartHasQuote = $derived(cartLines.some((l) => l.product.price?.requires_quote));

  function money(value: number | null | undefined) {
    if (value == null) return '—';
    return new Intl.NumberFormat('en-AU', { style: 'currency', currency: 'AUD' }).format(value);
  }

  function statusLabel(s: string) {
    return s.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
  }

  function addToCart(p: CatalogueProduct) {
    const current = cart[p.id] ?? 0;
    cart[p.id] = current ? current + 1 : Math.max(1, p.min_order_quantity);
  }

  function setQty(id: number, qty: number) {
    if (qty <= 0) {
      delete cart[id];
      cart = { ...cart };
    } else {
      cart[id] = qty;
    }
  }

  function clearCart() {
    cart = {};
    editingOrderId = null;
    poNumber = '';
    deliveryNotes = '';
    requestedDate = '';
    fulfilment = 'delivery';
  }

  function buildPayload() {
    return {
      lines: cartLines.map((l) => ({ product_id: l.product.id, quantity: l.qty })),
      purchase_order_number: poNumber || null,
      delivery_notes: deliveryNotes || null,
      requested_delivery_date: requestedDate ? new Date(requestedDate).toISOString() : null,
      fulfilment_method: fulfilment
    };
  }

  async function refreshOrders() {
    try {
      orders = await api.ordering.orders();
    } catch {
      /* ignore */
    }
  }

  async function saveDraft() {
    if (!cartCount) return toast.error('Add at least one product first.');
    busy = true;
    try {
      const payload = buildPayload();
      const saved = editingOrderId
        ? await api.ordering.updateDraft(editingOrderId, payload)
        : await api.ordering.createDraft(payload);
      editingOrderId = saved.id;
      toast.success(`Draft saved (${money(saved.subtotal_ex_gst)} ex GST).`);
      await refreshOrders();
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Could not save draft.');
    } finally {
      busy = false;
    }
  }

  async function submitOrder() {
    if (!cartCount) return toast.error('Add at least one product first.');
    busy = true;
    try {
      const payload = buildPayload();
      const saved = editingOrderId
        ? await api.ordering.updateDraft(editingOrderId, payload)
        : await api.ordering.createDraft(payload);
      const submitted = await api.ordering.submit(saved.id, {});
      toast.success(`Order ${submitted.order_number} submitted.`);
      clearCart();
      await refreshOrders();
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Could not submit order.');
    } finally {
      busy = false;
    }
  }

  async function editDraft(order: Order) {
    cart = Object.fromEntries(order.lines.map((l) => [l.product_id, l.quantity]));
    editingOrderId = order.id;
    poNumber = order.purchase_order_number ?? '';
    deliveryNotes = order.delivery_notes ?? '';
    requestedDate = order.requested_delivery_date ? order.requested_delivery_date.slice(0, 10) : '';
    fulfilment = (order.fulfilment_method as 'delivery' | 'pickup') ?? 'delivery';
    toast.add('Draft loaded into the order builder.', 'info');
  }

  async function reorder(order: Order) {
    busy = true;
    try {
      const draft = await api.ordering.reorder(order.id);
      await editDraft(draft);
      await refreshOrders();
      toast.success('Reorder draft created.');
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Could not reorder.');
    } finally {
      busy = false;
    }
  }

  async function downloadPdf(order: Order) {
    try {
      const blob = await api.ordering.confirmationPdf(order.id);
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `order-${order.order_number ?? order.id}.pdf`;
      a.click();
      URL.revokeObjectURL(url);
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Could not download PDF.');
    }
  }
</script>

<div class="ordering">
  <div class="layout">
    <!-- Catalogue -->
    <section class="catalogue surface-card">
      <div class="toolbar">
        <input class="search" placeholder="Search products or SKU…" bind:value={search} />
        <div class="chips">
          {#each categories as cat}
            <button class="chip" class:active={category === cat} onclick={() => (category = cat)}>
              {cat === 'all' ? 'All' : statusLabel(cat)}
            </button>
          {/each}
        </div>
      </div>

      {#if !filtered.length}
        <p class="empty">No products available.</p>
      {:else}
        <div class="grid">
          {#each filtered as p (p.id)}
            <article class="product">
              <div class="product-top">
                <span class="cat-tag">{statusLabel(p.category)}</span>
                {#if p.stock_status !== 'in_stock'}<span class="stock">{statusLabel(p.stock_status)}</span>{/if}
              </div>
              <h3>{p.name}</h3>
              <p class="sku">{p.sku} · {p.unit_of_measure}</p>
              {#if p.description}<p class="desc">{p.description}</p>{/if}
              <div class="price-row">
                {#if p.price?.requires_quote}
                  <span class="quote-badge">Quote required</span>
                {:else}
                  <strong>{money(p.price?.unit_price)}</strong>
                  <span class="price-label">{p.price?.label}</span>
                {/if}
              </div>
              <div class="product-foot">
                <span class="moq">Min {p.min_order_quantity}</span>
                {#if canOrder}
                  <button class="add-btn" onclick={() => addToCart(p)} disabled={p.price?.requires_quote}>
                    {p.price?.requires_quote ? 'Quote' : 'Add'}
                  </button>
                {/if}
              </div>
            </article>
          {/each}
        </div>
      {/if}
    </section>

    <!-- Cart / order builder -->
    <aside class="cart surface-card">
      <div class="cart-head">
        <h2>{editingOrderId ? 'Editing draft' : 'Order builder'}</h2>
        {#if cartCount}<button class="link" onclick={clearCart}>Clear</button>{/if}
      </div>

      {#if !canOrder}
        <p class="empty">Your role has view-only access. Contact an account owner to place orders.</p>
      {:else if !cartCount}
        <p class="empty">Add products from the catalogue to build an order.</p>
      {:else}
        <ul class="cart-lines">
          {#each cartLines as line (line.product.id)}
            <li>
              <div class="cl-main">
                <span class="cl-name">{line.product.name}</span>
                <button class="link remove" onclick={() => setQty(line.product.id, 0)}>Remove</button>
              </div>
              <div class="cl-foot">
                <input
                  class="qty"
                  type="number"
                  min={line.product.min_order_quantity}
                  step="1"
                  value={line.qty}
                  oninput={(e) => setQty(line.product.id, Number(e.currentTarget.value))}
                />
                <span class="cl-unit">{line.product.price?.requires_quote ? 'Quote' : money(line.product.price?.unit_price)}</span>
                <span class="cl-total">
                  {line.product.price?.unit_price != null ? money(line.product.price.unit_price * line.qty) : '—'}
                </span>
              </div>
            </li>
          {/each}
        </ul>

        <div class="totals">
          <span>Subtotal (ex GST)</span>
          <strong>{money(cartSubtotal)}</strong>
        </div>
        {#if cartHasQuote}<p class="quote-note">Some items need a quote — our team will confirm pricing.</p>{/if}

        <div class="order-fields">
          <label>PO number <input bind:value={poNumber} placeholder="Optional" /></label>
          <label>Requested date <input type="date" bind:value={requestedDate} /></label>
          <label class="full">
            Fulfilment
            <select bind:value={fulfilment}>
              <option value="delivery">Delivery</option>
              <option value="pickup">Pickup</option>
            </select>
          </label>
          <label class="full">Delivery notes <textarea bind:value={deliveryNotes} rows="2" placeholder="Optional"></textarea></label>
        </div>

        <div class="cart-actions">
          <button class="secondary" onclick={saveDraft} disabled={busy}>Save draft</button>
          <button class="primary" onclick={submitOrder} disabled={busy}>Submit order</button>
        </div>
      {/if}
    </aside>
  </div>

  <!-- Order history -->
  <section class="history surface-card">
    <h2>Your orders</h2>
    {#if !orders.length}
      <p class="empty">No orders yet.</p>
    {:else}
      <table>
        <thead>
          <tr><th>Order</th><th>Status</th><th>Items</th><th>Subtotal</th><th>Created</th><th></th></tr>
        </thead>
        <tbody>
          {#each orders as o (o.id)}
            <tr>
              <td>{o.order_number ?? `Draft #${o.id}`}</td>
              <td><span class="pill pill-{o.status}">{statusLabel(o.status)}</span></td>
              <td>{o.lines.length}</td>
              <td>{o.requires_quote ? 'Quote' : money(o.subtotal_ex_gst)}</td>
              <td>{new Date(o.created_at).toLocaleDateString('en-AU')}</td>
              <td class="row-actions">
                {#if o.editable && canOrder}<button class="link" onclick={() => editDraft(o)}>Edit</button>{/if}
                {#if canOrder}<button class="link" onclick={() => reorder(o)}>Reorder</button>{/if}
                {#if o.order_number}<button class="link" onclick={() => downloadPdf(o)}>PDF</button>{/if}
              </td>
            </tr>
          {/each}
        </tbody>
      </table>
    {/if}
  </section>
</div>

<style>
  .ordering { display: grid; gap: 1.25rem; }
  h2 { margin: 0 0 0.75rem; font-size: 1.05rem; }
  h3 { margin: 0; font-size: 0.98rem; }
  p { margin: 0; }
  .surface-card { border: 1px solid rgba(34, 54, 45, 0.12); border-radius: 1rem; background: var(--surface, rgba(255,255,255,0.9)); padding: 1.1rem; }
  .layout { display: grid; grid-template-columns: minmax(0, 1fr) 22rem; gap: 1.25rem; align-items: start; }
  .toolbar { display: grid; gap: 0.6rem; margin-bottom: 1rem; }
  .search { width: 100%; padding: 0.6rem 0.75rem; border: 1px solid rgba(34,54,45,0.15); border-radius: 0.7rem; }
  .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }
  .chip { padding: 0.3rem 0.7rem; border: 1px solid rgba(34,54,45,0.15); border-radius: 999px; background: transparent; cursor: pointer; font-size: 0.8rem; }
  .chip.active { background: var(--color-brand, #2f6f4f); color: #fff; border-color: transparent; }
  .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); gap: 0.85rem; }
  .product { display: flex; flex-direction: column; gap: 0.4rem; padding: 0.85rem; border: 1px solid rgba(34,54,45,0.1); border-radius: 0.85rem; background: rgba(248,251,249,0.6); }
  .product-top { display: flex; justify-content: space-between; gap: 0.5rem; }
  .cat-tag { font-size: 0.66rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: #6e8576; }
  .stock { font-size: 0.66rem; font-weight: 700; color: #b07a1a; }
  .sku { color: #7c8c82; font-size: 0.76rem; }
  .desc { color: #64776b; font-size: 0.8rem; line-height: 1.3; }
  .price-row { display: flex; align-items: baseline; gap: 0.5rem; margin-top: auto; }
  .price-row strong { font-size: 1.05rem; }
  .price-label { font-size: 0.7rem; color: #7c8c82; }
  .quote-badge { font-size: 0.78rem; font-weight: 600; color: #b07a1a; }
  .product-foot { display: flex; align-items: center; justify-content: space-between; }
  .moq { font-size: 0.72rem; color: #7c8c82; }
  .add-btn, .primary, .secondary { border-radius: 0.7rem; padding: 0.45rem 0.85rem; font-weight: 600; cursor: pointer; border: none; }
  .add-btn { background: var(--color-brand, #2f6f4f); color: #fff; }
  .add-btn:disabled { opacity: 0.5; cursor: not-allowed; }
  .cart-head { display: flex; justify-content: space-between; align-items: center; }
  .cart-lines { list-style: none; margin: 0.5rem 0; padding: 0; display: grid; gap: 0.6rem; }
  .cart-lines li { border-bottom: 1px solid rgba(34,54,45,0.08); padding-bottom: 0.5rem; }
  .cl-main { display: flex; justify-content: space-between; gap: 0.5rem; }
  .cl-name { font-size: 0.86rem; font-weight: 600; }
  .cl-foot { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.35rem; }
  .qty { width: 4rem; padding: 0.3rem 0.4rem; border: 1px solid rgba(34,54,45,0.15); border-radius: 0.5rem; }
  .cl-unit { font-size: 0.78rem; color: #7c8c82; }
  .cl-total { margin-left: auto; font-weight: 600; font-size: 0.86rem; }
  .totals { display: flex; justify-content: space-between; align-items: baseline; padding: 0.6rem 0; border-top: 1px solid rgba(34,54,45,0.12); }
  .totals strong { font-size: 1.1rem; }
  .quote-note { font-size: 0.76rem; color: #b07a1a; }
  .order-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 0.55rem; margin: 0.6rem 0; }
  .order-fields label { display: grid; gap: 0.2rem; font-size: 0.74rem; color: #64776b; }
  .order-fields .full { grid-column: 1 / -1; }
  .order-fields input, .order-fields select, .order-fields textarea { padding: 0.45rem 0.5rem; border: 1px solid rgba(34,54,45,0.15); border-radius: 0.5rem; font: inherit; }
  .cart-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
  .primary { background: var(--color-brand, #2f6f4f); color: #fff; }
  .secondary { background: rgba(34,54,45,0.08); color: #22362d; }
  .primary:disabled, .secondary:disabled { opacity: 0.6; cursor: wait; }
  .link { background: none; border: none; color: var(--color-brand, #2f6f4f); cursor: pointer; font-size: 0.8rem; padding: 0; }
  .remove { color: #b33636; }
  .empty { color: #7c8c82; font-size: 0.86rem; padding: 0.5rem 0; }
  table { width: 100%; border-collapse: collapse; font-size: 0.86rem; }
  th, td { text-align: left; padding: 0.5rem 0.6rem; border-bottom: 1px solid rgba(34,54,45,0.08); }
  th { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em; color: #7c8c82; }
  .row-actions { display: flex; gap: 0.6rem; }
  .pill { padding: 0.18rem 0.55rem; border-radius: 999px; font-size: 0.72rem; font-weight: 600; background: rgba(34,54,45,0.08); }
  .pill-draft { background: #eee; color: #555; }
  .pill-submitted, .pill-processing { background: #fdf0d5; color: #8a5a00; }
  .pill-confirmed { background: #d8ece0; color: #1f6b46; }
  .pill-dispatched, .pill-ready { background: #d5e4fd; color: #234e8a; }
  .pill-completed { background: #d8ece0; color: #1f6b46; }
  .pill-cancelled { background: #f7d5d5; color: #8a2323; }
  @media (max-width: 960px) { .layout { grid-template-columns: 1fr; } }
</style>
