<script lang="ts">
  import { onMount, tick } from 'svelte';
  import { CookingPot, Link, Plus, ChevronDown, Pencil } from 'lucide-svelte';
  import { goto } from '$app/navigation';
  import { alertAction } from '$lib/client/confirm.svelte';
  import { requireOnline } from '$lib/client/require-online';
  import type { PageData } from './$types';

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

  let filter = $state('');
  let importUrl = $state('');
  let menuOpen = $state(false);
  let importOpen = $state(false);
  let creatingBlank = $state(false);
  let menuWrap: HTMLElement | undefined = $state();
  let importInput: HTMLInputElement | undefined = $state();

  function toggleMenu() {
    menuOpen = !menuOpen;
  }

  async function openImport() {
    menuOpen = false;
    importOpen = true;
    await tick();
    importInput?.focus();
  }

  function closeImport() {
    importOpen = false;
    importUrl = '';
  }

  function submitImport(e: SubmitEvent) {
    e.preventDefault();
    const url = importUrl.trim();
    if (!url) return;
    if (!requireOnline('Der URL-Import')) return;
    importOpen = false;
    goto(`/preview?url=${encodeURIComponent(url)}`);
  }

  async function createBlank() {
    if (creatingBlank) return;
    if (!requireOnline('Das Anlegen')) return;
    menuOpen = false;
    creatingBlank = true;
    try {
      const res = await fetch('/api/recipes/blank', { method: 'POST' });
      if (!res.ok) {
        await alertAction({
          title: 'Anlegen fehlgeschlagen',
          message: `HTTP ${res.status}`
        });
        return;
      }
      const body = await res.json();
      goto(`/recipes/${body.id}?edit=1`);
    } finally {
      creatingBlank = false;
    }
  }

  function onDocClick(e: MouseEvent) {
    if (!menuOpen) return;
    if (menuWrap && !menuWrap.contains(e.target as Node)) menuOpen = false;
  }

  function onKey(e: KeyboardEvent) {
    if (e.key === 'Escape') {
      if (importOpen) closeImport();
      else if (menuOpen) menuOpen = false;
    }
  }

  onMount(() => {
    document.addEventListener('click', onDocClick);
    document.addEventListener('keydown', onKey);
    return () => {
      document.removeEventListener('click', onDocClick);
      document.removeEventListener('keydown', onKey);
    };
  });

  // Umlaute und Diakritika auf Basis-Buchstaben normalisieren, damit
  // "apfel" auch "Äpfel" findet und "A/Ä/O/Ö/U/Ü" im gleichen Section-Header landen.
  function normalize(s: string): string {
    return s
      .normalize('NFD')
      .replace(/[\u0300-\u036f]/g, '')
      .toLowerCase();
  }

  function sectionKey(title: string): string {
    const first = normalize(title.trim()).charAt(0).toUpperCase();
    return /[A-Z]/.test(first) ? first : '#';
  }

  const collator = new Intl.Collator('de', { sensitivity: 'base', numeric: true });

  type Hit = PageData['recipes'][number];
  type Section = { letter: string; recipes: Hit[] };

  const sections = $derived.by<Section[]>(() => {
    const f = normalize(filter.trim());
    const filtered = f
      ? data.recipes.filter((r) => normalize(r.title).includes(f))
      : data.recipes;
    const sorted = [...filtered].sort((a, b) => collator.compare(a.title, b.title));
    const groups = new Map<string, Hit[]>();
    for (const r of sorted) {
      const key = sectionKey(r.title);
      const arr = groups.get(key);
      if (arr) arr.push(r);
      else groups.set(key, [r]);
    }
    // '#' am Ende, sonst alphabetisch
    return [...groups.entries()]
      .sort(([a], [b]) => {
        if (a === '#') return 1;
        if (b === '#') return -1;
        return collator.compare(a, b);
      })
      .map(([letter, recipes]) => ({ letter, recipes }));
  });

  const letters = $derived(sections.map((s) => s.letter));

  function scrollToLetter(letter: string) {
    const el = document.getElementById(`sect-${letter}`);
    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }
</script>

<header class="head">
  <div class="head-top">
    <div class="head-titles">
      <h1>Register</h1>
      <p class="sub">{data.recipes.length} Rezepte insgesamt</p>
    </div>
    <div class="add-menu" bind:this={menuWrap}>
      <button
        type="button"
        class="add-btn"
        onclick={toggleMenu}
        aria-haspopup="menu"
        aria-expanded={menuOpen}
      >
        <Plus size={16} strokeWidth={2.2} />
        <span>Rezept hinzufügen</span>
        <ChevronDown size={14} strokeWidth={2.2} />
      </button>
      {#if menuOpen}
        <div class="menu" role="menu">
          <button type="button" role="menuitem" class="menu-item" onclick={openImport}>
            <Link size={16} strokeWidth={2} />
            <div class="menu-text">
              <div class="menu-title">Von URL importieren</div>
              <div class="menu-desc">Rezept aus einer Website ziehen</div>
            </div>
          </button>
          <button
            type="button"
            role="menuitem"
            class="menu-item"
            onclick={createBlank}
            disabled={creatingBlank}
          >
            <Pencil size={16} strokeWidth={2} />
            <div class="menu-text">
              <div class="menu-title">Leeres Rezept</div>
              <div class="menu-desc">Manuell ausfüllen</div>
            </div>
          </button>
        </div>
      {/if}
    </div>
  </div>
</header>

{#if importOpen}
  <div
    class="modal-backdrop"
    role="presentation"
    onclick={(e) => {
      if (e.target === e.currentTarget) closeImport();
    }}
  >
    <div
      class="modal"
      role="dialog"
      aria-modal="true"
      aria-labelledby="import-title"
      tabindex="-1"
    >
      <h2 id="import-title">Rezept-URL importieren</h2>
      <form onsubmit={submitImport}>
        <input
          bind:this={importInput}
          type="url"
          bind:value={importUrl}
          placeholder="https://…"
          aria-label="Rezept-URL"
          required
        />
        <div class="modal-actions">
          <button type="button" class="btn" onclick={closeImport}>Abbrechen</button>
          <button type="submit" class="btn primary" disabled={!importUrl.trim()}>
            Weiter
          </button>
        </div>
      </form>
    </div>
  </div>
{/if}

<div class="filter-wrap">
  <input
    type="search"
    bind:value={filter}
    placeholder="Rezepte filtern…"
    autocomplete="off"
    inputmode="search"
    aria-label="Rezepte filtern"
  />
</div>

{#if letters.length > 1 && !filter.trim()}
  <nav class="letters" aria-label="Buchstaben-Navigation">
    {#each letters as l}
      <button class="letter-chip" onclick={() => scrollToLetter(l)}>{l}</button>
    {/each}
  </nav>
{/if}

{#if sections.length === 0}
  <p class="empty">Nichts passt zu „{filter}".</p>
{:else}
  {#each sections as sect (sect.letter)}
    <section class="sect" id={`sect-${sect.letter}`}>
      <h2 class="letter">{sect.letter}</h2>
      <ul class="list">
        {#each sect.recipes as r (r.id)}
          <li>
            <a class="item" href={`/recipes/${r.id}`}>
              {#if r.image_path}
                <img src={`/images/${r.image_path}`} alt="" loading="lazy" />
              {:else}
                <div class="placeholder"><CookingPot size={22} /></div>
              {/if}
              <div class="body">
                <div class="title">{r.title}</div>
                <div class="meta">
                  {#if r.source_domain}<span>{r.source_domain}</span>{/if}
                  {#if r.avg_stars !== null}<span>· ★ {r.avg_stars.toFixed(1)}</span>{/if}
                </div>
              </div>
            </a>
          </li>
        {/each}
      </ul>
    </section>
  {/each}
{/if}

<style>
  .head {
    padding: 1.25rem 0 0.5rem;
  }
  .head-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
  }
  .head-titles {
    min-width: 0;
  }
  .head h1 {
    margin: 0;
    font-size: 1.6rem;
    color: #2b6a3d;
  }
  .sub {
    margin: 0.2rem 0 0;
    color: #666;
    font-size: 0.9rem;
  }
  .add-menu {
    position: relative;
    flex-shrink: 0;
  }
  .add-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.55rem 0.9rem;
    background: #2b6a3d;
    color: white;
    border: 0;
    border-radius: 10px;
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    min-height: 40px;
  }
  .add-btn:hover {
    background: #235532;
  }
  .menu {
    position: absolute;
    top: calc(100% + 0.35rem);
    right: 0;
    min-width: 260px;
    background: white;
    border: 1px solid #e4eae7;
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    padding: 0.3rem;
    z-index: 20;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
  }
  .menu-item {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.6rem 0.75rem;
    background: transparent;
    border: 0;
    border-radius: 8px;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    color: #1a1a1a;
    width: 100%;
  }
  .menu-item:hover:not(:disabled) {
    background: #f4f8f5;
  }
  .menu-item:disabled {
    opacity: 0.55;
    cursor: progress;
  }
  .menu-item :global(svg) {
    color: #2b6a3d;
    flex-shrink: 0;
  }
  .menu-text {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
  }
  .menu-title {
    font-weight: 600;
    font-size: 0.95rem;
  }
  .menu-desc {
    color: #888;
    font-size: 0.8rem;
  }
  .modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(20, 30, 25, 0.45);
    display: grid;
    place-items: center;
    z-index: 100;
    padding: 1rem;
  }
  .modal {
    background: white;
    border-radius: 14px;
    padding: 1.1rem 1.1rem 1rem;
    width: min(440px, 100%);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.2);
  }
  .modal h2 {
    margin: 0 0 0.75rem;
    font-size: 1.05rem;
    color: #2b6a3d;
  }
  .modal input {
    width: 100%;
    padding: 0.7rem 0.85rem;
    border: 1px solid #cfd9d1;
    border-radius: 10px;
    font-size: 1rem;
    min-height: 44px;
    font-family: inherit;
    box-sizing: border-box;
  }
  .modal input:focus {
    outline: 2px solid #2b6a3d;
    outline-offset: 1px;
  }
  .modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 0.85rem;
  }
  .modal .btn {
    padding: 0.6rem 1rem;
    min-height: 42px;
    border: 1px solid #cfd9d1;
    background: white;
    border-radius: 10px;
    cursor: pointer;
    font-size: 0.95rem;
    font-family: inherit;
  }
  .modal .btn:hover:not(:disabled) {
    background: #f4f8f5;
  }
  .modal .btn.primary {
    background: #2b6a3d;
    color: white;
    border: 0;
  }
  .modal .btn.primary:hover:not(:disabled) {
    background: #235532;
  }
  .modal .btn.primary:disabled {
    opacity: 0.55;
    cursor: not-allowed;
  }
  .filter-wrap {
    position: sticky;
    top: 57px;
    z-index: 5;
    background: #f8faf8;
    padding: 0.75rem 0 0.5rem;
  }
  .filter-wrap input {
    width: 100%;
    padding: 0.6rem 0.9rem;
    font-size: 0.95rem;
    border: 1px solid #cfd9d1;
    border-radius: var(--pill-radius);
    background: white;
    min-height: 44px;
  }
  .filter-wrap input:focus {
    outline: 2px solid #2b6a3d;
    outline-offset: 1px;
  }
  .letters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    padding: 0.25rem 0 0.75rem;
  }
  .letter-chip {
    min-width: 32px;
    min-height: 32px;
    padding: 0 0.4rem;
    border: 1px solid #e4eae7;
    background: white;
    border-radius: 8px;
    color: #2b6a3d;
    font-weight: 600;
    font-size: 0.85rem;
    cursor: pointer;
  }
  .letter-chip:hover {
    background: #eaf4ed;
  }
  .empty {
    color: #888;
    text-align: center;
    padding: 2rem 0;
  }
  .sect {
    margin-top: 0.75rem;
    scroll-margin-top: 115px;
  }
  .sect h2.letter {
    margin: 0;
    padding: 0.35rem 0.1rem;
    font-size: 0.95rem;
    color: #2b6a3d;
    border-bottom: 1px solid #e4eae7;
    font-weight: 700;
  }
  .list {
    list-style: none;
    padding: 0;
    margin: 0;
  }
  .item {
    display: flex;
    gap: 0.7rem;
    padding: 0.55rem 0.25rem;
    text-decoration: none;
    color: inherit;
    border-bottom: 1px solid #f0f3f1;
    min-height: 56px;
    align-items: center;
  }
  .item:hover {
    background: #f4f8f5;
  }
  .item img,
  .placeholder {
    width: 44px;
    height: 44px;
    object-fit: cover;
    border-radius: 8px;
    background: #eef3ef;
    display: grid;
    place-items: center;
    color: #8fb097;
    flex-shrink: 0;
  }
  .body {
    min-width: 0;
    flex: 1;
  }
  .title {
    font-weight: 600;
    font-size: 0.98rem;
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .meta {
    font-size: 0.8rem;
    color: #888;
    display: flex;
    gap: 0.25rem;
    margin-top: 0.1rem;
  }
</style>
