// app/cost.jsx — recipe-costing UI. The "Calculate / Refresh cost" control (the
// cost analogue of the photo-enhance control), the cost breakdown, and the
// cook-mode servings scaler. All numbers come from the adapter (mock computes,
// live calls the API); these components only format + drive the actions.
//
// Cost vocabulary: every figure is an estimate, so it always reads with a
// leading "≈". Per-serve is the headline; full ("to make") is secondary.

const lcMoney = (n) => window.LCDomain.money(n);          // "≈ $2.60"
const lcDollars = (n) => window.LCDomain.fmtMoney(n);     // "$2.60"

function CostSpinner({ size = 14 }) {
  return <span style={{ width: size, height: size, borderRadius: '50%',
    border: '2px solid rgba(240,168,80,0.28)', borderTopColor: 'var(--olive)', boxSizing: 'border-box',
    display: 'inline-block', animation: 'lcSpin 0.7s linear infinite', flexShrink: 0 }} />;
}

const costKicker = { fontFamily: 'Bricolage Grotesque', fontSize: 10, fontWeight: 600,
  letterSpacing: '0.28em', textTransform: 'uppercase', color: 'var(--olive)' };

// ── headline figure: $2.60 /serve · $10.40 to make  (with inline refresh) ──
function CostFigure({ perServing, full, rough, big, onRefresh }) {
  return (
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' }}>
      <span style={{ display: 'inline-flex', alignItems: 'baseline', gap: 6 }}>
        <span style={{ fontFamily: 'Bricolage Grotesque', fontWeight: 700, fontSize: big ? 30 : 24,
          letterSpacing: '-0.03em', color: 'var(--ink)' }}>{lcMoney(perServing)}</span>
        <span style={{ fontFamily: 'Bricolage Grotesque', fontSize: 11, fontWeight: 600,
          letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--ink-3)' }}>/ serve</span>
        {rough && <span style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 13,
          color: 'var(--olive)' }}>· rough</span>}
      </span>
      {full != null && (
        <span style={{ display: 'inline-flex', alignItems: 'baseline', gap: 8 }}>
          <span style={{ width: 4, height: 4, borderRadius: 999, background: 'var(--hairline)', alignSelf: 'center' }} />
          <span style={{ fontFamily: 'Bricolage Grotesque', fontSize: big ? 15 : 14, fontWeight: 500,
            color: 'var(--ink-2)' }}>{lcMoney(full)} <span style={{ color: 'var(--ink-3)' }}>to make</span></span>
          {onRefresh && (
            <button onClick={onRefresh} title="Recalculate" style={{ alignSelf: 'center', cursor: 'pointer',
              width: 30, height: 30, borderRadius: 999, display: 'inline-flex', alignItems: 'center',
              justifyContent: 'center', background: 'rgba(240,168,80,0.12)', border: '1px solid rgba(240,168,80,0.4)',
              color: 'var(--olive)', marginLeft: 2, flexShrink: 0 }}>
              <Icon.undo size={16} />
            </button>
          )}
        </span>
      )}
    </div>
  );
}

// ── per-ingredient breakdown (disclosure) ──
function CostBreakdown({ breakdown, onReview, onEditIngredients }) {
  if (!breakdown) return null;
  const rows = breakdown.filter((b) => b.status !== 'section');
  const flagged = rows.filter((b) => b.status === 'needs_attention');
  const ok = rows.filter((b) => b.status !== 'needs_attention');
  return (
    <div style={{ marginTop: 14, paddingTop: 14, borderTop: '1px solid var(--hairline-2)',
      display: 'flex', flexDirection: 'column', gap: 2 }}>
      {/* All faulty lines grouped in ONE box, error on the same line, one CTA. */}
      {flagged.length > 0 && (
        <div style={{ marginBottom: 12, padding: '14px 16px', borderRadius: 12,
          background: 'rgba(240,168,80,0.08)', border: '1px solid rgba(240,168,80,0.3)' }}>
          <div style={{ fontFamily: 'Bricolage Grotesque', fontSize: 10, fontWeight: 600,
            letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--olive)', marginBottom: 10 }}>
            {flagged.length} ingredient{flagged.length === 1 ? '' : 's'} need{flagged.length === 1 ? 's' : ''} a look
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
            {flagged.map((b, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                <span style={{ color: 'var(--olive)', flexShrink: 0, fontSize: 12 }}>⚠</span>
                <span style={{ fontFamily: 'Spectral', fontSize: 14.5, lineHeight: 1.4, color: 'var(--ink)' }}>
                  {b.line}
                  <span style={{ color: 'var(--ink-3)' }}> — {b.note || 'needs a look'}</span>
                </span>
              </div>
            ))}
          </div>
          <div style={{ marginTop: 12 }}>
            <FButton size="s" onClick={onEditIngredients}>Edit ingredients →</FButton>
          </div>
        </div>
      )}
      {ok.map((b, i) => {
        const ignored = b.status === 'ignored';
        return (
          <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '6px 0' }}>
            <span style={{ flex: 1, minWidth: 0, fontFamily: 'Spectral', fontSize: 14.5, lineHeight: 1.4,
              color: ignored ? 'var(--ink-3)' : 'var(--ink-2)' }}>
              {b.line}
              {b.item && <span style={{ fontFamily: 'Bricolage Grotesque', fontSize: 11, color: 'var(--ink-3)',
                marginLeft: 8 }}>· {b.item}{b.qtyLabel ? ` · ${b.qtyLabel}` : ''}{b.isStaple ? ' · staple' : ''}</span>}
            </span>
            <span style={{ fontFamily: 'var(--mono)', fontSize: 12, whiteSpace: 'nowrap',
              color: ignored ? 'var(--ink-4)' : 'var(--ink-2)' }}>
              {ignored ? '—' : b.lineCost != null ? lcDollars(b.lineCost) : '—'}
            </span>
          </div>
        );
      })}
      <div style={{ marginTop: 8, fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 12.5,
        color: 'var(--ink-3)', lineHeight: 1.5 }}>
        Prices are AU estimates from your ingredient list — staples you keep on hand still count toward the cost.
        {onReview && <button onClick={onReview} style={{ background: 'transparent', border: 'none',
          cursor: 'pointer', color: 'var(--olive)', fontFamily: 'Bricolage Grotesque', fontSize: 12.5,
          fontWeight: 600, padding: 0, marginLeft: 6 }}>Edit prices →</button>}
      </div>
    </div>
  );
}

// ── small "serves N" stepper ──
function ServeStepper({ value, onChange, min = 1, max = 24 }) {
  const btn = (disabled) => ({ width: 30, height: 30, borderRadius: 999, cursor: disabled ? 'default' : 'pointer',
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
    background: disabled ? 'transparent' : 'rgba(255,255,255,0.05)', border: '1px solid var(--hairline)',
    color: disabled ? 'var(--ink-4)' : 'var(--ink-2)', fontSize: 16, fontWeight: 600, lineHeight: 1,
    opacity: disabled ? 0.5 : 1 });
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
      <button style={btn(value <= min)} disabled={value <= min}
        onClick={() => onChange(Math.max(min, value - 1))}>−</button>
      <span style={{ minWidth: 26, textAlign: 'center', fontFamily: 'Bricolage Grotesque',
        fontWeight: 700, fontSize: 19, color: 'var(--ink)', letterSpacing: '-0.02em' }}>{value}</span>
      <button style={btn(value >= max)} disabled={value >= max}
        onClick={() => onChange(Math.min(max, value + 1))}>+</button>
    </span>
  );
}

// ─────────────────────────────────────────────────────────────
// CostBar — the recipe-screen cost control (Calculate · Costing · Costed ·
// Needs-attention). Mirrors the photo-enhance control: per-recipe, on demand.
// ─────────────────────────────────────────────────────────────
function CostBar({ recipe, compact, inlineRefresh }) {
  const { calculateCost, saveRecipe, go } = useApp();
  const c = window.LCDomain.costInfo(recipe);
  const [open, setOpen] = React.useState(false);     // breakdown disclosure
  const [askServes, setAskServes] = React.useState(false);
  const [serves, setServes] = React.useState(c.servingsCount || 4);

  // Auto-expand the breakdown when a calculation resolves to needs_attention so
  // the user sees what to fix; collapse it again when a re-run comes back clean.
  const prevStatus = React.useRef(c.status);
  React.useEffect(() => {
    if (prevStatus.current === 'costing') {
      if (c.status === 'needs_attention') setOpen(true);
      else if (c.status === 'costed') setOpen(false);
    }
    prevStatus.current = c.status;
  }, [c.status]);

  const card = { background: 'rgba(255,255,255,0.03)', border: '1px solid var(--hairline)',
    borderRadius: 14, padding: compact ? '16px 18px' : '18px 22px' };
  const review = () => go('edit', { recipeId: recipe.id });

  const runCalc = (force) => {
    if (c.servingsCount == null && !force) { setAskServes(true); return; }
    calculateCost(recipe.id, { force: !!force });
  };
  const confirmServes = () => {
    // set servings first (the costing gate), then calculate
    saveRecipe({ ...recipe, servings: `serves ${serves}`, servingsCount: serves });
    setAskServes(false);
    setTimeout(() => calculateCost(recipe.id, { force: true }), 30);
  };

  // ── costing ──
  if (c.status === 'costing') {
    return (
      <div style={card}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <CostSpinner size={16} />
          <div>
            <div style={{ fontFamily: 'Bricolage Grotesque', fontSize: 15, fontWeight: 600, color: 'var(--ink)' }}>
              Working out the cost…</div>
            <div style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 13, color: 'var(--ink-3)', marginTop: 2 }}>
              reading your ingredients and matching prices</div>
          </div>
        </div>
      </div>
    );
  }

  // ── not costed yet ──
  if (c.status === 'none') {
    return (
      <div style={card}>
        {!askServes ? (
          <div style={{ display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap' }}>
            <div style={{ flex: 1, minWidth: 200 }}>
              <span style={costKicker}>Cost</span>
              <div style={{ fontFamily: 'Bricolage Grotesque', fontSize: compact ? 17 : 19, fontWeight: 600,
                color: 'var(--ink)', marginTop: 4 }}>Not calculated yet</div>
              <div style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 13.5, color: 'var(--ink-3)', marginTop: 2 }}>
                A quick per-serve estimate from your ingredients.</div>
            </div>
            <FButton size={compact ? 'm' : 'l'} onClick={() => runCalc(false)}>
              <Icon.sparkle size={15} />Calculate cost
            </FButton>
          </div>
        ) : (
          <div style={{ display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap' }}>
            <div style={{ flex: 1, minWidth: 180 }}>
              <span style={costKicker}>One thing first</span>
              <div style={{ fontFamily: 'Bricolage Grotesque', fontSize: 16, fontWeight: 600,
                color: 'var(--ink)', marginTop: 4 }}>How many does this serve?</div>
              <div style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 13, color: 'var(--ink-3)', marginTop: 2 }}>
                We split the total across servings.</div>
            </div>
            <ServeStepper value={serves} onChange={setServes} />
            <FButton size="m" onClick={confirmServes}><Icon.sparkle size={14} />Calculate</FButton>
            <button onClick={() => setAskServes(false)} style={{ background: 'transparent', border: 'none',
              cursor: 'pointer', color: 'var(--ink-3)', fontFamily: 'Bricolage Grotesque', fontSize: 13 }}>Cancel</button>
          </div>
        )}
      </div>
    );
  }

  // ── costed / needs_attention ──
  const flagged = c.status === 'needs_attention';
  const priced = (c.breakdown || []).filter((b) => b.status === 'priced' || b.status === 'needs_attention').length;
  const cardStyle = { ...card, border: flagged ? '1px solid rgba(240,168,80,0.32)' : '1px solid var(--hairline)',
    background: flagged ? 'rgba(240,168,80,0.05)' : 'rgba(255,255,255,0.03)' };
  const subLine = (
    <div style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 13, color: 'var(--ink-3)', marginTop: 6 }}>
      estimated from {priced} ingredient{priced === 1 ? '' : 's'}
      {c.flaggedCount > 0 && <span style={{ color: 'var(--olive)' }}> · {c.flaggedCount} need{c.flaggedCount === 1 ? 's' : ''} a look</span>}
    </div>
  );
  const workedOutBtn = (
    <button onClick={() => setOpen((o) => !o)} style={{ display: 'inline-flex', alignItems: 'center', gap: 6,
      height: 38, padding: '0 14px', borderRadius: 999, cursor: 'pointer', background: 'rgba(255,255,255,0.04)',
      border: '1px solid var(--hairline)', color: 'var(--ink-2)', fontFamily: 'Bricolage Grotesque',
      fontSize: 13, fontWeight: 500 }}>
      How it's worked out <Icon.chevD size={14} style={{ transform: open ? 'rotate(180deg)' : 'none', opacity: 0.6 }} />
    </button>
  );

  // Mobile: header (kicker + refresh icon), stacked figure, sub, then disclosure.
  if (inlineRefresh) {
    return (
      <div style={cardStyle}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>
          <span style={costKicker}>Cost{flagged ? ' · needs a look' : ''}</span>
          <button onClick={() => runCalc(true)} title="Recalculate" style={{ cursor: 'pointer',
            width: 32, height: 32, borderRadius: 999, display: 'inline-flex', alignItems: 'center',
            justifyContent: 'center', background: 'rgba(240,168,80,0.12)', border: '1px solid rgba(240,168,80,0.4)',
            color: 'var(--olive)', flexShrink: 0 }}>
            <Icon.undo size={16} />
          </button>
        </div>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginTop: 8, flexWrap: 'wrap' }}>
          <span style={{ fontFamily: 'Bricolage Grotesque', fontWeight: 700, fontSize: 28,
            letterSpacing: '-0.03em', color: 'var(--ink)' }}>{lcMoney(c.perServing)}</span>
          <span style={{ fontFamily: 'Bricolage Grotesque', fontSize: 11, fontWeight: 600,
            letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--ink-3)' }}>/ serve</span>
          {flagged && <span style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 13, color: 'var(--olive)' }}>· rough</span>}
          {c.full != null && (
            <span style={{ fontFamily: 'Bricolage Grotesque', fontSize: 14, fontWeight: 500, color: 'var(--ink-2)' }}>
              <span style={{ color: 'var(--ink-4)', margin: '0 4px' }}>·</span>{lcMoney(c.full)} <span style={{ color: 'var(--ink-3)' }}>to make</span></span>
          )}
        </div>
        {subLine}
        <div style={{ marginTop: 14 }}>{workedOutBtn}</div>
        {open && <CostBreakdown breakdown={c.breakdown} onReview={() => go('settings')} onEditIngredients={review} />}
      </div>
    );
  }

  // Desktop / tablet
  return (
    <div style={cardStyle}>
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 16, flexWrap: 'wrap' }}>
        <div style={{ flex: 1, minWidth: 220 }}>
          <span style={costKicker}>Cost{flagged ? ' · needs a look' : ''}</span>
          <div style={{ marginTop: 6 }}>
            <CostFigure perServing={c.perServing} full={c.full} rough={flagged} big={!compact} />
          </div>
          {subLine}
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
          {workedOutBtn}
          <button onClick={() => runCalc(true)} title="Recalculate" style={{ display: 'inline-flex', alignItems: 'center',
            gap: 6, height: 38, padding: '0 14px', borderRadius: 999, cursor: 'pointer', background: 'rgba(255,255,255,0.04)',
            border: '1px solid var(--hairline)', color: 'var(--ink-2)', fontFamily: 'Bricolage Grotesque',
            fontSize: 13, fontWeight: 500 }}>
            <Icon.undo size={14} />Refresh
          </button>
        </div>
      </div>
      {open && <CostBreakdown breakdown={c.breakdown} onReview={() => go('settings')} onEditIngredients={review} />}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// CookScaleControl — servings scaler for cook mode. Controlled by the parent;
// shows the scaled total cost so the figure tracks the serving count.
// ─────────────────────────────────────────────────────────────
function CookScaleControl({ recipe, servings, setServings, compact }) {
  const c = window.LCDomain.costInfo(recipe);
  const base = c.servingsCount || servings;
  const scaledTotal = c.perServing != null ? c.perServing * servings : null;
  return (
    <div style={{ display: 'inline-flex', alignItems: 'center', gap: compact ? 10 : 14,
      padding: compact ? '6px 10px 6px 14px' : '8px 12px 8px 16px', borderRadius: 999,
      background: 'rgba(255,255,255,0.04)', border: '1px solid var(--hairline)' }}>
      <span style={{ fontFamily: 'Bricolage Grotesque', fontSize: 11, fontWeight: 600,
        letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--ink-3)' }}>Serves</span>
      <ServeStepper value={servings} onChange={setServings} />
      {scaledTotal != null && (
        <>
          <span style={{ width: 1, height: 22, background: 'var(--hairline)' }} />
          <span style={{ display: 'inline-flex', flexDirection: 'column', lineHeight: 1.1 }}>
            <span style={{ fontFamily: 'Bricolage Grotesque', fontWeight: 700, fontSize: 15,
              color: 'var(--ink)', letterSpacing: '-0.02em', whiteSpace: 'nowrap' }}>{lcMoney(scaledTotal)}</span>
            <span style={{ fontFamily: 'Bricolage Grotesque', fontSize: 9, fontWeight: 600,
              letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--ink-3)' }}>
              {servings === base ? 'total' : `was ${base}`}</span>
          </span>
        </>
      )}
    </div>
  );
}

Object.assign(window, { CostBar, CostBreakdown, ServeStepper, CookScaleControl, CostFigure, lcMoney, lcDollars });
