// app/screen-edit.jsx — create / edit a recipe. Generous single column,
// big textareas; sub-section headers ("For the chilli oil:") preserved on save.

function slugify(s) {
  return (s || 'recipe').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 40)
    || 'recipe';
}

const FIELD_LABEL = { fontFamily: 'Bricolage Grotesque', fontSize: 10, fontWeight: 600,
  letterSpacing: '0.24em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 8,
  display: 'block' };

// The fixed meal vocabulary (CONTRACT: Recipe.meals). Replaces the dated free-text
// Paprika categories — a known, toggleable set that drives the library filters.
const MEAL_OPTIONS = ['breakfast', 'lunch', 'dinner', 'snack', 'dessert'];

function MealPicker({ value, onToggle }) {
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
      {MEAL_OPTIONS.map((m) => {
        const on = (value || []).includes(m);
        return (
          <button key={m} type="button" onClick={() => onToggle(m)} aria-pressed={on}
            style={{ textTransform: 'capitalize', cursor: 'pointer',
              fontFamily: 'Bricolage Grotesque', fontSize: 14, fontWeight: 500,
              padding: '9px 18px', borderRadius: 999,
              border: on ? '1px solid rgba(240,168,80,0.55)' : '1px solid var(--hairline)',
              background: on ? 'rgba(240,168,80,0.14)' : 'transparent',
              color: on ? 'var(--olive)' : 'var(--ink-2)' }}>
            {m}
          </button>
        );
      })}
    </div>
  );
}

const DIFFICULTY_OPTIONS = ['easy', 'medium', 'hard'];
function DifficultyPicker({ value, onChange }) {
  return (
    <div style={{ display: 'flex', gap: 8 }}>
      {DIFFICULTY_OPTIONS.map((d) => {
        const on = value === d;
        return (
          <button key={d} type="button" onClick={() => onChange(d)} aria-pressed={on}
            style={{ flex: 1, textTransform: 'capitalize', cursor: 'pointer',
              fontFamily: 'Bricolage Grotesque', fontSize: 14, fontWeight: 500,
              padding: '11px 12px', borderRadius: 10,
              border: on ? '1px solid rgba(240,168,80,0.55)' : '1px solid var(--hairline)',
              background: on ? 'rgba(240,168,80,0.14)' : 'transparent',
              color: on ? 'var(--olive)' : 'var(--ink-2)' }}>
            {d}
          </button>
        );
      })}
    </div>
  );
}

// Settable rating — click a star to set, click the current one to step back to it
// minus one (so a 1★ → 0 clears it).
function StarPicker({ value, onChange }) {
  const v = value || 0;
  return (
    <div style={{ display: 'flex', gap: 5, alignItems: 'center', minHeight: 44 }}>
      {[1, 2, 3, 4, 5].map((n) => (
        <button key={n} type="button" onClick={() => onChange(v === n ? n - 1 : n)} aria-label={`${n} star${n > 1 ? 's' : ''}`}
          style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 2, lineHeight: 0,
            color: n <= v ? 'var(--olive)' : 'var(--ink-4)' }}>
          <svg width="24" height="24" viewBox="0 0 24 24" fill={n <= v ? 'currentColor' : 'none'}
            stroke="currentColor" strokeWidth="1.5" strokeLinejoin="round">
            <path d="M12 2.6l2.9 5.9 6.5.95-4.7 4.6 1.1 6.45L12 18.9l-5.8 3.05 1.1-6.45-4.7-4.6 6.5-.95z" />
          </svg>
        </button>
      ))}
    </div>
  );
}

function Field({ label, hint, children }) {
  return (
    <div>
      <label style={FIELD_LABEL}>{label}{hint && <span style={{ fontFamily: 'Spectral',
        fontStyle: 'italic', fontSize: 12, color: 'var(--ink-4)', letterSpacing: 0,
        textTransform: 'none', marginLeft: 8 }}>{hint}</span>}</label>
      {children}
    </div>
  );
}

const inputStyle = { width: '100%', padding: '13px 15px', borderRadius: 10,
  background: 'rgba(0,0,0,0.3)', border: '1px solid var(--hairline)', color: 'var(--ink)',
  fontFamily: 'Bricolage Grotesque', fontSize: 16, outline: 'none', boxSizing: 'border-box' };
const areaStyle = { ...inputStyle, fontFamily: 'Spectral', fontSize: 16, lineHeight: 1.6,
  resize: 'vertical' };

function EditScreen() {
  const { layout, state, getRecipe, saveRecipe, openRecipe, back, calculateCost, estimateEffort } = useApp();
  const isNew = !!state.params.isNew;
  const existing = !isNew ? getRecipe(state.params.recipeId) : null;
  const isMobile = layout === 'mobile';
  // Live recipe (reactive) — lets the editor watch an in-flight AI effort estimate.
  const liveRecipe = !isNew ? getRecipe(state.params.recipeId) : null;
  const effortInitInfo = window.LCDomain.effortInfo(existing);

  const [form, setForm] = React.useState(() => ({
    name: existing?.name || '',
    description: existing?.description || '',
    meals: existing?.meals || [],
    effort: effortInitInfo.known ? effortInitInfo.label : '',
    servings: (existing?.servings || '').replace(/serves\s*/i, '') || '4',
    difficulty: existing?.difficulty || 'easy',
    rating: existing?.rating || 0,
    ingredients: (existing?.ingredients || []).join('\n'),
    directions: (existing?.directions || []).join('\n\n'),
    notes: existing?.notes || '',
  }));
  // Whether the effort value is currently an unconfirmed AI estimate (vs typed).
  const [accepted, setAccepted] = React.useState(effortInitInfo.known && effortInitInfo.estimated);
  const [effortErr, setEffortErr] = React.useState(null);
  const awaitingEstimate = React.useRef(false);
  const prevEffortStatus = React.useRef(liveRecipe?.effortStatus);
  const upd = (k, v) => setForm((f) => ({ ...f, [k]: v }));
  const toggleMeal = (m) => setForm((f) => ({ ...f,
    meals: f.meals.includes(m) ? f.meals.filter((x) => x !== m) : [...f.meals, m] }));
  const updEffort = (v) => { setForm((f) => ({ ...f, effort: v })); setAccepted(false); setEffortErr(null); };

  // When an AI estimate we requested lands, drop it into the field (marked as
  // an unconfirmed estimate the user can edit to confirm).
  const estimating = liveRecipe?.effortStatus === 'estimating';
  React.useEffect(() => {
    const st = liveRecipe?.effortStatus;
    if (awaitingEstimate.current && prevEffortStatus.current === 'estimating' && st === 'done' && liveRecipe) {
      setForm((f) => ({ ...f, effort: liveRecipe.effort }));
      setAccepted(true); setEffortErr(null);
      awaitingEstimate.current = false;
    }
    prevEffortStatus.current = st;
  }, [liveRecipe?.effortStatus, liveRecipe?.effort]);
  const runEstimate = () => {
    if (isNew || !existing) return;
    awaitingEstimate.current = true;
    estimateEffort(existing.id);
  };

  const save = () => {
    const trimmedEffort = form.effort.trim();
    // Gentle validation — don't silently drop a value we can't parse.
    if (trimmedEffort && window.LCDomain.parseDuration(trimmedEffort) == null) {
      setEffortErr('Couldn’t read that time — try “30 min”, “1h30”, or “1:30”.');
      return;
    }
    const id = existing?.id || (slugify(form.name) + '-' + Date.now().toString(36).slice(-4));
    const servesN = parseInt(String(form.servings).match(/\d+/)?.[0] || '0', 10) || null;
    const recipe = {
      id,
      name: form.name.trim() || 'Untitled recipe',
      description: form.description.trim(),
      // Fixed meal tags drive the library filters (CONTRACT: meals).
      meals: form.meals,
      // Imported Paprika categories kept as hidden provenance — no longer edited or shown.
      categories: existing?.categories || [],
      // Raw prep/cook/total kept as hidden provenance — never edited here now.
      prep: existing?.prep || '—',
      cook: existing?.cook || '—',
      total: existing?.total || '—',
      // Effort — one flexible field; the backend normalises effortInput → minutes.
      effortInput: trimmedEffort,
      effortEstimated: !!(trimmedEffort && accepted),
      servings: form.servings.toString().match(/serves/i) ? form.servings : `serves ${form.servings}`,
      servingsCount: servesN,
      cost: existing?.cost || '',
      difficulty: form.difficulty,
      rating: form.rating,
      ingredients: form.ingredients.split('\n').map((l) => l.replace(/\s+$/, '')).filter((l, i, arr) =>
        !(l === '' && (i === 0 || arr[i - 1] === ''))),
      directions: form.directions.split(/\n\s*\n/).map((d) => d.trim()).filter(Boolean),
      notes: form.notes.trim(),
      photo: 'placeholder',
      bg: existing?.bg || '#3a2e22',
      angle: existing?.angle || 30,
      placeholder: form.name.trim().toLowerCase() || 'your recipe',
    };
    saveRecipe(recipe);
    // Editing an already-costed recipe re-triggers the cost on save (PRD rule).
    const wasCosted = existing && (existing.costStatus === 'costed' || existing.costStatus === 'needs_attention');
    if (wasCosted && servesN) setTimeout(() => calculateCost(id, { force: true }), 40);
    openRecipe(id);
  };

  const maxW = isMobile ? '100%' : 720;
  const pad = isMobile ? '24px 18px 60px' : '40px 48px 80px';

  return (
    <Shell tab="recipes">
      {/* Top bar */}
      <div style={{ padding: isMobile ? '20px 18px' : '24px 48px', display: 'flex',
        alignItems: 'center', gap: 16, borderBottom: '1px solid var(--hairline)', flexWrap: 'wrap' }}>
        <button onClick={back} style={{ background: 'transparent', border: 'none', cursor: 'pointer',
          fontFamily: 'Bricolage Grotesque', fontSize: 13, fontWeight: 500, color: 'var(--ink-3)', padding: 0 }}>
          ← Cancel
        </button>
        <span style={{ flex: 1 }} />
        <span style={{ fontFamily: 'Bricolage Grotesque', fontSize: 10, fontWeight: 600,
          letterSpacing: '0.24em', textTransform: 'uppercase', color: 'var(--ink-4)' }}>
          {isNew ? 'New recipe' : 'Editing'}
        </span>
      </div>

      <div style={{ padding: pad }}>
        <div style={{ maxWidth: maxW, margin: '0 auto' }}>
          <h1 style={{ fontFamily: 'Bricolage Grotesque', fontWeight: 700, fontSize: isMobile ? 40 : 64,
            lineHeight: 0.95, letterSpacing: '-0.045em', color: 'var(--ink)', margin: '0 0 8px' }}>
            {isNew ? 'New' : 'Edit'}
            <span style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontWeight: 400,
              color: 'var(--olive)' }}> recipe.</span>
          </h1>
          <p style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 17, color: 'var(--ink-3)',
            margin: '0 0 36px' }}>
            Fill in what you know — everything stays editable later.
          </p>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 26 }}>
            <Field label="Recipe name">
              <input value={form.name} onChange={(e) => upd('name', e.target.value)}
                placeholder="e.g. Sichuan-style cold chicken with chilli oil" style={inputStyle} />
            </Field>
            <Field label="Description" hint="the one-line pitch">
              <textarea value={form.description} onChange={(e) => upd('description', e.target.value)}
                rows={2} placeholder="e.g. A weeknight standby…" style={areaStyle} />
            </Field>
            <Field label="Meals" hint="tap the ones it fits">
              <MealPicker value={form.meals} onToggle={toggleMeal} />
            </Field>

            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
              <Field label="Effort" hint="active hands-on time">
                <div style={{ position: 'relative' }}>
                  <input value={estimating ? '' : form.effort} onChange={(e) => updEffort(e.target.value)}
                    disabled={estimating}
                    placeholder={estimating ? 'Estimating…' : 'e.g. 30 min · 1h30 · 1:30'}
                    style={{ ...inputStyle, borderColor: effortErr ? 'var(--olive)' : 'var(--hairline)' }} />
                  {estimating && (
                    <span style={{ position: 'absolute', right: 13, top: '50%', transform: 'translateY(-50%)',
                      display: 'inline-flex' }}>
                      <span style={{ display: 'block', width: 14, height: 14, borderRadius: '50%',
                        border: '2px solid rgba(240,168,80,0.28)', borderTopColor: 'var(--olive)',
                        boxSizing: 'border-box', animation: 'lcSpin 0.7s linear infinite' }} />
                    </span>
                  )}
                </div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 8, flexWrap: 'wrap' }}>
                  <button type="button" onClick={runEstimate} disabled={isNew || estimating}
                    title={isNew ? 'Save the recipe first to estimate' : 'Estimate active time with AI'}
                    style={{ display: 'inline-flex', alignItems: 'center', gap: 6,
                      cursor: (isNew || estimating) ? 'default' : 'pointer', padding: '5px 11px', borderRadius: 999,
                      border: '1px solid rgba(240,168,80,0.42)',
                      background: (isNew || estimating) ? 'rgba(240,168,80,0.05)' : 'rgba(240,168,80,0.10)',
                      color: 'var(--olive)', opacity: (isNew || estimating) ? 0.5 : 1,
                      fontFamily: 'Bricolage Grotesque', fontSize: 12, fontWeight: 600 }}>
                    ✦ {estimating ? 'Estimating…' : 'Estimate with AI'}
                  </button>
                  {effortErr
                    ? <span style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 12.5, color: 'var(--olive)' }}>{effortErr}</span>
                    : isNew
                      ? <span style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 12.5, color: 'var(--ink-4)' }}>save first to estimate</span>
                      : null}
                </div>
              </Field>
              <Field label="Serves" hint="needed for cost"><input value={form.servings} onChange={(e) => upd('servings', e.target.value)}
                placeholder="e.g. 4" style={inputStyle} /></Field>
            </div>

            <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', gap: 14, alignItems: 'start' }}>
              <Field label="Difficulty">
                <DifficultyPicker value={form.difficulty} onChange={(v) => upd('difficulty', v)} />
              </Field>
              <Field label="Rating" hint="how it turned out">
                <StarPicker value={form.rating} onChange={(v) => upd('rating', v)} />
              </Field>
            </div>

            <Field label="Ingredients" hint="one per line">
              <p style={{ fontFamily: 'Spectral', fontStyle: 'italic', fontSize: 13.5, color: 'var(--ink-3)',
                margin: '0 0 10px' }}>
                Start a line with words ending in a colon — like <span style={{ color: 'var(--olive)' }}>For the chilli oil:</span> —
                to group ingredients into sections.
              </p>
              <textarea value={form.ingredients} onChange={(e) => upd('ingredients', e.target.value)}
                rows={isMobile ? 8 : 10}
                placeholder={'e.g. For the chicken:\n1 whole chicken\n6 spring onions\n\nFor the chilli oil:\n½ cup neutral oil'}
                style={areaStyle} />
            </Field>

            <Field label="Method" hint="one step per paragraph (blank line between)">
              <textarea value={form.directions} onChange={(e) => upd('directions', e.target.value)}
                rows={isMobile ? 8 : 10}
                placeholder={'e.g. Bring a large pot of water to the boil…\n\nLift the chicken out and plunge into iced water…'}
                style={areaStyle} />
            </Field>

            <Field label="Your notes" hint="just for you">
              <textarea value={form.notes} onChange={(e) => upd('notes', e.target.value)}
                rows={2} placeholder="Add any useful notes here" style={{ ...areaStyle, fontFamily: 'Caveat', fontSize: 22 }} />
            </Field>

            <div style={{ display: 'flex', gap: 12, marginTop: 8 }}>
              <FButton size="l" onClick={save} style={{ flex: isMobile ? 1 : 'none', minHeight: 54 }}>
                {isNew ? 'Save recipe' : 'Save changes'} <span style={{ fontSize: 18 }}>→</span>
              </FButton>
              <FButton size="l" variant="ghost" onClick={back} style={{ minHeight: 54 }}>Cancel</FButton>
            </div>
          </div>
        </div>
      </div>
    </Shell>
  );
}

Object.assign(window, { EditScreen });
