<script lang="ts">
  import { enhance } from '$app/forms';
  import type { PageData, ActionData } from './$types';

  let { data, form }: { data: PageData; form: ActionData } = $props();

  let resizeMap = $state<Record<string, number>>({});
  let previewMap = $state<Record<string, string>>({});
  let processing = $state<Record<string, boolean>>({});

  async function resizeAndSet(slot: string, inputEl: HTMLInputElement) {
    const file = inputEl.files?.[0];
    if (!file) return;
    const max = resizeMap[slot] ?? 0;
    if (!max || file.type === 'image/svg+xml') {
      previewMap[slot] = URL.createObjectURL(file);
      return;
    }
    processing[slot] = true;
    try {
      const resized = await resizeImageFile(file, max);
      const dt = new DataTransfer();
      dt.items.add(resized);
      inputEl.files = dt.files;
      previewMap[slot] = URL.createObjectURL(resized);
    } finally {
      processing[slot] = false;
    }
  }

  async function resizeImageFile(file: File, maxDim: number): Promise<File> {
    const bitmap = await createImageBitmap(file);
    const ratio = Math.min(1, maxDim / Math.max(bitmap.width, bitmap.height));
    const w = Math.round(bitmap.width * ratio);
    const h = Math.round(bitmap.height * ratio);
    const canvas = document.createElement('canvas');
    canvas.width = w;
    canvas.height = h;
    const ctx = canvas.getContext('2d');
    if (!ctx) return file;
    ctx.drawImage(bitmap, 0, 0, w, h);
    const type = file.type === 'image/png' ? 'image/png' : 'image/jpeg';
    const quality = type === 'image/jpeg' ? 0.88 : undefined;
    const blob: Blob = await new Promise((resolve) =>
      canvas.toBlob((b) => resolve(b as Blob), type, quality)
    );
    const ext = type === 'image/png' ? 'png' : 'jpg';
    return new File([blob], `${file.name.replace(/\.[^.]+$/, '')}.${ext}`, { type });
  }
</script>

<svelte:head><title>Immagini — Admin</title></svelte:head>

<header class="page-head">
  <p class="kicker">Media</p>
  <h1>Immagini</h1>
  <p>Sostituisci, ridimensiona o ripristina ogni immagine presente sulla landing page. Il ridimensionamento avviene in browser prima dell'upload, così riduci banda e peso.</p>
</header>

{#if form?.success}
  <div class="alert-row">
    {form.altOnly ? 'Alt text aggiornato' : form.reset ? 'Immagine ripristinata al default' : 'Immagine sostituita con successo'} — slot <code>{form.slot}</code>.
  </div>
{/if}
{#if form?.error}
  <div class="alert-row err">{form.error}</div>
{/if}

<div class="image-grid">
  {#each Object.values(data.images) as img}
    <div class="image-card">
      <header>
        <div>
          <div class="slot-label">{img.label}</div>
          <div class="slot-id">{img.id}</div>
        </div>
      </header>
      <div class="preview">
        <img src={previewMap[img.id] ?? img.src} alt={img.alt} />
      </div>

      <form
        method="POST"
        action="?/upload"
        enctype="multipart/form-data"
        use:enhance={() => {
          return async ({ update }) => {
            await update();
            previewMap[img.id] = '';
          };
        }}
      >
        <input type="hidden" name="slot" value={img.id} />
        <div class="field">
          <label for="alt-{img.id}">Alt text</label>
          <input id="alt-{img.id}" name="alt" type="text" value={img.alt} />
        </div>
        <div class="grid-2">
          <div class="field">
            <label for="file-{img.id}">Sostituisci file</label>
            <input
              id="file-{img.id}"
              name="file"
              type="file"
              accept="image/png,image/jpeg,image/webp,image/gif,image/svg+xml"
              onchange={(e) => resizeAndSet(img.id, e.currentTarget as HTMLInputElement)}
            />
          </div>
          <div class="field">
            <label for="resize-{img.id}">Max lato (px)</label>
            <select id="resize-{img.id}" bind:value={resizeMap[img.id]}>
              <option value={0}>Originale</option>
              <option value={480}>480 px</option>
              <option value={800}>800 px</option>
              <option value={1200}>1200 px</option>
              <option value={1920}>1920 px</option>
            </select>
            <small>Applicato al prossimo file scelto.</small>
          </div>
        </div>
        <div class="actions">
          <button type="submit" class="btn" disabled={processing[img.id]}>
            <span class="material-symbols-outlined" aria-hidden="true">upload</span>
            {processing[img.id] ? 'Ridimensiono…' : 'Salva'}
          </button>
        </div>
      </form>

      <form method="POST" action="?/reset" use:enhance style="margin-top:8px;">
        <input type="hidden" name="slot" value={img.id} />
        <button type="submit" class="btn btn-ghost btn-sm">
          <span class="material-symbols-outlined" aria-hidden="true">restore</span>
          Ripristina default
        </button>
      </form>
    </div>
  {/each}
</div>
