<script>
  // FoodEditor — Food creation/editing form (spec §4.5).
  // Shared by scan/search/library flows. Accepts an optional `food` prop
  // for pre-filling from OFF or edit flows. When pre-filled, barcode is
  // read-only and source is set from the prefill.

  import { api } from '../lib/api.js'
  import { currentDate, addLogEntryToStore, appView, refreshDayData } from '../lib/stores.svelte.js'
  import { defaultQuantity, previewCalories, formatKcal, formatGrams } from '../lib/format.js'

  /** @type {import('../lib/api.js').FoodCreate | null} */
  let { food = null, mealId = null, onSaved = null, onCancel = null } = $props()

  // ── Meal component editing state (spec §4.7, TICKET-007) ───────────────
  // Active when `mealId` is set: edit the component list of an is_meal food.
  let meal = $state(null) // MealRead: components + computed_nutrition_per_meal
  let mealLoading = $state(false)
  let mealLoadError = $state(null)
  let components = $state([]) // [{ food_id, quantity, food }]
  let compSaving = $state(false)
  let compSaveError = $state(null)
  let compQuery = $state('')
  let compResults = $state([])
  let compSearching = $state(false)
  let compSearchError = $state(null)

  $effect(() => {
    if (mealId) loadMeal(mealId)
  })

  async function loadMeal(id) {
    mealLoading = true
    mealLoadError = null
    try {
      const m = await api.getFood(id)
      meal = m
      components = (m.components || []).map(c => ({
        food_id: c.food_id,
        quantity: c.quantity,
        food: c.food,
      }))
    } catch (e) {
      mealLoadError = e.message
    } finally {
      mealLoading = false
    }
  }

  async function searchComponents(e) {
    e.preventDefault()
    if (!compQuery.trim()) return
    compSearching = true
    compSearchError = null
    try {
      compResults = await api.searchFoods(compQuery.trim())
    } catch (err) {
      compSearchError = err.message
      compResults = []
    } finally {
      compSearching = false
    }
  }

  function addComponent(result) {
    if (components.some(c => c.food_id === result.id)) return
    components = [...components, {
      food_id: result.id,
      quantity: defaultQuantity(result),
      food: result,
    }]
    compResults = compResults.filter(r => r.id !== result.id)
  }

  function removeComponent(foodId) {
    components = components.filter(c => c.food_id !== foodId)
  }

  async function saveComponents() {
    compSaving = true
    compSaveError = null
    try {
      const payload = components.map(c => ({
        food_id: c.food_id,
        quantity: parseFloat(c.quantity),
      }))
      await api.updateMealComponents(mealId, payload)
      await refreshDayData() // meal nutrition changed → log/summary refresh
      appView.current = 'dashboard'
    } catch (e) {
      // Backend rejects cycles with 422 — surface the detail to the user
      compSaveError = e.message
    } finally {
      compSaving = false
    }
  }

  // ── Form state ──────────────────────────────────────────────────────────
  let name = $state('')
  let brand = $state('')
  let barcode = $state('')
  let source = $state('manual')
  let unitType = $state('weight')
  let caloriesPerUnit = $state('')
  let proteinPerUnit = $state('')
  let carbsPerUnit = $state('')
  let fatPerUnit = $state('')
  let servingSizeG = $state('')
  let servingName = $state('')
  let isPrefilled = $state(false)

  // ── Log-after-save state ────────────────────────────────────────────────
  let justSaved = $state(null) // { food: FoodRead } after save
  let logQuantity = $state(1)
  let logMealSlot = $state('')
  let logging = $state(false)
  let logError = $state(null)
  let liveKcal = $derived(justSaved ? Math.round(previewCalories(justSaved.food, logQuantity)) : 0)

  const SLOTS = ['', 'breakfast', 'lunch', 'dinner', 'snack']

  let saving = $state(false)
  let error = $state(null)

  // Edit mode: an existing food (with id) was passed in — update, don't create.
  let isEdit = $derived(!!food?.id)

  // ── Pre-fill from food prop ─────────────────────────────────────────────
  $effect(() => {
    if (food) {
      name = food.name || ''
      brand = food.brand || ''
      barcode = food.barcode || ''
      source = food.source || 'manual'
      unitType = food.unit_type || 'weight'
      caloriesPerUnit = food.calories_per_unit != null ? String(food.calories_per_unit) : ''
      proteinPerUnit = food.protein_per_unit != null ? String(food.protein_per_unit) : ''
      carbsPerUnit = food.carbs_per_unit != null ? String(food.carbs_per_unit) : ''
      fatPerUnit = food.fat_per_unit != null ? String(food.fat_per_unit) : ''
      servingSizeG = food.serving_size_g != null ? String(food.serving_size_g) : ''
      servingName = food.serving_name || ''
      isPrefilled = true
    }
  })

  function reset() {
    name = ''
    brand = ''
    barcode = ''
    source = 'manual'
    unitType = 'weight'
    caloriesPerUnit = ''
    proteinPerUnit = ''
    carbsPerUnit = ''
    fatPerUnit = ''
    servingSizeG = ''
    servingName = ''
    isPrefilled = false
    justSaved = null
    error = null
  }

  async function handleSubmit(e) {
    e.preventDefault()
    const cal = parseFloat(caloriesPerUnit)
    if (!name.trim()) { error = 'Name is required'; return }
    if (isNaN(cal) || cal <= 0) { error = 'Calories per unit is required'; return }

    saving = true
    error = null
    try {
      const payload = {
        name: name.trim(),
        brand: brand.trim() || null,
        unit_type: unitType,
        calories_per_unit: cal,
        protein_per_unit: proteinPerUnit ? parseFloat(proteinPerUnit) : null,
        carbs_per_unit: carbsPerUnit ? parseFloat(carbsPerUnit) : null,
        fat_per_unit: fatPerUnit ? parseFloat(fatPerUnit) : null,
        serving_size_g: servingSizeG ? parseFloat(servingSizeG) : null,
        serving_name: servingName.trim() || null,
        source,
        is_meal: food?.is_meal ?? false,
      }
      // Include barcode when present
      if (barcode.trim()) payload.barcode = barcode.trim()
      else payload.barcode = null

      if (isEdit) {
        const saved = await api.updateFood(food.id, payload)
        // Nutrition edits affect historical log rendering — refresh the day
        await refreshDayData()
        if (onSaved) onSaved(saved)
        else appView.current = 'dashboard'
        return
      }

      const saved = await api.createFood(payload)
      // After save, offer to log the new food
      justSaved = { food: saved }
      logQuantity = defaultQuantity(saved)
      logMealSlot = ''

      if (onSaved) onSaved(saved)
    } catch (e) {
      error = e.message
    } finally {
      saving = false
    }
  }

  async function confirmLog() {
    if (!justSaved || logQuantity <= 0) return
    logging = true
    logError = null
    try {
      const entry = await api.addLogEntry({
        food_id: justSaved.food.id,
        quantity: parseFloat(logQuantity),
        meal_slot: logMealSlot || null,
        date: currentDate.value,
      })
      await addLogEntryToStore(entry)
      reset()
      appView.current = 'dashboard'
    } catch (e) {
      logError = e.message
    } finally {
      logging = false
    }
  }

  function skipLog() {
    reset()
    appView.current = 'dashboard'
  }

  function goBack() {
    reset()
    if (onCancel) {
      onCancel()
    } else if (mealId) {
      appView.current = 'dashboard'
    } else if (onSaved) {
      // Came from scan flow with no cancel — go to dashboard
      appView.current = 'dashboard'
    } else {
      appView.current = 'addFood'
    }
  }
</script>

<div class="food-editor">
  <button type="button" class="back-btn" onclick={goBack}>
    ← Back
  </button>

  {#if mealId}
    <!-- Meal component editor (spec §4.7) -->
    <h3>Edit meal components{meal ? `: ${meal.name}` : ''}</h3>

    {#if mealLoading}
      <p>Loading meal…</p>
    {:else if mealLoadError}
      <p class="err" role="alert">{mealLoadError}</p>
    {:else if meal}
      <!-- Derived nutrition is read-only — the backend is the source of truth (§8.2 rule 2) -->
      {#if meal.computed_nutrition_per_meal}
        <p class="derived-nutrition">
          Per meal: {formatKcal(Math.round(meal.computed_nutrition_per_meal.calories ?? 0))}
          · P {formatGrams(meal.computed_nutrition_per_meal.protein_g ?? 0)}
          · C {formatGrams(meal.computed_nutrition_per_meal.carbs_g ?? 0)}
          · F {formatGrams(meal.computed_nutrition_per_meal.fat_g ?? 0)}
        </p>
      {/if}

      <ul class="component-edit-list">
        {#each components as comp (comp.food_id)}
          <li class="component-edit-item">
            <span class="comp-name">{comp.food?.name ?? `Food #${comp.food_id}`}</span>
            <input
              type="number"
              step="any"
              min="0.1"
              bind:value={comp.quantity}
              class="qty-input"
            />
            <span class="comp-unit">{comp.food?.unit_type === 'count' ? '×' : 'g'}</span>
            <button type="button" class="icon-btn" title="Remove" onclick={() => removeComponent(comp.food_id)}>✕</button>
          </li>
        {:else}
          <li class="component-edit-item empty">No components yet</li>
        {/each}
      </ul>

      <form class="comp-search" onsubmit={searchComponents}>
        <input type="text" bind:value={compQuery} placeholder="Search foods to add…" />
        <button type="submit" disabled={compSearching || !compQuery.trim()}>
          {compSearching ? '…' : 'Search'}
        </button>
      </form>
      {#if compSearchError}<p class="err" role="alert">{compSearchError}</p>{/if}
      {#if compResults.length > 0}
        <ul class="comp-results">
          {#each compResults as r (r.id)}
            <li class="comp-result">
              <span>{r.name}{r.brand ? ` (${r.brand})` : ''}{r.is_meal ? ' [meal]' : ''}</span>
              <button type="button" class="secondary" onclick={() => addComponent(r)}>Add</button>
            </li>
          {/each}
        </ul>
      {/if}

      {#if compSaveError}<p class="err" role="alert">{compSaveError}</p>{/if}

      <div class="form-actions">
        <button
          type="button"
          onclick={saveComponents}
          disabled={compSaving || components.length === 0 || components.some(c => !(parseFloat(c.quantity) > 0))}
        >
          {compSaving ? 'Saving…' : 'Save components'}
        </button>
        <button type="button" class="secondary" onclick={goBack} disabled={compSaving}>Cancel</button>
      </div>
    {/if}

  {:else if justSaved}
    <!-- Post-save: offer to log the new food -->
    <h3>"{justSaved.food.name}" saved</h3>

    <div class="log-form">
      <p class="brand">{justSaved.food.brand}</p>

      <label>
        Quantity
        <input
          type="number"
          step="any"
          min="0.1"
          bind:value={logQuantity}
          class="qty-input"
        />
        {justSaved.food.unit_type === 'count' ? 'items' : 'g'}
      </label>
      <p class="preview-kcal">= {formatKcal(liveKcal)}</p>

      <label>
        Meal slot
        <select bind:value={logMealSlot}>
          {#each SLOTS as s}
            <option value={s}>{s || '(none)'}</option>
          {/each}
        </select>
      </label>

      {#if logError}<p class="err" role="alert">{logError}</p>{/if}

      <div class="log-actions">
        <button type="button" onclick={confirmLog} disabled={logging || logQuantity <= 0}>
          {logging ? 'Logging…' : 'Log it'}
        </button>
        <button type="button" class="secondary" onclick={skipLog} disabled={logging}>
          Skip
        </button>
      </div>
    </div>

  {:else}
    <!-- Creation/edit form -->
    <h3>{isEdit ? 'Edit food' : isPrefilled ? 'Confirm & edit food' : 'Create food'}</h3>

    <form onsubmit={handleSubmit}>
      <label>
        Name <span class="required">*</span>
        <input type="text" bind:value={name} placeholder="e.g. Oatmeal" required />
      </label>

      <label>
        Brand
        <input type="text" bind:value={brand} placeholder="Optional" />
      </label>

      <label>
        Barcode
        <input
          type="text"
          bind:value={barcode}
          placeholder={isPrefilled ? '' : 'Optional'}
          disabled={isPrefilled}
          class:barcode-ro={isPrefilled}
        />
      </label>

      {#if isPrefilled}
        <p class="source-badge">Source: {source}</p>
      {/if}

      <fieldset>
        <legend>Unit type</legend>
        <label class="radio-label">
          <input type="radio" name="unitType" value="weight" bind:group={unitType} disabled={isPrefilled} />
          Weight (nutrition per 100g)
        </label>
        <label class="radio-label">
          <input type="radio" name="unitType" value="count" bind:group={unitType} disabled={isPrefilled} />
          Count (nutrition per item)
        </label>
      </fieldset>

      <label>
        Calories per {unitType === 'weight' ? '100g' : 'item'} <span class="required">*</span>
        <input type="number" step="any" min="0.01" bind:value={caloriesPerUnit} placeholder="e.g. 350" required />
      </label>

      <fieldset>
        <legend>Macros (optional, per {unitType === 'weight' ? '100g' : 'item'})</legend>
        <div class="macro-grid">
          <label>
            Protein
            <input type="number" step="any" min="0" bind:value={proteinPerUnit} placeholder="g" />
          </label>
          <label>
            Carbs
            <input type="number" step="any" min="0" bind:value={carbsPerUnit} placeholder="g" />
          </label>
          <label>
            Fat
            <input type="number" step="any" min="0" bind:value={fatPerUnit} placeholder="g" />
          </label>
        </div>
      </fieldset>

      {#if unitType === 'weight'}
        <fieldset>
          <legend>Serving info (optional)</legend>
          <label>
            Serving size (g)
            <input type="number" step="any" min="0.1" bind:value={servingSizeG} placeholder="e.g. 40" />
          </label>
          <label>
            Serving name
            <input type="text" bind:value={servingName} placeholder='e.g. "1 scoop (40g)"' />
          </label>
        </fieldset>
      {/if}

      {#if error}<p class="err" role="alert">{error}</p>{/if}

      <div class="form-actions">
        <button type="submit" disabled={saving}>
          {saving ? 'Saving…' : isEdit ? 'Save changes' : 'Save food'}
        </button>
        <button type="button" class="secondary" onclick={goBack} disabled={saving}>
          Cancel
        </button>
      </div>
    </form>
  {/if}
</div>

<style>
  .food-editor { }

  .back-btn {
    background: none;
    border: none;
    color: var(--link, #2563eb);
    cursor: pointer;
    font: inherit;
    font-size: 0.9rem;
    padding: 0;
    margin-bottom: 0.75rem;
  }

  h3 {
    margin: 0 0 1rem;
    font-size: 1.1rem;
  }

  form {
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
  }

  label {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    font-size: 0.9rem;
    color: var(--text, #111827);
  }

  .required { color: #dc2626; }

  input[type="text"],
  input[type="number"] {
    padding: 0.4rem 0.6rem;
    font: inherit;
    border: 1px solid var(--border, #d1d5db);
    border-radius: 0.35rem;
  }

  .barcode-ro {
    background: var(--bg-muted, #f3f4f6);
    color: var(--text-muted, #6b7280);
  }

  .source-badge {
    font-size: 0.8rem;
    color: var(--text-muted, #6b7280);
    background: var(--bg-muted, #f3f4f6);
    padding: 0.2rem 0.5rem;
    border-radius: 0.25rem;
    display: inline-block;
    text-transform: capitalize;
    margin: 0;
  }

  fieldset {
    border: 1px solid var(--border, #e5e7eb);
    border-radius: 0.35rem;
    padding: 0.6rem 0.8rem;
  }

  legend {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-muted, #6b7280);
    padding: 0 0.3rem;
  }

  .radio-label {
    flex-direction: row;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.3rem;
  }

  .macro-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 0.5rem;
  }

  .form-actions {
    display: flex;
    gap: 0.4rem;
    margin-top: 0.5rem;
  }

  .brand { color: var(--text-muted, #6b7280); font-size: 0.9rem; margin-top: -0.5rem; }

  .log-form {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
  }

  .log-form label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.9rem;
  }

  .qty-input {
    width: 5rem;
    padding: 0.3rem 0.4rem;
    font: inherit;
    border: 1px solid var(--border, #d1d5db);
    border-radius: 0.35rem;
  }

  .preview-kcal {
    font-weight: 600;
    font-size: 1rem;
    color: var(--text, #111827);
    margin: 0;
  }

  .log-actions { display: flex; gap: 0.4rem; margin-top: 0.5rem; }

  button {
    padding: 0.5rem 1rem;
    border: 1px solid var(--border, #d1d5db);
    border-radius: 0.35rem;
    background: var(--bg, #fff);
    cursor: pointer;
    font: inherit;
    font-size: 0.9rem;
  }
  button:disabled { opacity: 0.5; cursor: default; }
  button.secondary { background: var(--bg-muted, #f3f4f6); }

  .err { color: #dc2626; font-size: 0.85rem; }

  /* Meal component editor (§4.7) */
  .derived-nutrition {
    font-size: 0.9rem;
    color: var(--text-muted, #6b7280);
    background: var(--bg-muted, #f3f4f6);
    padding: 0.4rem 0.6rem;
    border-radius: 0.35rem;
    margin: 0 0 0.75rem;
  }
  .component-edit-list {
    list-style: none;
    margin: 0 0 0.75rem;
    padding: 0;
  }
  .component-edit-item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0;
    border-bottom: 1px solid var(--border, #e5e7eb);
    font-size: 0.9rem;
  }
  .component-edit-item .comp-name { flex: 1; font-weight: 500; }
  .component-edit-item.empty { color: var(--text-muted, #6b7280); font-style: italic; }
  .component-edit-item .qty-input { width: 5rem; }
  .comp-unit { color: var(--text-muted, #6b7280); }
  .comp-search {
    display: flex;
    gap: 0.4rem;
    margin-bottom: 0.5rem;
  }
  .comp-search input { flex: 1; }
  .comp-results {
    list-style: none;
    margin: 0 0 0.75rem;
    padding: 0;
  }
  .comp-result {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem;
    padding: 0.3rem 0;
    border-bottom: 1px solid var(--border, #e5e7eb);
    font-size: 0.9rem;
  }
  select {
    padding: 0.3rem 0.4rem;
    font: inherit;
    border: 1px solid var(--border, #d1d5db);
    border-radius: 0.35rem;
  }
</style>
