<script lang="ts">
  import { untrack } from 'svelte';
  import { ImagePlus, ImageOff } from 'lucide-svelte';
  import { confirmAction } from '$lib/client/confirm.svelte';
  import { asyncFetch } from '$lib/client/api-fetch-wrapper';
  import { requireOnline } from '$lib/client/require-online';

  type Props = {
    recipeId: number;
    imagePath: string | null;
    onchange: (path: string | null) => void;
  };

  let { recipeId, imagePath: initial, onchange }: Props = $props();

  let imagePath = $state<string | null>(untrack(() => initial));
  let uploading = $state(false);
  let fileInput: HTMLInputElement | null = $state(null);

  const imageSrc = $derived(
    imagePath === null
      ? null
      : /^https?:\/\//i.test(imagePath)
        ? imagePath
        : `/images/${imagePath}`
  );

  async function onFileChosen(event: Event) {
    const input = event.target as HTMLInputElement;
    const file = input.files?.[0];
    input.value = '';
    if (!file) return;
    if (!requireOnline('Der Bild-Upload')) return;
    uploading = true;
    try {
      const fd = new FormData();
      fd.append('file', file);
      const res = await asyncFetch(
        `/api/recipes/${recipeId}/image`,
        { method: 'POST', body: fd },
        'Upload fehlgeschlagen'
      );
      if (!res) return;
      const body = await res.json();
      imagePath = body.image_path;
      onchange(imagePath);
    } finally {
      uploading = false;
    }
  }

  async function removeImage() {
    if (imagePath === null) return;
    const ok = await confirmAction({
      title: 'Bild entfernen?',
      message: 'Das Rezept wird danach ohne Titelbild angezeigt.',
      confirmLabel: 'Entfernen',
      destructive: true
    });
    if (!ok) return;
    if (!requireOnline('Das Entfernen')) return;
    uploading = true;
    try {
      const res = await asyncFetch(
        `/api/recipes/${recipeId}/image`,
        { method: 'DELETE' },
        'Entfernen fehlgeschlagen'
      );
      if (!res) return;
      imagePath = null;
      onchange(null);
    } finally {
      uploading = false;
    }
  }
</script>

<div class="image-row">
  <div class="image-preview" class:empty={!imageSrc}>
    {#if imageSrc}
      <img src={imageSrc} alt="" />
    {:else}
      <span class="placeholder">Kein Bild</span>
    {/if}
  </div>
  <div class="image-actions">
    <button
      class="btn"
      type="button"
      onclick={() => fileInput?.click()}
      disabled={uploading}
    >
      <ImagePlus size={16} strokeWidth={2} />
      <span>{imagePath ? 'Bild ersetzen' : 'Bild hochladen'}</span>
    </button>
    {#if imagePath}
      <button class="btn ghost" type="button" onclick={removeImage} disabled={uploading}>
        <ImageOff size={16} strokeWidth={2} />
        <span>Entfernen</span>
      </button>
    {/if}
    {#if uploading}
      <span class="upload-status">Lade …</span>
    {/if}
  </div>
  <input
    bind:this={fileInput}
    type="file"
    accept="image/jpeg,image/png,image/webp,image/gif,image/avif"
    class="file-input"
    onchange={onFileChosen}
  />
</div>
<p class="image-hint">Max. 10 MB. JPG, PNG, WebP, GIF oder AVIF.</p>

<style>
  .image-row {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
    flex-wrap: wrap;
  }
  .image-preview {
    width: 160px;
    aspect-ratio: 16 / 10;
    border-radius: 10px;
    overflow: hidden;
    background: #eef3ef;
    border: 1px solid #e4eae7;
    flex-shrink: 0;
  }
  .image-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }
  .image-preview.empty {
    display: grid;
    place-items: center;
    color: #999;
    font-size: 0.85rem;
  }
  .image-preview .placeholder {
    padding: 0 0.5rem;
    text-align: center;
  }
  .image-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
  }
  .upload-status {
    color: #666;
    font-size: 0.9rem;
  }
  .file-input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
  }
  .image-hint {
    margin: 0.6rem 0 0;
    color: #888;
    font-size: 0.8rem;
  }
  .btn {
    padding: 0.55rem 0.85rem;
    border-radius: 10px;
    border: 1px solid #cfd9d1;
    background: white;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.9rem;
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
  }
  .btn.ghost {
    color: #666;
  }
  .btn:disabled {
    opacity: 0.6;
    cursor: progress;
  }
</style>
