/* global React, window */
// Ruticomidas — screens
// Each screen is a self-contained function exported on window.RC_SCREENS.

const { useState, useEffect, useMemo, useCallback, useRef } = React;
const D = window.RC_DATA;

// -------- Small helpers --------
function Masthead({ kicker, title, deck, stats, actions }) {
  return (
    <header className="masthead">
      <div>
        {kicker && <div className="kicker">{kicker}</div>}
        <h1 className="t-display-2">{title}</h1>
        {deck && <div className="deck">{deck}</div>}
        {actions && <div className="row" style={{ marginTop: 18 }}>{actions}</div>}
      </div>
      {stats && <div className="masthead-stats">{stats}</div>}
    </header>
  );
}

function Stat({ label, value, delta, down }) {
  return (
    <div className="stat">
      <div className="label">{label}</div>
      <div className="value">{value}</div>
      {delta && <div className={'delta' + (down ? ' down' : '')}>{delta}</div>}
    </div>
  );
}

function SectionHead({ title, sub, right }) {
  return (
    <div className="section-head">
      <div>
        <h2 className="t-headline-l">{title}</h2>
        {sub && <div className="sub" style={{ marginTop: 6 }}>{sub}</div>}
      </div>
      {right}
    </div>
  );
}

// -------- PLANNING --------
function PlanningScreen() {
  const store = window.RC_STORE.useStore();
  const { planningWeek, weekOffset, changeWeek, recipes, recipeCosts, reload } = store;
  const [showCost, setShowCost] = useState(false);
  const [applyingTemplate, setApplyingTemplate] = useState(false);

  const MEAL_SLOTS = D.MEAL_SLOTS;

  const days     = planningWeek?.days     || [];
  const planning = planningWeek?.planning || [];

  const meals    = planning.flat().filter(Boolean).reduce((s, m) => s + (m.recipes?.length || 0), 0);
  const loose    = planning.flat().filter(Boolean).reduce((s, m) => s + (m.loose?.length || 0), 0);
  const weekLabel = planningWeek?.weekLabel || '';

  const FALLBACK_TONES = ['mint', 'yellow', 'pink', 'orange', 'purple'];
  const toneByName = useMemo(() => {
    const m = {};
    (recipes || []).forEach(r => { m[r.name] = r.tone; });
    return m;
  }, [recipes]);
  const toneFor = (name) => {
    if (!name) return 'mint';
    if (toneByName[name]) return toneByName[name];
    let h = 0;
    for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) >>> 0;
    return FALLBACK_TONES[h % FALLBACK_TONES.length];
  };

  const todayIdx = days.findIndex(d => d.today);
  const isPast = (dIdx) => todayIdx >= 0 && dIdx < todayIdx;

  const openAddRecipeModal = (dIdx, sIdx) => {
    window.dispatchEvent(new CustomEvent('rc:modal', {
      detail: {
        name: 'meal',
        props: { day: days[dIdx], slot: MEAL_SLOTS[sIdx], recipes, onSave: reload.planning },
      },
    }));
  };
  const openLooseModal = (e, dIdx, sIdx) => {
    e.stopPropagation();
    window.dispatchEvent(new CustomEvent('rc:modal', {
      detail: {
        name: 'loose',
        props: { day: days[dIdx], slot: MEAL_SLOTS[sIdx], onSave: reload.planning },
      },
    }));
  };

  const openRecipeDetailModal = (e, r) => {
    e.stopPropagation();
    window.dispatchEvent(new CustomEvent('rc:modal', {
      detail: {
        name: 'planning-recipe',
        props: {
          planRecipe: r,
          recipe: (recipes || []).find(x => x.id === r.recipeId) || null,
          onSave: reload.planning,
        },
      },
    }));
  };

  const deleteLoose = async (e, lid) => {
    e.stopPropagation();
    try {
      await window.api(`/api/planning/loose/${lid}`, 'DELETE');
      await reload.planning();
    } catch (err) { window.showToast(err.message, 'error'); }
  };

  const applyTemplate = async () => {
    setApplyingTemplate(true);
    try {
      await window.api('/api/template/apply', 'POST', {});
      await reload.planning();
      window.showToast('Plantilla aplicada');
    } catch (e) { window.showToast(e.message, 'error'); }
    finally { setApplyingTemplate(false); }
  };

  const weekCostRows = useMemo(() => {
    if (!planningWeek || !recipeCosts) return [];
    const rows = [];
    (planningWeek.planning || []).forEach((daySlots, dIdx) => {
      const day = (planningWeek.days || [])[dIdx];
      (daySlots || []).forEach((meal, sIdx) => {
        if (!meal) return;
        const slot = (D.MEAL_SLOTS || [])[sIdx];
        (meal.recipes || []).forEach(r => {
          const cost = recipeCosts[r.recipeId];
          rows.push({
            day: day?.dow || '', date: day?.date || '',
            slot: slot?.label || '', name: r.title,
            raciones: r.raciones || 1,
            cost: cost ? cost.total * (r.raciones || 1) : null,
            partial: cost?.partial || false,
          });
        });
      });
    });
    return rows;
  }, [planningWeek, recipeCosts]);

  const weekTotalCost = weekCostRows.reduce((s, r) => s + (r.cost || 0), 0);

  return (
    <>
      <Masthead
        kicker="01 · Comidas / Planning"
        title={weekLabel}
        deck="Semana seleccionada"
        stats={
          <>
            <Stat label="Recetas" value={meals} />
            <Stat label="Sueltos" value={loose} />
            {weekTotalCost > 0 && <Stat label="Coste est." value={weekTotalCost.toFixed(2) + '€'} />}
          </>
        }
      />
      <div className="screen">
        <div className="week-toolbar">
          <div className="row" style={{ gap: 8 }}>
            <div className="week-nav">
              <button onClick={() => changeWeek(weekOffset - 1)} aria-label="anterior">‹</button>
              <span className="label">{weekLabel}</span>
              <button onClick={() => changeWeek(weekOffset + 1)} aria-label="siguiente">›</button>
            </div>
            <button className="btn btn--ghost btn--sm" onClick={() => changeWeek(0)}>Hoy</button>
            <button className="btn btn--ghost btn--sm" onClick={applyTemplate} disabled={applyingTemplate}>
              {applyingTemplate ? '…' : 'Aplicar plantilla'}
            </button>
          </div>
          <div className="row" style={{ gap: 8 }}>
            <button className="btn btn--outline btn--sm" onClick={() => setShowCost(v => !v)}>
              {showCost ? 'Ocultar coste' : 'Coste detallado'}
            </button>
            <div className="t-mono-micro dim" style={{ marginLeft: 8 }}>● STOCK SE DESCUENTA AL FINALIZAR EL DÍA</div>
          </div>
        </div>

        {showCost && (
          <div className="card" style={{ marginBottom: 16 }}>
            <div className="row-between" style={{ marginBottom: 12 }}>
              <div>
                <div className="t-mono-label">Coste estimado de la semana</div>
                <div className="t-mono-micro dim" style={{ marginTop: 2 }}>* = datos parciales (sin precio de algún ingrediente)</div>
              </div>
              <div className="t-display-3" style={{ fontSize: 28, color: 'var(--mint)' }}>{weekTotalCost.toFixed(2)}€</div>
            </div>
            {weekCostRows.length === 0 && <div className="t-body dim">Sin comidas planificadas esta semana.</div>}
            {weekCostRows.length > 0 && (
              <table className="dt">
                <thead><tr><th>Día</th><th>Comida</th><th>Receta</th><th>Rac.</th><th style={{ textAlign: 'right' }}>Coste</th></tr></thead>
                <tbody>
                  {weekCostRows.map((r, i) => (
                    <tr key={i}>
                      <td><span className="t-mono-micro dim">{r.day}</span></td>
                      <td><span className="t-mono-micro dim">{r.slot}</span></td>
                      <td>{r.name}</td>
                      <td>{r.raciones}</td>
                      <td style={{ textAlign: 'right' }}>
                        {r.cost !== null
                          ? <span className="t-mono-micro">{r.cost.toFixed(2)}€{r.partial ? '*' : ''}</span>
                          : <span className="t-mono-micro dim">—</span>}
                      </td>
                    </tr>
                  ))}
                </tbody>
                <tfoot>
                  <tr>
                    <td colSpan="4" style={{ textAlign: 'right' }}><span className="t-mono-label dim">TOTAL SEMANA</span></td>
                    <td style={{ textAlign: 'right' }}><span className="t-mono-micro" style={{ color: 'var(--mint)' }}>{weekTotalCost.toFixed(2)}€</span></td>
                  </tr>
                </tfoot>
              </table>
            )}
          </div>
        )}

        <div className="planning-grid">
          <div></div>
          {days.map((d, i) => (
            <div key={i} className={'plan-day-head' + (d.today ? ' today' : '')}>
              <div className="dow">{d.dow}{d.today && ' · Hoy'}</div>
              <div className="dom">{d.dom}</div>
            </div>
          ))}

          {MEAL_SLOTS.map((slot, sIdx) => (
            <React.Fragment key={slot.id}>
              <div className="plan-row-head">{slot.label}</div>
              {days.map((day, dIdx) => {
                const meal = planning[dIdx]?.[sIdx];
                const recipeList = meal?.recipes || [];
                const firstTone = recipeList.length > 0 ? toneFor(recipeList[0].title) : null;
                const cellClasses = ['plan-cell'];
                if (day.today) cellClasses.push('today');
                if (isPast(dIdx)) cellClasses.push('past');
                if (!meal) {
                  cellClasses.push('empty');
                } else if (firstTone) {
                  cellClasses.push('tone-' + firstTone);
                }

                return (
                  <div key={dIdx} className={cellClasses.join(' ')}>
                    {recipeList.map(r => {
                      const rc = recipeCosts[r.recipeId];
                      const costVal = rc ? rc.total * (r.raciones || 1) : null;
                      return (
                        <div key={r.id}
                          className={'recipe-row' + (r.notConsumed ? ' not-consumed' : '')}
                          onClick={(e) => openRecipeDetailModal(e, r)}>
                          <div style={{ flex: 1, minWidth: 0 }}>
                            <div className="meal-title">{r.title}</div>
                            <div className="meal-tag">{r.raciones} RAC</div>
                            {costVal !== null && (
                              <div className="meal-tag" style={{ color: 'var(--mint-border)' }}>
                                {costVal.toFixed(2)}€{rc.partial ? '*' : ''}
                              </div>
                            )}
                          </div>
                        </div>
                      );
                    })}
                    {meal && (meal.loose || []).length > 0 && (
                      <div className="meal-loose">
                        <div className="ll">+ EXTRA</div>
                        {meal.loose.map(l => (
                          <div key={l.id} className="lr">
                            <span>{l.name}</span>
                            <span className="qq">{l.qty} {l.unit}</span>
                            <button className="recipe-btn recipe-btn--del"
                              onClick={(e) => deleteLoose(e, l.id)}>×</button>
                          </div>
                        ))}
                      </div>
                    )}
                    <div className="add-row">
                      <button className="add-loose"
                        onClick={(e) => { e.stopPropagation(); openAddRecipeModal(dIdx, sIdx); }}>+ Receta</button>
                      <button className="add-loose"
                        onClick={(e) => openLooseModal(e, dIdx, sIdx)}>+ Extra</button>
                    </div>
                  </div>
                );
              })}
            </React.Fragment>
          ))}
        </div>
      </div>
    </>
  );
}

// -------- RECETAS --------
function RecetasScreen() {
  const store = window.RC_STORE.useStore();
  const { recipes, recipeCosts, reload } = store;
  const [filter, setFilter] = useState('Todas');
  // costDetails[recipeId] = array of {name, qty, unit, cost|null} (lazy fetched on hover)
  const [costDetails, setCostDetails] = useState({});
  const filters = ['Todas', 'Desayuno', 'Comida', 'Merienda', 'Cena', 'Pública'];

  const list = useMemo(() => {
    if (filter === 'Todas') return recipes;
    if (filter === 'Pública') return recipes.filter(r => r.public);
    return recipes.filter(r => (r.kinds || []).some(k => k.toLowerCase().includes(filter.toLowerCase())));
  }, [recipes, filter]);

  const openRecipeModal = (r) => {
    window.dispatchEvent(new CustomEvent('rc:modal', { detail: { name: 'recipe', props: { recipe: r, onSave: reload.recipes } } }));
  };

  const fetchCostDetail = async (rid) => {
    if (costDetails[rid] !== undefined) return; // already fetched or fetching
    setCostDetails(prev => ({ ...prev, [rid]: null })); // mark as loading
    try {
      const data = await window.api(`/api/recipes/${rid}/cost`);
      setCostDetails(prev => ({ ...prev, [rid]: data?.items || [] }));
    } catch (_) {
      setCostDetails(prev => ({ ...prev, [rid]: [] }));
    }
  };

  return (
    <>
      <Masthead
        kicker="01 · Comidas / Recetas"
        title="Biblioteca"
        deck={`${recipes.length} recetas en el hogar`}
        actions={
          <>
            <button className="btn" onClick={() => window.rcOpen('public-recipes', { onSave: reload.recipes })}>Explorar públicas</button>
            <button className="btn btn--primary" onClick={() => window.rcOpen('new-recipe', { onSave: reload.recipes })}>+ Nueva receta</button>
          </>
        }
      />
      <div className="screen">
        <div className="recipe-filters">
          {filters.map(f => (
            <button key={f} className={'chip' + (filter === f ? ' active' : '')} onClick={() => setFilter(f)}>{f}</button>
          ))}
          <div style={{ flex: 1 }} />
          <div className="t-mono-label dim">{list.length} recetas</div>
        </div>

        <div className="recipe-grid">
          {list.map((r) => {
            const rc = recipeCosts[r.id];
            const ingItems = costDetails[r.id]; // null=loading, undefined=not fetched, array=ready
            const ings = r.ingredients || [];
            return (
              <article
                key={r.id}
                className={'recipe-card' + (r.public ? ' recipe-card--public' : '')}
                onClick={() => openRecipeModal(r)}
                onMouseEnter={() => fetchCostDetail(r.id)}
              >
                <div className={'recipe-card__bar tone-' + r.tone}>
                  <div className="recipe-card__bar-meta">
                    <span>{(r.kinds[0] || 'receta').toUpperCase()}</span>
                    {r.public && (
                      <span style={{
                        fontFamily: 'var(--f-mono)', fontSize: 9, letterSpacing: '0.16em',
                        textTransform: 'uppercase', opacity: 0.75,
                        border: '1px solid currentColor', borderRadius: 3, padding: '1px 5px',
                      }}>PÚBLICA</span>
                    )}
                  </div>
                  <h3 className="recipe-card__title">{r.name}</h3>
                </div>

                <div className="recipe-card__body">
                  {ings.length > 0 && (
                    <div className="recipe-card__ings">
                      {ings.slice(0, 6).map((ing, ii) => {
                        const ingName = ing.name || ing.ingredient_name;
                        const priceItem = Array.isArray(ingItems) && ingItems.find(it => it.name === ingName);
                        return (
                          <div key={ii} className="recipe-card__ing">
                            <span className="ing-name">{ingName}</span>
                            <span className="ing-qty">{ing.qty} {ing.unit}</span>
                            <span className="ing-price">
                              {priceItem && priceItem.cost != null ? priceItem.cost.toFixed(2) + '€' : ''}
                            </span>
                          </div>
                        );
                      })}
                      {ings.length > 6 && (
                        <div className="recipe-card__ing" style={{ paddingTop: 2 }}>
                          <span className="t-mono-micro dim">+{ings.length - 6} MÁS</span>
                        </div>
                      )}
                    </div>
                  )}
                  <div className="recipe-card__meta">
                    <div className="t-mono-micro dim">{ings.length} ingredientes{rc?.partial ? '*' : ''}</div>
                    <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
                      {rc && rc.total != null && (
                        <span className="price">{rc.total.toFixed(2)}€</span>
                      )}
                      <button
                        className="btn btn--ghost btn--sm"
                        style={{ fontSize: 11, padding: '2px 8px' }}
                        onClick={(e) => { e.stopPropagation(); window.rcOpen('recipe', { recipe: r, edit: true, onSave: reload.recipes }); }}
                      >Editar</button>
                    </div>
                  </div>
                </div>
              </article>
            );
          })}
          {list.length === 0 && (
            <div style={{ gridColumn: '1/-1', padding: 32, color: 'var(--text-meta)', textAlign: 'center' }}>
              No hay recetas. Crea la primera.
            </div>
          )}
        </div>
      </div>
    </>
  );
}

// -------- COMPRA --------
const MKT_COLORS = { Mercadona: 'mint', Lidl: 'yellow', Carrefour: 'orange' };

function CompraScreen() {
  const [shoppingList, setShoppingList] = useState(null);
  const [checks, setChecks] = useState({});
  const pendingRemoval = useRef({});

  useEffect(() => {
    return () => { Object.values(pendingRemoval.current).forEach(clearTimeout); };
  }, []);

  const weekStart = (() => {
    const today = new Date();
    const dow = (today.getDay() + 6) % 7;
    const m = new Date(today);
    m.setDate(today.getDate() - dow);
    return m.toISOString().slice(0, 10);
  })();

  useEffect(() => {
    window.api('/api/shopping')
      .then(r => setShoppingList(r || []))
      .catch(e => window.showToast(e.message, 'error'));
  }, []);

  const toggle = async (k, item) => {
    const nowOn = !checks[k];
    setChecks(c => ({ ...c, [k]: nowOn }));
    if (nowOn && item.id) {
      try {
        await window.api('/api/shopping/buy', 'POST', {
          ingredient_id: item.id,
          qty: (item.to_buy || 0) * (item.packs || 1),
          ingredient_name: item.name,
          week_start: weekStart,
          unset_manual: false,
          reset_extra_packs: false,
        });
        clearTimeout(pendingRemoval.current[k]);
        pendingRemoval.current[k] = setTimeout(() => {
          setShoppingList(l => l ? l.filter(x => String(x.id || x.name) !== k) : l);
        }, 2500);
      } catch (e) {
        window.showToast(e.message, 'error');
        setChecks(c => ({ ...c, [k]: false }));
      }
    }
  };

  const byMarket = (shoppingList || []).reduce((acc, it) => {
    const mkt = it.supermarket || 'Otros';
    if (!acc[mkt]) acc[mkt] = [];
    acc[mkt].push(it);
    return acc;
  }, {});
  const markets = Object.entries(byMarket);
  const totalItems = (shoppingList || []).length;
  const totalChecked = Object.values(checks).filter(Boolean).length;

  return (
    <>
      <Masthead
        kicker="01 · Comidas / Compra"
        title="Lista activa"
        deck="Basada en planning de esta semana"
        stats={
          <>
            <Stat label="Items" value={totalItems} />
            <Stat label="Comprados" value={`${totalChecked}/${totalItems}`} />
          </>
        }
        actions={
          <>
            <button className="btn" onClick={() => window.rcOpen('adhoc', {})}>+ Artículo único</button>
          </>
        }
      />
      <div className="screen">
        <div className="t-mono-micro dim" style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ display: 'inline-block', width: 6, height: 6, borderRadius: 999, background: 'var(--mint)' }}></span>
          AL MARCAR UN ÍTEM SE SUMA AUTOMÁTICAMENTE AL STOCK DEL ARTÍCULO
        </div>

        {shoppingList === null && (
          <div className="card" style={{ padding: 24, color: 'var(--text-meta)' }}>Cargando lista…</div>
        )}
        {shoppingList !== null && markets.length === 0 && (
          <div className="card" style={{ textAlign: 'center', padding: 32, color: 'var(--text-meta)' }}>
            Lista vacía. Asigna recetas al planning para generar la compra.
          </div>
        )}
        {markets.map(([market, items]) => (
          <div className="market-block" key={market}>
            <div className="market-block__head">
              <div className="row">
                <span className={'tag tag--' + (MKT_COLORS[market] || 'outline')}>{market}</span>
                <span className="t-mono-micro dim">{items.length} items</span>
              </div>
            </div>
            <ul className="market-block__list">
              {items.map((it) => {
                const k = String(it.id || it.name);
                const on = !!checks[k];
                const qtyLabel = it.packs > 1
                  ? `× ${it.packs} envases`
                  : `${(it.to_buy || 0).toFixed(1)} ${it.unit}`;
                return (
                  <li key={k} className={'shop-row' + (on ? ' checked' : '')}>
                    <button className={'check' + (on ? ' on' : '')} onClick={() => toggle(k, it)} aria-label="comprado">
                      {on && '✓'}
                    </button>
                    <div className="name">{it.name}</div>
                    <div className="qty">{qtyLabel}</div>
                    {it.manual && <div className="src">manual</div>}
                  </li>
                );
              })}
            </ul>
          </div>
        ))}
      </div>
    </>
  );
}

// -------- SUGERENCIAS --------
const MEAL_OPTS_SUG = [
  { v: '',          l: 'Todas' },
  { v: 'desayuno',  l: 'Desayuno' },
  { v: 'comida',    l: 'Comida' },
  { v: 'merienda',  l: 'Merienda' },
  { v: 'cena',      l: 'Cena' },
];

function SugerenciasScreen() {
  const { recipes, ingredients } = window.RC_STORE.useStore();
  const [mealFilter, setMealFilter] = useState('');

  const stock = useMemo(() => {
    const s = {};
    (ingredients || []).forEach(i => { s[i.name] = i.stock ?? 0; });
    return s;
  }, [ingredients]);

  const { puedes, falta } = useMemo(() => {
    const puedes = [], falta = [];
    (recipes || []).forEach(r => {
      if (mealFilter && r.kinds && !r.kinds.includes(mealFilter)) return;
      const ings = r.ingredients || [];
      if (!ings.length) return;
      const missing = ings.filter(ing => (stock[ing.name] ?? 0) < (ing.qty ?? 0));
      if (missing.length === 0)      puedes.push({ r, missing: [] });
      else if (missing.length <= 2)  falta.push({ r, missing: missing.map(i => i.name) });
    });
    return { puedes, falta };
  }, [recipes, stock, mealFilter]);

  return (
    <>
      <Masthead
        kicker="01 · Comidas / Sugerencias"
        title="Cocina con lo que hay"
        deck="A partir del stock actual del hogar"
        stats={
          <>
            <Stat label="Puedes cocinar" value={puedes.length} delta="STOCK OK" />
            <Stat label="Casi lista" value={falta.length} delta="≤2 FALTANTES" />
          </>
        }
      />
      <div className="screen">
        <div className="recipe-filters" style={{ marginBottom: 20 }}>
          {MEAL_OPTS_SUG.map(o => (
            <button key={o.v} className={'chip' + (mealFilter === o.v ? ' active' : '')} onClick={() => setMealFilter(o.v)}>{o.l}</button>
          ))}
        </div>

        <SectionHead title="Puedes cocinar ahora" sub="Stock completo" />
        {puedes.length === 0 && <div className="t-body dim" style={{ padding: '8px 0 20px' }}>Ninguna receta con todo el stock.</div>}
        <div className="recipe-grid" style={{ marginTop: 12, marginBottom: 24 }}>
          {puedes.map(({ r }) => (
            <article key={r.id} className={'recipe-card tone-' + r.tone}>
              <div className={'recipe-card__bar tone-' + r.tone}>
                <div className="recipe-card__bar-meta">
                  <span>{(r.kinds[0] || 'receta').toUpperCase()}</span>
                </div>
                <h3 className="recipe-card__title">{r.name}</h3>
              </div>
              <div className="recipe-card__body">
                <div className="recipe-card__meta">
                  <div className="t-mono-micro dim">{(r.ingredients || []).length} ingredientes</div>
                </div>
              </div>
            </article>
          ))}
        </div>

        <SectionHead title="Casi lista" sub="Faltan ≤2 ingredientes" />
        {falta.length === 0 && <div className="t-body dim" style={{ padding: '8px 0' }}>Ninguna receta aquí.</div>}
        <div className="recipe-grid" style={{ marginTop: 12 }}>
          {falta.map(({ r, missing }) => (
            <article key={r.id} className={'recipe-card tone-' + r.tone}>
              <div className={'recipe-card__bar tone-' + r.tone}>
                <div className="recipe-card__bar-meta">
                  <span>{(r.kinds[0] || 'receta').toUpperCase()}</span>
                </div>
                <h3 className="recipe-card__title">{r.name}</h3>
              </div>
              <div className="recipe-card__body">
                <div style={{ fontSize: 11, color: 'var(--tile-pink)' }}>Falta: {missing.join(', ')}</div>
              </div>
            </article>
          ))}
        </div>
      </div>
    </>
  );
}

// -------- GASTOS / RESUMEN --------
const GASTOS_CAT_COLORS = ['#3cffd0','#5200ff','#ffd166','#ef476f','#06d6a0','#118ab2','#ff9f1c','#e63946'];

function GastosScreen() {
  const store = window.RC_STORE.useStore();
  const { budgets: rawBudgets, reload: storeReload } = store;

  const [monthOffset, setMonthOffset] = useState(0);
  const [rawSummary, setRawSummary] = useState(null);
  const [prevTotal, setPrevTotal] = useState(null);

  const getMonthDate = useCallback((offset) => {
    const d = new Date();
    d.setDate(1);
    d.setMonth(d.getMonth() + offset);
    return d.toISOString().slice(0, 10);
  }, []);

  const monthLabel = useMemo(() => {
    const d = new Date();
    d.setDate(1);
    d.setMonth(d.getMonth() + monthOffset);
    const lbl = d.toLocaleString('es-ES', { month: 'long', year: 'numeric' });
    return lbl.charAt(0).toUpperCase() + lbl.slice(1);
  }, [monthOffset]);

  useEffect(() => {
    const date = getMonthDate(monthOffset);
    const datePrev = getMonthDate(monthOffset - 1);
    Promise.all([
      window.api(`/api/expenses/summary?period=month&date=${date}`),
      window.api(`/api/expenses/summary?period=month&date=${datePrev}`),
    ])
      .then(([cur, prev]) => {
        setRawSummary(cur || null);
        setPrevTotal(prev?.total ?? null);
      })
      .catch(e => window.showToast(e.message, 'error'));
  }, [monthOffset, getMonthDate]);

  const byCat = useMemo(() => {
    const m = {};
    ((rawSummary || {}).by_category || []).forEach(c => { m[c.name] = c; });
    return m;
  }, [rawSummary]);

  const budgets = useMemo(() => (rawBudgets || []).map((b, i) => {
    const spent = (byCat[b.name]?.total) || 0;
    const limit = b.monthly_limit || 0;
    const pct = limit > 0 ? Math.round((spent / limit) * 100) : 0;
    return {
      id: b.id, cat: b.name, icon: b.icon || '📦',
      spent, limit, pct, over: limit > 0 && spent > limit,
      color: GASTOS_CAT_COLORS[i % GASTOS_CAT_COLORS.length],
    };
  }), [rawBudgets, byCat]);

  const totalMonth = rawSummary?.total || 0;
  const topCat = ((rawSummary || {}).by_category || [])[0] || { name: '—', total: 0 };
  const budget = budgets.reduce((s, b) => s + b.limit, 0);
  const vsLast = (prevTotal != null && prevTotal > 0)
    ? Math.round(((totalMonth - prevTotal) / prevTotal) * 100)
    : null;
  const k = { totalMonth, budget, topCategory: topCat.name, topCategoryAmount: topCat.total };

  const weekBars = ((rawSummary || {}).evolution || []).map((e, i) => ({
    lbl: `S${i + 1}`, v: e.total || 0, c: i % 2 === 0 ? 'mint' : 'ultra',
  }));
  const topPlaces = ((rawSummary || {}).top_places || []).map(p => ({ name: p.name, v: p.total }));
  const byPayment = (rawSummary || {}).by_payment || {};
  const paymentEntries = Object.entries(byPayment).sort((a, b) => b[1] - a[1]);

  const total = budgets.reduce((sum, b) => sum + b.spent, 0);
  let acc = 0;
  const stops = budgets.length > 0
    ? budgets.map(b => {
        const start = total > 0 ? (acc / total) * 360 : 0;
        acc += b.spent;
        const end = total > 0 ? (acc / total) * 360 : 0;
        return `${b.color} ${start}deg ${end}deg`;
      }).join(', ')
    : 'var(--text-meta) 0deg 360deg';

  const barMax = weekBars.length > 0 ? Math.max(...weekBars.map(b => b.v), 1) : 1;
  const plMax  = topPlaces.length > 0 ? topPlaces[0].v : 1;

  return (
    <>
      <Masthead
        kicker="02 · Gastos / Resumen"
        title={monthLabel}
        deck="Resumen mensual de gastos"
        actions={
          <>
            <button className="btn btn--primary" onClick={() => window.rcOpen('expense', { onSave: storeReload.expenses })}>+ Nuevo gasto</button>
          </>
        }
      />
      <div className="screen">
        <div className="week-toolbar" style={{ marginBottom: 16 }}>
          <div className="week-nav">
            <button onClick={() => setMonthOffset(v => v - 1)} aria-label="mes anterior">‹</button>
            <span className="label">{monthLabel}</span>
            <button onClick={() => setMonthOffset(v => v + 1)} aria-label="mes siguiente" disabled={monthOffset >= 0}>›</button>
          </div>
          <button className="btn btn--ghost btn--sm" onClick={() => setMonthOffset(0)} disabled={monthOffset === 0}>Hoy</button>
        </div>

        <div className="kpi-grid">
          <div className="kpi kpi--mint invert">
            <div className="label">GASTO TOTAL</div>
            <div className="v">{k.totalMonth.toFixed(2)}€</div>
            <div className="sub">DE {k.budget.toFixed(0)}€{k.budget > 0 ? ` · ${Math.round((k.totalMonth/k.budget)*100)}%` : ''}</div>
          </div>
          <div className="kpi kpi--ultra">
            <div className="label">VS. MES ANTERIOR</div>
            <div className="v">{vsLast == null ? '—' : (vsLast >= 0 ? '+' : '') + vsLast + '%'}</div>
          </div>
          <div className="kpi kpi--canvas">
            <div className="label">TOP CATEGORÍA</div>
            <div className="v" style={{ color: 'var(--mint)' }}>{k.topCategoryAmount.toFixed(2)}€</div>
            <div className="sub">{k.topCategory.toUpperCase()}</div>
          </div>
          <div className="kpi kpi--yellow invert">
            <div className="label">MÉTODO DE PAGO</div>
            <div className="v">{paymentEntries.length > 0 ? paymentEntries[0][1].toFixed(2) + '€' : '—'}</div>
            <div className="sub">
              {paymentEntries.map(([k, v]) => `${k.toUpperCase()} ${v.toFixed(2)}€`).join(' · ') || '—'}
            </div>
          </div>
        </div>

        <div className="cols-l-r">
          <div className="card">
            <SectionHead title="Categorías vs presupuesto" sub="Mensual" />
            <div style={{ marginTop: 12 }}>
              {budgets.map(b => (
                <div className="budget-row" key={b.cat}>
                  <div className="icon" style={{ background: b.color, color: '#000' }}>{b.icon}</div>
                  <div className="name">
                    <div className="top">
                      <div className="label">{b.cat}</div>
                      <div className="pct">{b.pct}%</div>
                    </div>
                    <div className={'progress' + (b.over ? ' progress--over' : '')}>
                      <span style={{ width: Math.min(b.pct, 100) + '%', background: b.over ? 'var(--tile-pink)' : b.color }}></span>
                    </div>
                  </div>
                  <div className="amount">
                    {b.spent.toFixed(2)}€
                    {b.limit > 0 && <span className="of">DE {b.limit.toFixed(0)}€</span>}
                  </div>
                </div>
              ))}
              {budgets.length === 0 && <div style={{ color: 'var(--text-meta)', fontSize: 13, padding: '12px 0' }}>Sin categorías aún.</div>}
            </div>
          </div>

          <div className="card">
            <SectionHead title="Reparto" sub="Por categoría" />
            <div style={{ display: 'flex', gap: 24, alignItems: 'center', marginTop: 16 }}>
              <div className="donut" style={{ background: `conic-gradient(${stops})` }}>
                <div className="center">
                  <div>
                    <div className="v">{k.totalMonth.toFixed(0)}€</div>
                    <div className="l">TOTAL MES</div>
                  </div>
                </div>
              </div>
              <div className="legend" style={{ flex: 1 }}>
                {budgets.filter(b => b.spent > 0).map(b => (
                  <div className="legend-row" key={b.cat}>
                    <span className="sw" style={{ background: b.color }}></span>
                    <span className="ln">{b.cat}</span>
                    <span className="pc">{total > 0 ? Math.round((b.spent / total) * 100) : 0}%</span>
                    <span className="vl">{b.spent.toFixed(0)}€</span>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>

        <div className="cols-l-r">
          <div className="card">
            <SectionHead title="Evolución semanal" sub="€ por semana del mes" />
            <div className="bars" style={{ marginTop: 24 }}>
              {weekBars.map(b => (
                <div className="bar" key={b.lbl}>
                  <div className={'col ' + b.c} style={{ height: `${(b.v / barMax) * 100}%` }}>
                    <span className="v">{b.v.toFixed(0)}€</span>
                  </div>
                  <span className="lbl">{b.lbl}</span>
                </div>
              ))}
              {weekBars.length === 0 && <div style={{ color: 'var(--text-meta)', fontSize: 13 }}>Sin datos.</div>}
            </div>
          </div>

          <div className="card">
            <SectionHead title="Top lugares" sub="Más visitados este mes" />
            <div style={{ marginTop: 12, display: 'flex', flexDirection: 'column', gap: 14 }}>
              {topPlaces.map((p, i) => (
                <div key={p.name}>
                  <div className="row-between" style={{ marginBottom: 6 }}>
                    <div className="row" style={{ gap: 8 }}>
                      <span className="t-mono-micro dim">0{i + 1}</span>
                      <span className="t-body-bold">{p.name}</span>
                    </div>
                    <span className="t-mono-micro">{p.v.toFixed(2)}€</span>
                  </div>
                  <div className="progress"><span style={{ width: `${(p.v / plMax) * 100}%` }}></span></div>
                </div>
              ))}
              {topPlaces.length === 0 && <div style={{ color: 'var(--text-meta)', fontSize: 13 }}>Sin datos.</div>}
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

// -------- TICKETS / OCR --------
const TICKET_PERIODS = [
  { id: 'month', label: 'Este mes' },
  { id: 'lastmonth', label: 'Mes anterior' },
  { id: 'year', label: 'Este año' },
  { id: 'all', label: 'Todo' },
];

function TicketsScreen() {
  const [queuePending, setQueuePending] = useState([]);
  const [ticketStats, setTicketStats] = useState(null);
  const [topProducts, setTopProducts] = useState([]);
  const [recentTickets, setRecentTickets] = useState([]);
  const [loading, setLoading] = useState(true);
  const [period, setPeriod] = useState('month');
  const [priceQuery, setPriceQuery] = useState('');
  const [priceResults, setPriceResults] = useState(null);
  const [priceLoading, setPriceLoading] = useState(false);

  const buildRecentUrl = (p) => {
    const now = new Date();
    if (p === 'month') {
      return `/api/tickets/recent?limit=50&year=${now.getFullYear()}&month=${now.getMonth() + 1}`;
    }
    if (p === 'lastmonth') {
      const d = new Date(now.getFullYear(), now.getMonth() - 1, 1);
      return `/api/tickets/recent?limit=50&year=${d.getFullYear()}&month=${d.getMonth() + 1}`;
    }
    if (p === 'year') return `/api/tickets/recent?limit=200&year=${now.getFullYear()}`;
    return '/api/tickets/recent?limit=200';
  };

  const loadData = useCallback(async (p) => {
    setLoading(true);
    try {
      const [stats, queue, tops, recent] = await Promise.all([
        window.api('/api/tickets/stats'),
        window.api('/api/tickets/queue/pending'),
        window.api('/api/tickets/top-products?limit=5'),
        window.api(buildRecentUrl(p)),
      ]);
      setTicketStats(stats || {});
      setQueuePending(queue || []);
      setTopProducts(tops || []);
      setRecentTickets(recent || []);
    } catch (e) {
      window.showToast(e.message, 'error');
    } finally { setLoading(false); }
  }, []);

  useEffect(() => { loadData(period); }, [period]);

  const doPriceSearch = useCallback(async () => {
    const q = priceQuery.trim();
    if (q.length < 2) { window.showToast('Escribe al menos 2 caracteres', 'error'); return; }
    setPriceLoading(true);
    try {
      const r = await window.api(`/api/tickets/price-search?q=${encodeURIComponent(q)}`);
      setPriceResults(r || []);
    } catch (e) { window.showToast(e.message, 'error'); }
    finally { setPriceLoading(false); }
  }, [priceQuery]);

  const deleteTicket = async (id) => {
    try {
      await window.api(`/api/tickets/${id}`, 'DELETE');
      setRecentTickets(prev => prev.filter(t => t.id !== id));
      window.showToast('Ticket eliminado');
    } catch (e) { window.showToast(e.message, 'error'); }
  };

  const reparseTicket = async (id) => {
    try {
      await window.api(`/api/tickets/${id}/reparse`, 'POST', {});
      window.showToast('Reprocesando con Gemini… puede tardar unos segundos');
      setTimeout(() => loadData(period), 3000);
    } catch (e) { window.showToast(e.message, 'error'); }
  };

  const s = ticketStats || { ticket_count: 0, total_spent: 0, avg_ticket: 0 };
  const maxFreq = topProducts.length > 0 ? topProducts[0].times_bought || 1 : 1;

  return (
    <>
      <Masthead
        kicker="02 · Gastos / Tickets"
        title="Gestión de tickets"
        deck="Cola FIFO · Gemini Vision · normalización de nombres"
        actions={
          <>
            <button className="btn btn--primary" onClick={() => window.rcOpen('upload-ticket', { onSave: () => loadData(period) })}>📷 Subir foto</button>
            <button className="btn btn--ghost btn--sm" onClick={() => loadData(period)}>↻ Actualizar</button>
          </>
        }
      />
      <div className="screen">
        {queuePending.length > 0 && (
          <div className="notify-banner">
            ● {queuePending.length} TICKET{queuePending.length > 1 ? 'S' : ''} LISTO{queuePending.length > 1 ? 'S' : ''} PARA VERIFICAR
          </div>
        )}

        <div className="tickets-stats">
          <div className="kpi kpi--canvas">
            <div className="label">TICKETS DEL MES</div>
            <div className="v">{s.ticket_count}</div>
          </div>
          <div className="kpi kpi--canvas">
            <div className="label">GASTO TOTAL</div>
            <div className="v" style={{ color: 'var(--mint)' }}>{(s.total_spent || 0).toFixed(0)}€</div>
          </div>
          <div className="kpi kpi--canvas">
            <div className="label">TICKET MEDIO</div>
            <div className="v">{(s.avg_ticket || 0).toFixed(2)}€</div>
          </div>
          <div className="kpi kpi--canvas">
            <div className="label">COLA PENDIENTE</div>
            <div className="v" style={{ color: queuePending.length > 0 ? 'var(--tile-orange)' : undefined }}>{queuePending.length}</div>
            <div className="sub">LISTOS PARA VERIFICAR</div>
          </div>
        </div>

        <div className="cols-l-r">
          <div>
            <SectionHead title="Cola de verificación" sub="Tickets procesados pendientes de confirmar" right={<button className="btn btn--ghost btn--sm" onClick={() => loadData(period)}>↻</button>} />
            {loading && <div className="t-body dim" style={{ marginTop: 16 }}>Cargando…</div>}
            {!loading && queuePending.length === 0 && (
              <div className="card" style={{ textAlign: 'center', padding: 32, color: 'var(--text-meta)', marginTop: 16 }}>
                Cola vacía. Sube una foto para procesar un ticket.
              </div>
            )}
            <div className="rail" style={{ marginTop: 24 }}>
              {queuePending.map(item => {
                const f = window.RC_ticketFlat(item.ticket_data);
                const when = item.created_at
                  ? new Date(item.created_at).toLocaleString('es-ES', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })
                  : '—';
                return (
                  <div className="rail-item" key={item.id}>
                    <div className="rail-time">{when}</div>
                    <div className="queue-card done" style={{ cursor: 'pointer' }}
                      onClick={() => window.rcOpen('ticket', { queueItem: item, onSave: () => loadData(period) })}>
                      <div className="thumb">
                        <div className="imgph" data-tone="mint" data-label="TICKET" style={{ width: '100%', height: '100%' }}></div>
                      </div>
                      <div>
                        <div className="row" style={{ gap: 8, marginBottom: 6 }}>
                          <span className="tag tag--mint">LISTO</span>
                          <span className="t-mono-micro dim">#{item.id}</span>
                        </div>
                        <div className="t-headline-s">{f.supermarket || 'Supermercado'}</div>
                        <div className="meta" style={{ marginTop: 6 }}>
                          <span>{f.items.length} ítems</span>
                          <span>{f.date || ''}</span>
                        </div>
                      </div>
                      <div style={{ textAlign: 'right' }} onClick={(ev) => ev.stopPropagation()}>
                        <div className="total">{(f.total ?? 0).toFixed(2)}€</div>
                        <div className="row" style={{ marginTop: 8, justifyContent: 'flex-end', gap: 6 }}>
                          <button className="btn btn--primary btn--sm"
                            onClick={() => window.rcOpen('ticket', { queueItem: item, onSave: () => loadData(period) })}>
                            Verificar
                          </button>
                        </div>
                      </div>
                    </div>
                  </div>
                );
              })}
            </div>
          </div>

          <div className="stack-4">
            <div className="card">
              <SectionHead title="Top productos" sub="Frecuencia · precio medio" />
              <div className="stack-3" style={{ marginTop: 12 }}>
                {topProducts.length === 0 && <div className="t-body dim" style={{ fontSize: 13 }}>Sin datos aún.</div>}
                {topProducts.map((p, i) => (
                  <div key={p.name}>
                    <div className="row-between">
                      <div className="row" style={{ gap: 8 }}>
                        <span className="t-mono-micro dim">{String(i + 1).padStart(2, '0')}</span>
                        <span className="t-body-bold">{p.name}</span>
                      </div>
                      <span className="t-mono-micro">{(p.avg_price || 0).toFixed(2)}€</span>
                    </div>
                    <div className="progress" style={{ marginTop: 6 }}>
                      <span style={{ width: `${((p.times_bought || 0) / maxFreq) * 100}%`, background: 'var(--ultraviolet)' }}></span>
                    </div>
                    <div className="t-mono-micro dim" style={{ marginTop: 4 }}>×{p.times_bought} TICKETS</div>
                  </div>
                ))}
              </div>
            </div>

            <div className="card card--block card--yellow">
              <div className="t-mono-label invert">BÚSQUEDA DE PRECIO</div>
              <div className="t-display-3 invert" style={{ marginTop: 8, fontSize: 36 }}>Histórico</div>
              <div className="t-body invert" style={{ marginTop: 8 }}>
                Encuentra el mejor supermercado para un producto.
              </div>
              <div className="row" style={{ marginTop: 12, gap: 8 }}>
                <input
                  className="input"
                  placeholder="ej. aceite oliva"
                  value={priceQuery}
                  onChange={e => { setPriceQuery(e.target.value); setPriceResults(null); }}
                  onKeyDown={e => e.key === 'Enter' && doPriceSearch()}
                  style={{ flex: 1, background: 'rgba(0,0,0,0.06)', borderColor: 'rgba(0,0,0,0.2)', color: '#000' }}
                />
                <button className="btn" style={{ background: '#000', color: '#fff' }} onClick={doPriceSearch} disabled={priceLoading}>
                  {priceLoading ? '…' : 'Buscar'}
                </button>
              </div>
              {priceResults !== null && (
                <div style={{ marginTop: 12, borderRadius: 8, overflow: 'hidden', maxHeight: 240, overflowY: 'auto', background: 'rgba(0,0,0,0.08)' }}>
                  {priceResults.length === 0 && (
                    <div style={{ padding: '10px 12px', color: '#000', fontSize: 13 }}>Sin resultados.</div>
                  )}
                  {priceResults.map((r, i) => (
                    <div key={i}
                      style={{ padding: '8px 12px', borderBottom: '1px solid rgba(0,0,0,0.1)', cursor: 'pointer', display: 'flex', justifyContent: 'space-between', alignItems: 'center', background: 'rgba(255,255,255,0.4)' }}
                      onClick={() => window.rcOpen('ticket', { ticketId: r.ticket_id, onSave: () => loadData(period) })}
                    >
                      <div>
                        <div style={{ fontWeight: 700, fontSize: 13, color: '#000' }}>{r.product_name || r.name}</div>
                        <div style={{ fontSize: 11, color: 'rgba(0,0,0,0.6)' }}>{r.supermarket} · {r.date}</div>
                      </div>
                      <div style={{ fontWeight: 700, fontSize: 14, color: '#000' }}>{(r.unit_price || 0).toFixed(2)}€/{r.unit || 'ud'}</div>
                    </div>
                  ))}
                </div>
              )}
            </div>
          </div>
        </div>

        <div className="row-between" style={{ marginTop: 24, marginBottom: 8 }}>
          <SectionHead title="Tickets confirmados" sub={`${recentTickets.length} tickets`} />
          <div className="recipe-filters" style={{ marginBottom: 0 }}>
            {TICKET_PERIODS.map(p => (
              <button key={p.id} className={'chip' + (period === p.id ? ' active' : '')}
                onClick={() => setPeriod(p.id)}>{p.label}</button>
            ))}
          </div>
        </div>
        {loading && <div className="t-body dim" style={{ marginTop: 12 }}>Cargando…</div>}
        {!loading && recentTickets.length === 0 && (
          <div className="card" style={{ textAlign: 'center', padding: 24, color: 'var(--text-meta)', marginTop: 8 }}>
            Sin tickets confirmados en este periodo.
          </div>
        )}
        {!loading && recentTickets.length > 0 && (
          <div className="card" style={{ padding: 0, overflow: 'hidden', marginTop: 8 }}>
            <table className="dt">
              <thead>
                <tr>
                  <th>#</th>
                  <th>Supermercado</th>
                  <th>Fecha</th>
                  <th>Ítems</th>
                  <th style={{ textAlign: 'right' }}>Total</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {recentTickets.map(t => (
                  <tr key={t.id}>
                    <td><span className="t-mono-micro dim">#{t.id}</span></td>
                    <td><div className="t-body-bold" style={{ cursor: 'pointer' }}
                      onClick={() => window.rcOpen('ticket', { ticketId: t.id, onSave: () => loadData(period) })}>{t.supermarket || '—'}</div></td>
                    <td><span className="t-mono-micro dim">{(t.date || '').toUpperCase()}</span></td>
                    <td><span className="t-mono-micro dim">{(t.items || []).length}</span></td>
                    <td style={{ textAlign: 'right' }}>
                      <span className="t-display-3" style={{ fontSize: 18 }}>{(t.total || 0).toFixed(2)}€</span>
                    </td>
                    <td style={{ whiteSpace: 'nowrap' }}>
                      <button className="btn btn--ghost btn--sm" style={{ marginRight: 4 }}
                        onClick={() => window.rcOpen('ticket', { ticketId: t.id, onSave: () => loadData(period) })}>Ver</button>
                      <button className="btn btn--ghost btn--sm" style={{ marginRight: 4 }}
                        title="Reprocesar con Gemini"
                        onClick={() => reparseTicket(t.id)}>↺</button>
                      <button className="btn btn--ghost btn--sm" style={{ color: 'var(--tile-pink)' }}
                        onClick={() => deleteTicket(t.id)}>✕</button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
    </>
  );
}

// -------- Placeholder for less-developed screens --------
function PlaceholderScreen({ kicker, title, deck }) {
  return (
    <>
      <Masthead kicker={kicker} title={title} deck={deck} />
      <div className="screen">
        <div className="card" style={{ textAlign: 'center', padding: 64 }}>
          <div className="t-mono-label dim">WIP · PRÓXIMAMENTE</div>
          <div className="t-display-3" style={{ marginTop: 12 }}>Pantalla en construcción</div>
          <div className="t-body dim" style={{ marginTop: 12, maxWidth: 460, margin: '12px auto 0' }}>
            Esta vista se desarrollará en la siguiente iteración del prototipo. La estructura del backend ya está cubierta por los endpoints correspondientes.
          </div>
          <div style={{ marginTop: 20 }}>
            <button className="btn btn--outline">Ver endpoints relacionados</button>
          </div>
        </div>
      </div>
    </>
  );
}

window.RC_SCREENS = {
  planning: () => <PlanningScreen />,
  recetas:  () => <RecetasScreen />,
  compra:   () => <CompraScreen />,
  sugerencias: () => <SugerenciasScreen />,
  gastos:   () => <GastosScreen />,
  tickets:  () => <TicketsScreen />,
  // remaining screens are attached by screens-extra.jsx
};
