// TextiGreen v4 · input form + settings

const { useState: useSf4, useMemo: useMf4 } = React;

const STAGES = [
  { value: 'fiber', label: 'Fiber' },
  { value: 'yarn', label: 'Yarn' },
  { value: 'fabric', label: 'Fabric' },
  { value: 'dyed_fabric', label: 'Dyed fabric' },
];

// Beginner-friendly help text (shown via the "i" tooltips / helper lines)
const HELP = {
  composition: 'The fibre(s) your fabric is made of, with each one\'s share by weight (up to 5, totalling 100%). The result is the weight-weighted footprint of the fibres.',
  stage: 'How far along the supply chain to estimate — the "system boundary". Fiber = raw fibre only · Yarn = fibre spun into yarn · Fabric = yarn woven/knitted into cloth · Dyed fabric = cloth coloured & finished. Pick the stage your product has reached. Numbers from different stages are NOT comparable.',
  origin: 'Where the fabric is made. Each region\'s electricity-grid carbon intensity is applied to the power-using steps — so the same fabric has a different footprint in, say, Vietnam vs Italy vs the US.',
  dyeing: 'Optional. The colouring process — shown as its own block, NOT added to the fibre total (it sits on a different boundary).',
  fabrication: 'Optional. How yarn is turned into fabric — shown as a separate electricity block.',
  boiler_fuel: 'Optional. The fuel your factory\'s boiler burns to make steam/heat. Switching it (coal → gas → biomass) re-bases the heat part of the footprint; it does not add heat twice.',
};
const DYE_LABEL = { conventional: 'Conventional (water-based)', d5: 'D5 waterless (non-aqueous)', s1: 'S-1 binary solvent', yuan2013: 'Continuous pad-dyeing (Yuan 2013)' };
const DYE_DESC = {
  conventional: 'Standard water-based dyeing — the most common route, and the default reference.',
  d5: 'Waterless silicone-solvent (D5) dyeing: much less water & energy, but it may RAISE toxicity — don\'t read lower GWP as simply "better".',
  s1: 'S-1 binary organic-solvent dyeing route.',
  yuan2013: 'Continuous pad-dyeing from Yuan (2013). Its boundary excludes cotton growing & greige fabric, so it is NOT directly comparable to the others.',
};
const FAB_LABEL = { weaving: 'Weaving (loom)', knitting: 'Knitting' };
const FAB_DESC = {
  weaving: 'Weaving interlaces yarns on a loom — electricity-heavy, and it climbs steeply for finer yarns.',
  knitting: 'Knitting loops yarns together — generally uses far less electricity than weaving.',
};

function EstimatorForm({ catalogs, value, onChange }) {
  const { fibers, geos, processes, fuels } = catalogs;
  const v = value;
  const comp = v.composition;
  const total = Math.round(comp.reduce((s, c) => s + (c.fraction || 0) * 100, 0));

  const set = (patch) => onChange({ ...v, ...patch });
  const setRow = (i, patch) => set({ composition: comp.map((c, j) => j === i ? { ...c, ...patch } : c) });
  const removeRow = (i) => set({ composition: comp.filter((_, j) => j !== i) });
  const addRow = () => {
    if (comp.length >= 5) return;
    const used = new Set(comp.map(c => c.fiber));
    const next = (fibers || []).find(f => !used.has(f.fiber));
    const remaining = Math.max(0, 1 - comp.reduce((s, c) => s + c.fraction, 0));
    set({ composition: [...comp, { fiber: next ? next.fiber : '', fraction: remaining > 0 ? remaining : 0.1 }] });
  };
  const normalize = () => {
    const sum = comp.reduce((s, c) => s + c.fraction, 0);
    if (!sum) return;
    set({ composition: comp.map(c => ({ ...c, fraction: Math.round((c.fraction / sum) * 100) / 100 })) });
  };

  const usedFibers = comp.map(c => c.fiber);

  // origin groups
  const originGroups = useMf4(() => {
    const g = { 'China': [], 'United States': [], 'Other countries': [] };
    (geos || []).forEach(geo => {
      const item = { value: geo.geo, label: geo.geo.replace('China_national', 'China (national avg)'), sub: geo.factor_value.toFixed(3) };
      if (geo.scope === 'province' || geo.geo === 'China_national') g['China'].push(item);
      else if (geo.scope === 'subregion' || geo.geo.startsWith('US')) g['United States'].push(item);
      else g['Other countries'].push(item);
    });
    return Object.entries(g).filter(([, items]) => items.length).map(([label, items]) => ({ label, items }));
  }, [geos]);

  const dyeOpts = (processes?.dyeing || []);
  const fabOpts = (processes?.fabrication || []);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 26 }}>

      {/* Composition */}
      <section>
        <Label n={1} hint={
          <span style={{ color: total === 100 ? 'var(--accent)' : 'var(--warn-fg)', fontFamily: 'var(--mono)', fontSize: 11 }}>
            {total}% {total === 100 ? '✓' : 'under'}
          </span>
        } info={HELP.composition}>Composition</Label>

        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          {comp.map((c, i) => {
            const f = (fibers || []).find(x => x.fiber === c.fiber);
            const otherSum = comp.reduce((s, row, j) => j !== i ? s + (row.fraction || 0) : s, 0);
            const maxPct = Math.max(0, Math.round((1 - otherSum) * 100));
            const valuePct = Math.min(Math.round(c.fraction * 100), maxPct);
            return (
              <div key={i} style={{ background: 'var(--surface)', border: '1px solid var(--line)', padding: '12px 12px 14px' }}>
                <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginBottom: 10 }}>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <Select value={c.fiber} onChange={val => setRow(i, { fiber: val })} placeholder="Select fiber">
                      {(fibers || []).map(fb => (
                        <option key={fb.fiber} value={fb.fiber} disabled={usedFibers.includes(fb.fiber) && fb.fiber !== c.fiber}>
                          {fb.label}{fb.default_gwp != null ? ` · ${fb.default_gwp} kg` : ''}
                        </option>
                      ))}
                    </Select>
                  </div>
                  {comp.length > 1 && (
                    <button type="button" onClick={() => removeRow(i)} aria-label="Remove" style={{
                      width: 36, height: 44, border: '1px solid var(--line)', background: 'var(--bg)',
                      color: 'var(--muted)', cursor: 'pointer', fontSize: 18,
                    }}>×</button>
                  )}
                </div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                  <input type="range" min={0} max={maxPct} value={valuePct}
                    onChange={e => setRow(i, { fraction: parseInt(e.target.value) / 100 })}
                    style={{ flex: 1, accentColor: 'var(--accent)', height: 24, cursor: 'pointer' }} />
                  <div style={{ width: 48, textAlign: 'right', fontFamily: 'var(--mono)', fontSize: 14, color: 'var(--fg)', fontWeight: 500 }}>
                    {Math.round(c.fraction * 100)}%
                  </div>
                </div>
                {f && (
                  <div style={{ marginTop: 8, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, flexWrap: 'wrap' }}>
                    <span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--muted)' }}>{f.boundary}</span>
                    <span style={{ display: 'inline-flex', gap: 8, alignItems: 'center' }}>
                      <ConfidenceBadge value={f.confidence} />
                      <SourceChip id={f.source_id} caveat={f.caveat} />
                    </span>
                  </div>
                )}
              </div>
            );
          })}
        </div>

        <div style={{ display: 'flex', gap: 10, marginTop: 12 }}>
          <button type="button" onClick={addRow} disabled={comp.length >= 5} style={{
            flex: 1, padding: '12px', border: '1px dashed var(--fg)', background: 'var(--bg)', color: 'var(--fg)',
            fontSize: 13, cursor: comp.length >= 5 ? 'default' : 'pointer', opacity: comp.length >= 5 ? 0.4 : 1,
            fontFamily: 'var(--sans)', minHeight: 44,
          }}>+ Add fiber {comp.length >= 5 && '(max 5)'}</button>
          {total !== 100 && total > 0 && (
            <button type="button" onClick={normalize} style={{
              padding: '12px 14px', border: '1px solid var(--fg)', background: 'var(--fg)', color: 'var(--bg)',
              fontSize: 13, cursor: 'pointer', minHeight: 44, fontFamily: 'var(--sans)',
            }}>Normalize</button>
          )}
        </div>
      </section>

      {/* Stage */}
      <section>
        <Label n={2} info={HELP.stage}>Stage / boundary</Label>
        <Segmented options={STAGES} value={v.stage} onChange={s => set({ stage: s })} />
      </section>

      {/* Origin */}
      <section>
        <Label n={3} hint="grid re-base" info={HELP.origin}>Factory origin</Label>
        <SearchSelect value={v.origin} onChange={o => set({ origin: o })} groups={originGroups} placeholder="Search origin (province / state / country)" />
      </section>

      {/* Optional knobs */}
      <section style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
        <Label info="These inputs are optional. Each is reported as its own block — they are NOT added into the fibre total, as they sit on a different system boundary.">Optional</Label>

        <div>
          <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 8, display: 'flex', alignItems: 'center' }}>Dyeing <InfoDot text={HELP.dyeing} /></div>
          <Select value={v.dyeing} onChange={d => set({ dyeing: d })} placeholder="None">
            {dyeOpts.map(d => <option key={d.process} value={d.process}>{DYE_LABEL[d.process] || d.label || d.process}</option>)}
          </Select>
          {v.dyeing && DYE_DESC[v.dyeing] && (
            <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 6, lineHeight: 1.5 }}>{DYE_DESC[v.dyeing]}</div>
          )}
        </div>

        <div>
          <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 8, display: 'flex', alignItems: 'center' }}>Fabrication <InfoDot text={HELP.fabrication} /></div>
          <Select value={v.fabrication} onChange={fb => set({ fabrication: fb })} placeholder="None">
            {fabOpts.map(f => <option key={f.stage} value={f.stage}>{FAB_LABEL[f.stage] || f.stage}</option>)}
          </Select>
          {v.fabrication && FAB_DESC[v.fabrication] && (
            <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 6, lineHeight: 1.5 }}>{FAB_DESC[v.fabrication]}</div>
          )}
        </div>

        <div>
          <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 8, display: 'flex', alignItems: 'center' }}>Boiler fuel <span style={{ fontFamily: 'var(--mono)', fontSize: 11, marginLeft: 6 }}>(thermal re-base)</span><InfoDot text={HELP.boiler_fuel} /></div>
          <Select value={v.boiler_fuel} onChange={bf => set({ boiler_fuel: bf })} placeholder="None (baseline: coal)">
            {(fuels || []).map(f => <option key={f.fuel} value={f.fuel}>{f.fuel.replace(/_/g, ' ')}</option>)}
          </Select>
        </div>
      </section>
    </div>
  );
}

// ─── Settings overlay ───────────────────────────────────────────────
function SettingsPanel({ conn, onClose }) {
  const [base, setBase] = useSf4(conn.baseURL);
  const [busy, setBusy] = useSf4(false);
  const test = async () => { setBusy(true); await window.TGApi.setBase(base); setBusy(false); };

  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 100, background: 'rgba(10,10,10,0.4)', display: 'flex', alignItems: 'flex-start', justifyContent: 'center', padding: '60px 20px', overflowY: 'auto' }}>
      <div onClick={e => e.stopPropagation()} style={{ width: '100%', maxWidth: 420, background: 'var(--bg)', border: '1px solid var(--fg)', padding: 24 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
          <span style={{ fontSize: 15, fontWeight: 600, fontFamily: 'var(--display)', color: 'var(--fg)' }}>API connection</span>
          <button type="button" onClick={onClose} style={{ width: 32, height: 32, border: '1px solid var(--line)', background: 'var(--bg)', cursor: 'pointer', color: 'var(--muted)', fontSize: 16 }}>×</button>
        </div>

        <div style={{ marginBottom: 18 }}>
          <div style={{ fontSize: 11, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--muted)', fontFamily: 'var(--mono)', marginBottom: 10 }}>Mode</div>
          <Segmented compact options={[{ value: 'auto', label: 'Auto' }, { value: 'live', label: 'Live only' }, { value: 'offline', label: 'Offline' }]} value={conn.mode} onChange={m => window.TGApi.setMode(m)} />
          <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 8, lineHeight: 1.5 }}>
            {conn.mode === 'auto' && 'Use backend when reachable, fall back to mock otherwise.'}
            {conn.mode === 'live' && 'Backend only — errors surface (use to confirm the contract).'}
            {conn.mode === 'offline' && 'Never call the network — always use the bundled mock.'}
          </div>
        </div>

        <div style={{ marginBottom: 18 }}>
          <div style={{ fontSize: 11, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--muted)', fontFamily: 'var(--mono)', marginBottom: 10 }}>Base URL</div>
          <div style={{ display: 'flex', gap: 8 }}>
            <input value={base} onChange={e => setBase(e.target.value)} placeholder="http://127.0.0.1:8000" spellCheck={false} style={{
              flex: 1, padding: '11px 12px', border: '1px solid var(--line)', background: 'var(--bg)', color: 'var(--fg)', fontSize: 13, fontFamily: 'var(--mono)', minHeight: 44,
            }} />
            <button type="button" onClick={test} disabled={busy} style={{ padding: '0 16px', border: '1px solid var(--fg)', background: 'var(--fg)', color: 'var(--bg)', cursor: 'pointer', fontSize: 13, minHeight: 44, opacity: busy ? 0.5 : 1 }}>{busy ? '…' : 'Test'}</button>
          </div>
        </div>

        <div style={{ padding: '12px 14px', background: 'var(--surface)', fontFamily: 'var(--mono)', fontSize: 12, lineHeight: 1.7 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between' }}>
            <span style={{ color: 'var(--muted)' }}>status</span>
            <span style={{ color: conn.status === 'online' ? 'var(--accent)' : 'var(--fg)' }}>
              {conn.status === 'online' ? '● live' : conn.status === 'checking' ? '○ checking' : '○ offline'}
            </span>
          </div>
          {conn.lastError && conn.status === 'offline' && conn.mode !== 'offline' && (
            <div style={{ marginTop: 8, color: 'var(--band-red)', fontSize: 11, lineHeight: 1.5 }}>{conn.lastError}</div>
          )}
        </div>

        <div style={{ marginTop: 16, fontSize: 11, color: 'var(--muted)', lineHeight: 1.55 }}>
          Endpoints: <code style={{ fontFamily: 'var(--mono)' }}>/v1/fibers · /v1/geos · /v1/processes · /v1/fuels · POST /v1/estimate</code>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { EstimatorForm, SettingsPanel, STAGES });
