<script lang="ts">
  import { goto } from '$app/navigation';
  import { api } from '$lib/api';
  import MixCalculatorPrintDocument from '$lib/components/MixCalculatorPrintDocument.svelte';
  import { featureFlags } from '$lib/features';
  import { clientSession, hasModuleAccess } from '$lib/session';
  import { toast } from '$lib/toast';
  import type {
    MixCalculatorCreateInput,
    MixCalculatorOptions,
    MixCalculatorPreview,
    MixCalculatorSession
  } from '$lib/types';
  import MixCalculatorPreviewModal from './MixCalculatorPreviewModal.svelte';
  import MixCalculatorResultsPanel from './MixCalculatorResultsPanel.svelte';

  let { options, initialSession = null }: { options: MixCalculatorOptions; initialSession?: MixCalculatorSession | null } = $props();

  const todayIso = new Date().toISOString().slice(0, 10);

  function initialClientNameValue() {
    return initialSession?.client_name ?? options.clients[0] ?? '';
  }

  function initialProductIdValue() {
    return initialSession?.product_id ?? 0;
  }

  function initialMixDateValue() {
    return initialSession?.mix_date ?? todayIso;
  }

  function initialBatchSizeValue() {
    return initialSession ? `${initialSession.batch_size_kg}` : '';
  }

  function initialPreparedByNameValue() {
    return initialSession?.prepared_by_name ?? '';
  }

  function initialNotesValue() {
    return initialSession?.notes ?? '';
  }

  function initialPreviewValue() {
    return initialSession;
  }

  let clientName = $state(initialClientNameValue());
  let productId = $state(initialProductIdValue());
  let mixDate = $state(initialMixDateValue());
  let batchSizeKg = $state(initialBatchSizeValue());
  let preparedByName = $state(initialPreparedByNameValue());
  let notes = $state(initialNotesValue());
  let preview = $state<MixCalculatorPreview | MixCalculatorSession | null>(initialPreviewValue());
  let formError = $state('');
  let previewLoading = $state(false);
  let saveLoading = $state(false);
  let previewModalOpen = $state(false);

  const canEdit = $derived(hasModuleAccess($clientSession, 'mix_calculator', 'edit'));
  const isExistingSession = $derived(initialSession !== null);
  const availableClients = $derived(
    Array.from(new Set([...(options.clients ?? []), ...(initialSession ? [initialSession.client_name] : [])]))
  );
  const availableProducts = $derived(
    initialSession && !options.products.some((product) => product.product_id === initialSession.product_id)
      ? [
          ...options.products,
          {
            product_id: initialSession.product_id,
            client_name: initialSession.client_name,
            product_name: initialSession.product_name,
            mix_id: initialSession.mix_id,
            mix_name: initialSession.mix_name,
            unit_of_measure: initialSession.product_unit_of_measure,
            unit_size_kg: initialSession.product_unit_size_kg,
            mix_total_kg: initialSession.total_kg
          }
        ]
      : options.products
  );
  const filteredProducts = $derived(availableProducts.filter((product) => product.client_name === clientName));
  const selectedProduct = $derived(filteredProducts.find((product) => product.product_id === productId) ?? null);

  $effect(() => {
    if (!clientName && availableClients.length) {
      clientName = availableClients[0];
    }
  });

  $effect(() => {
    if (filteredProducts.length && !filteredProducts.some((product) => product.product_id === productId)) {
      productId = filteredProducts[0].product_id;
      return;
    }

    if (!filteredProducts.length) {
      productId = 0;
    }
  });

  $effect(() => {
    if (!preparedByName && $clientSession?.name) {
      preparedByName = $clientSession.name;
    }
  });

  function formatNumber(value: number | null | undefined, digits = 2) {
    if (value === null || value === undefined) {
      return 'N/A';
    }

    return value.toFixed(digits);
  }

  function buildPayload(): MixCalculatorCreateInput | null {
    formError = '';

    const numericBatchSize = Number(batchSizeKg);
    if (!mixDate) {
      formError = 'Select a mix date.';
      return null;
    }
    if (!clientName) {
      formError = 'Select a client.';
      return null;
    }
    if (!productId) {
      formError = 'Select a product.';
      return null;
    }
    if (!Number.isFinite(numericBatchSize) || numericBatchSize <= 0) {
      formError = 'Enter a batch size greater than zero.';
      return null;
    }
    if (!preparedByName.trim()) {
      formError = 'Enter the prepared by name.';
      return null;
    }

    return {
      mix_date: mixDate,
      client_name: clientName,
      product_id: productId,
      batch_size_kg: numericBatchSize,
      prepared_by_name: preparedByName.trim(),
      status: initialSession?.status ?? 'saved',
      notes: notes.trim() || null
    };
  }

  async function calculatePreview() {
    const payload = buildPayload();
    if (!payload) {
      toast.error(formError);
      return;
    }

    previewLoading = true;
    const tid = toast.loading('Calculating…');
    try {
      preview = await api.previewMixCalculatorSession(payload);
      toast.dismiss(tid);
    } catch (error) {
      toast.dismiss(tid);
      toast.error(error instanceof Error ? error.message : 'Unable to calculate the mix session.');
      formError = error instanceof Error ? error.message : 'Unable to calculate the mix session.';
    } finally {
      previewLoading = false;
    }
  }

  function clearForm() {
    clientName = options.clients[0] ?? '';
    productId = 0;
    mixDate = todayIso;
    batchSizeKg = '';
    preparedByName = $clientSession?.name ?? '';
    notes = '';
    preview = null;
    formError = '';
  }

  function printPreview() {
    if (typeof window !== 'undefined') {
      window.print();
    }
  }

  async function downloadSessionPdf(sessionId: number) {
    const tid = toast.loading('Generating PDF…');
    try {
      const blob = await api.mixCalculatorSessionPdf(sessionId);
      const url = URL.createObjectURL(blob);
      const anchor = document.createElement('a');
      anchor.href = url;
      anchor.download = `mix_calculator_${sessionId}.pdf`;
      document.body.appendChild(anchor);
      anchor.click();
      anchor.remove();
      URL.revokeObjectURL(url);
      toast.dismiss(tid);
    } catch (error) {
      toast.dismiss(tid);
      toast.error(error instanceof Error ? error.message : 'Unable to generate PDF.');
    }
  }

  function openPreviewModal() {
    if (!preview) {
      return;
    }

    previewModalOpen = true;
  }

  function closePreviewModal() {
    previewModalOpen = false;
  }

  async function saveSession(mode: 'update' | 'create', destination: 'detail' | 'print' = 'detail') {
    const payload = buildPayload();
    if (!payload) {
      return;
    }

    saveLoading = true;
    const tid = toast.loading(mode === 'update' ? 'Saving session…' : 'Creating session…');
    try {
      const saved =
        mode === 'update' && initialSession
          ? await api.updateMixCalculatorSession(initialSession.id, payload)
          : await api.createMixCalculatorSession(payload);

      toast.dismiss(tid);
      toast.success(mode === 'update' ? 'Session saved' : 'Session created');
      const target = destination === 'print' ? `/mix-calculator/${saved.id}/print` : `/mix-calculator/${saved.id}`;
      await goto(target);
    } catch (error) {
      toast.dismiss(tid);
      toast.error(error instanceof Error ? error.message : 'Unable to save the mix calculator session.');
      formError = error instanceof Error ? error.message : 'Unable to save the mix calculator session.';
      saveLoading = false;
    }
  }
</script>

{#if !canEdit && !initialSession}
  <section class="locked-card">
    <p class="eyebrow">Mix Calculator</p>
    <h2>Edit access is required to create a new session.</h2>
    <p>View-only users can open saved sessions from history, but cannot create or update production calculations.</p>
    {#if featureFlags.mixCalculatorSessionHistory}
      <a class="secondary-button" href="/mix-calculator">Back to session history</a>
    {/if}
  </section>
{:else}
  {#if featureFlags.mixCalculatorSessionHistory || initialSession}
    <section class="page-actions">
      {#if featureFlags.mixCalculatorSessionHistory}
        <a class="secondary-button" href="/mix-calculator">Session history</a>
      {/if}
      {#if initialSession}
        <a class="secondary-button" href={`/mix-calculator/${initialSession.id}/print`}>Printable view</a>
        <button class="secondary-button" type="button" onclick={() => downloadSessionPdf(initialSession.id)}>Download PDF</button>
      {/if}
    </section>
  {/if}

  <section class="editor-grid">
    <article class="form-card">
      <div class="section-header">
        <div>
          <h3>Session Inputs</h3>
          <p>Batch size drives the scale factor. Total bags are derived from the selected product unit size.</p>
        </div>
        {#if selectedProduct}
          <div class="product-pill">
            <strong>{selectedProduct.unit_size_kg}kg</strong>
            <span>{selectedProduct.unit_of_measure}</span>
          </div>
        {/if}
      </div>

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

      <div class="field-grid">
        <label>
          <span>Mix date</span>
          <input bind:value={mixDate} disabled={!canEdit} type="date" />
        </label>

        <label>
          <span>Client</span>
          <select bind:value={clientName} disabled={!canEdit}>
            <option value="">Select a client</option>
            {#each availableClients as client}
              <option value={client}>{client}</option>
            {/each}
          </select>
        </label>

        <label class="full-width">
          <span>Product</span>
          <select bind:value={productId} disabled={!canEdit || !filteredProducts.length}>
            <option value={0}>Select a product</option>
            {#each filteredProducts as product}
              <option value={product.product_id}>
                {product.product_name} · {product.mix_name} · {product.unit_of_measure}
              </option>
            {/each}
          </select>
        </label>

        <label>
          <span>Batch size (kg)</span>
          <input bind:value={batchSizeKg} disabled={!canEdit} inputmode="decimal" min="0" placeholder="560" type="number" />
        </label>

        <label>
          <span>Prepared by</span>
          <input bind:value={preparedByName} disabled={!canEdit} placeholder="Staff name" type="text" />
        </label>

        <label class="full-width">
          <span>Notes</span>
          <textarea bind:value={notes} disabled={!canEdit} placeholder="Optional production notes or shift context" rows="4"></textarea>
        </label>
      </div>

      {#if canEdit && selectedProduct}
        <div class="calculation-note">
          <strong>Source mix</strong>
          <span>{selectedProduct.mix_name} totals {formatNumber(selectedProduct.mix_total_kg, 2)}kg. Scale factor = batch size / source mix total.</span>
        </div>
      {/if}

      {#if canEdit}
        <div class="action-row">
          <button class="primary-button" disabled={previewLoading || saveLoading} type="button" onclick={calculatePreview}>
            <span class="button-icon" style="--button-icon-url: url('/icons/calculator.svg');" aria-hidden="true"></span>
            <span>{previewLoading ? 'Calculating...' : 'Calculate mix'}</span>
          </button>

          {#if featureFlags.mixCalculatorSessionSave}
            <button class="secondary-button" disabled={saveLoading || previewLoading} type="button" onclick={() => saveSession(isExistingSession ? 'update' : 'create')}>
              {saveLoading ? 'Saving...' : isExistingSession ? 'Save changes' : 'Save session'}
            </button>

            <button class="secondary-button" disabled={saveLoading || previewLoading} type="button" onclick={() => saveSession(isExistingSession ? 'update' : 'create', 'print')}>
              <span class="button-icon" style="--button-icon-url: url('/icons/print.svg');" aria-hidden="true"></span>
              <span>{saveLoading ? 'Saving...' : 'Save & print'}</span>
            </button>

            {#if initialSession}
              <button class="secondary-button" disabled={saveLoading || previewLoading} type="button" onclick={() => saveSession('create')}>
                Save as new
              </button>
            {/if}
          {:else}
            <button class="secondary-button" disabled={previewLoading || saveLoading || !preview} type="button" onclick={openPreviewModal}>
              <span>Preview</span>
            </button>

            <button class="secondary-button" disabled={previewLoading || saveLoading || !preview} type="button" onclick={printPreview}>
              <span class="button-icon" style="--button-icon-url: url('/icons/print.svg');" aria-hidden="true"></span>
              <span>Print</span>
            </button>
          {/if}

          <button class="secondary-button" disabled={previewLoading || saveLoading} type="button" onclick={clearForm}>
            <span class="button-icon" style="--button-icon-url: url('/icons/trash.svg');" aria-hidden="true"></span>
            <span>Clear</span>
          </button>
        </div>
      {/if}
    </article>

    <MixCalculatorResultsPanel
      preview={preview}
      sessionNumber={initialSession?.session_number ?? null}
    />
  </section>

  {#if preview}
    {#if previewModalOpen}
      <MixCalculatorPreviewModal
        preview={preview}
        sessionId={initialSession?.id ?? null}
        onClose={closePreviewModal}
        onPrint={printPreview}
        onDownloadPdf={downloadSessionPdf}
      />
    {/if}

    <section class="print-only" aria-hidden="true">
      <MixCalculatorPrintDocument session={preview} />
    </section>
  {/if}
{/if}

<style>
  h2,
  h3,
  p {
    margin: 0;
  }

  .eyebrow {
    color: #7d8d84;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .page-actions,
  .editor-grid {
    margin-bottom: 1.2rem;
  }

  .page-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    flex-wrap: wrap;
  }

  .section-header p,
  .calculation-note span {
    color: var(--muted);
  }

  .action-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
  }

  .editor-grid {
    display: grid;
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
    gap: 1rem;
  }

  .form-card,
  .locked-card {
    border: 1px solid var(--line);
    border-radius: 1.3rem;
    background: var(--panel);
    box-shadow: var(--shadow);
  }

  .form-card,
  .locked-card {
    padding: 1.2rem;
  }

  .locked-card {
    max-width: 42rem;
  }

  .locked-card h2 {
    margin: 0.35rem 0 0.45rem;
    font-size: clamp(1.7rem, 3vw, 2.1rem);
  }

  .section-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1rem;
  }

  .section-header h3 {
    font-size: 1.15rem;
    font-weight: 700;
  }

  .product-pill {
    display: grid;
    gap: 0.14rem;
    padding: 0.72rem 0.82rem;
    border: 1px solid var(--line);
    border-radius: 0.92rem;
    background: var(--panel-soft);
  }

  .product-pill span {
    color: var(--muted);
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }

  .field-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.9rem;
  }

  .field-grid label {
    display: grid;
    gap: 0.38rem;
  }

  .field-grid label span {
    font-size: 0.88rem;
    font-weight: 600;
  }

  .full-width {
    grid-column: 1 / -1;
  }

  input,
  select,
  textarea {
    width: 100%;
    padding: 0.78rem 0.82rem;
    border: 1px solid var(--line-strong);
    border-radius: 0.88rem;
    background: #fff;
    color: var(--text);
  }

  textarea {
    resize: vertical;
  }

  .calculation-note {
    display: grid;
    gap: 0.2rem;
    margin-top: 1rem;
    padding: 0.92rem;
    border-radius: 1rem;
    background: var(--panel-soft);
  }

  .message {
    margin-bottom: 0.85rem;
    padding: 0.75rem 0.85rem;
    border-radius: 0.88rem;
    font-size: 0.9rem;
  }

  .message.error {
    background: #fff1f0;
    color: #b2463f;
  }

  .action-row {
    margin-top: 1rem;
  }

  .primary-button,
  .secondary-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.78rem 0.96rem;
    border-radius: 0.9rem;
    border: 1px solid var(--line-strong);
    font-weight: 600;
    cursor: pointer;
    transition:
      transform 140ms ease,
      box-shadow 140ms ease,
      background-color 140ms ease,
      border-color 140ms ease;
  }

  .primary-button {
    border: none;
    background: var(--color-brand);
    color: #fff;
  }

  .secondary-button {
    background: #fff;
    color: #304038;
  }

  .primary-button:hover:not(:disabled),
  .secondary-button:hover:not(:disabled) {
    transform: translateY(-1px);
  }

  .primary-button:hover:not(:disabled) {
    box-shadow: none;
    filter: brightness(1.04);
  }

  .secondary-button:hover:not(:disabled) {
    border-color: #9fb0a6;
    background: #f6faf7;
    box-shadow: none;
  }

  .button-icon {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    background-color: currentColor;
    -webkit-mask: var(--button-icon-url) center / contain no-repeat;
    mask: var(--button-icon-url) center / contain no-repeat;
    flex-shrink: 0;
  }

  button:disabled {
    cursor: wait;
    opacity: 0.7;
  }

  @media (max-width: 980px) {
    .editor-grid {
      grid-template-columns: 1fr;
    }
  }

  @media (max-width: 720px) {
    .section-header {
      flex-direction: column;
    }

    .field-grid {
      grid-template-columns: 1fr;
    }
  }

  .print-only {
    display: none;
  }

  @media print {
    :global(body) {
      background: #fff !important;
      margin: 0 !important;
    }

    :global(body *) {
      visibility: hidden !important;
    }

    .print-only,
    .print-only :global(*) {
      visibility: visible !important;
    }

    .print-only {
      display: block;
      position: absolute;
      inset: 0;
      padding: 0;
      background: #fff;
      color: #1a2421;
      font-family: inherit;
    }
  }
</style>
