<script lang="ts">
  import CategorySection from './CategorySection.svelte';

  type Ingredient = { id: string; name: string; isStaple: boolean };
  type Category = { id: string; name: string; ingredients: Ingredient[] };

  let { categories, context }: {
    categories: Category[];
    context: 'onboarding' | 'settings';
  } = $props();

  let stapleState = $state<Record<string, boolean>>({});
  let errorMessage = $state('');

  $effect(() => {
    const initial: Record<string, boolean> = {};
    for (const cat of categories) {
      for (const ing of cat.ingredients) {
        initial[ing.id] = ing.isStaple;
      }
    }
    stapleState = initial;
  });

  function debounce<T extends (...args: any[]) => void>(fn: T, ms: number): T {
    let timer: ReturnType<typeof setTimeout> | null = null;
    return ((...args: any[]) => {
      if (timer) clearTimeout(timer);
      timer = setTimeout(() => fn(...args), ms);
    }) as T;
  }

  const debouncedPatchers: Record<string, (id: string, value: boolean) => void> = {};

  function getPatcher(id: string) {
    if (!debouncedPatchers[id]) {
      debouncedPatchers[id] = debounce(async (ingredientId: string, value: boolean) => {
        const previous = !value;
        const res = await fetch(`/household/staples`, {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ id: ingredientId, isStaple: value })
        });
        if (!res.ok) {
          stapleState[ingredientId] = previous;
          errorMessage = 'Vorrat konnte nicht gespeichert werden.';
        }
      }, 300);
    }
    return debouncedPatchers[id];
  }

  function handleToggle(ingredientId: string, newValue: boolean) {
    errorMessage = '';
    stapleState[ingredientId] = newValue;
    getPatcher(ingredientId)(ingredientId, newValue);
  }
</script>

<div>
  {#if errorMessage}
    <p class="mb-[12px] text-[12px] text-[var(--color-error)]">{errorMessage}</p>
  {/if}

  <div
    data-testid="category-grid"
    class="grid grid-cols-1 gap-[24px_32px] {context === 'settings' ? 'md:grid-cols-3' : 'md:grid-cols-2'}"
  >
    {#each categories as category (category.id)}
      <CategorySection
        name={category.name}
        ingredients={category.ingredients.map(ing => ({
          ...ing,
          isStaple: stapleState[ing.id] ?? ing.isStaple
        }))}
        onToggle={handleToggle}
      />
    {/each}
  </div>
</div>
