/* ===================================================================
   KabelFlux v5 — Wires view
   - Inline-edit cells w/ save-flash + error-shake (M4 fix)
   - Color cells pair color + IEC 2-letter code (M3 — no color-only signal)
   - Density-aware row height (driven by --density-row)
   - Status column with icon + word for open wires (M3)
   - Sticky header + sticky first column
   =================================================================== */

/* Specialized color cell: shows swatch + IEC code + name; click → inline select */
const ColorCell = ({ value, onSave }) => {
  const [editing, setEditing] = useState(false);
  const [v, setV] = useState(value);
  const [flash, setFlash] = useState(null);
  const ref = useRef();
  useEffect(() => setV(value), [value]);
  useEffect(() => { if (editing && ref.current) ref.current.focus(); }, [editing]);

  const commit = async (newV) => {
    if (newV === value) { setEditing(false); return; }
    try {
      await onSave(newV);
      setEditing(false);
      setFlash('ok');
      setTimeout(() => setFlash(null), 1100);
    } catch (e) {
      setFlash('err');
      setTimeout(() => setFlash(null), 400);
    }
  };

  const cls = 'kf-cell color-cell' + (editing ? ' editing' : '') + (flash === 'ok' ? ' flash-save' : '') + (flash === 'err' ? ' shake-err' : '');

  if (editing) {
    return (
      <td className={cls}>
        <select ref={ref} className="kf-cell-input" value={v}
                onChange={e => { setV(e.target.value); commit(e.target.value); }}
                onBlur={() => setEditing(false)}
                onKeyDown={e => { if (e.key === 'Escape') setEditing(false); }}>
          {Object.keys(COLOR_HEX).map(c => <option key={c} value={c}>{c}</option>)}
        </select>
      </td>
    );
  }
  return (
    <td className={cls} onClick={() => setEditing(true)} tabIndex={0}
        onKeyDown={e => { if (e.key === 'Enter' || e.key === 'F2') setEditing(true); }}>
      <div className="kf-color-cell">
        <span className="kf-color-sw" style={{ background: COLOR_HEX[value] }}/>
        <span className="kf-color-code">{COLOR_CODE[value]}</span>
        <span className="kf-color-name">{value}</span>
      </div>
    </td>
  );
};

const WiresView = ({ density='cozy', wires=[], connectors=[], loading=false, realPid=null, onRefresh, onImportCsv }) => {
  const toast = useToast();
  const [data, setData] = useState(wires);
  // Re-sync local state whenever the project's wire list changes.
  useEffect(() => { setData(wires); }, [wires]);
  const [filter, setFilter] = useState('');
  const [filterColor, setFilterColor] = useState('');
  const [filterShield, setFilterShield] = useState(false);
  const [confirm, setConfirm] = useState(null);
  const [selRow, setSelRow] = useState(null);
  const [showCreate, setShowCreate] = useState(false);

  const save = (id, field) => async (value) => {
    const w = data.find(x => x.id === id);
    if (!w || !w._raw || !w._raw.id) throw new Error('Wire has no backend id');
    // Build a complete wire object with the patched field so we PUT the
    // full row (backend's update_wire replaces all columns).
    const patched = { ...w, [field]: value };
    try {
      await kfxUpdateWire(w._raw.id, patched);
      setData(d => d.map(x => x.id === id ? patched : x));
      toast.ok(`Saved · ${field}`, `Wire ${w.fromConn}:${w.fromPin} → ${w.toConn}:${w.toPin} updated`);
    } catch (e) {
      toast.err(`Could not save ${field}`, (e && e.message) || 'Server error');
      throw e;
    }
  };
  const del = (w) => {
    setConfirm({
      title: `Delete wire ${w.cavity} (${w.fromConn}:${w.fromPin} → ${w.toConn}:${w.toPin})?`,
      body: <>This will remove the wire from the harness. The connection between <b>{w.fromConn}:{w.fromPin}</b> and <b>{w.toConn}:{w.toPin}</b> will be lost.</>,
      onConfirm: async () => {
        if (!w._raw || !w._raw.id) { toast.err('No backend id for this wire'); return; }
        try {
          await kfxDeleteWire(w._raw.id);
          setData(d => d.filter(x => x.id !== w.id));
          toast.ok(`Deleted wire ${w.fromConn}:${w.fromPin} → ${w.toConn}:${w.toPin}`);
          if (onRefresh) onRefresh();
        } catch (e) {
          toast.err('Could not delete wire', (e && e.message) || 'Server error');
        }
      }
    });
  };

  const createWire = async (draft) => {
    if (!realPid) throw new Error('No project loaded');
    await kfxCreateWire(realPid, draft);
    toast.ok('Wire added', `${draft.fromConn}:${draft.fromPin} → ${draft.toConn}:${draft.toPin}`);
    setShowCreate(false);
    if (onRefresh) await onRefresh();
  };

  const filtered = data.filter(w => {
    const q = filter.trim().toLowerCase();
    const ok = !q || [w.net, w.color, w.gauge, w.fromConn, w.toConn, w.notes, w.cable].some(v => (v + '').toLowerCase().includes(q));
    const co = !filterColor || w.color === filterColor;
    const sh = !filterShield || w.shield;
    return ok && co && sh;
  });

  if (loading && data.length === 0) {
    return (
      <div className="kf-view">
        <ViewHeader title="Wires"/>
        <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10, color: 'var(--t-3)' }}>
          <Spinner size={16}/> <span>Loading wires…</span>
        </div>
      </div>
    );
  }

  return (
    <div className="kf-view">
      <ViewHeader
        title="Wires"
        count={filtered.length}
        countTotal={data.length}
        actions={
          <>
            <Btn kind="ghost" icon="filter" size="sm">Filter</Btn>
            <Btn kind="ghost" icon="sort" size="sm">Sort</Btn>
            <Btn kind="ghost" icon="import_" size="sm" onClick={onImportCsv}>Import CSV</Btn>
            <Btn kind="primary" icon="plus" onClick={() => setShowCreate(true)}>New wire</Btn>
          </>
        }/>

      {/* Filter bar */}
      <div className="kf-toolbar">
        <div className="kf-search">
          <Icon name="search" size={14} stroke="var(--t-3)"/>
          <input
            type="text"
            placeholder="Filter by net, color, gauge, pin reference…"
            value={filter}
            onChange={e => setFilter(e.target.value)}
            aria-label="Filter wires"/>
          {filter && <button className="kf-search-clear" onClick={() => setFilter('')} aria-label="Clear filter"><Icon name="x" size={12}/></button>}
          <span className="kf-search-kbd"><Kbd>/</Kbd></span>
        </div>
        <Chip size="sm" tone="info" active={filterShield} onClick={() => setFilterShield(!filterShield)} icon="bolt">Shielded only</Chip>
        <select className="kf-select" value={filterColor} onChange={e => setFilterColor(e.target.value)} aria-label="Filter by color">
          <option value="">All colors</option>
          {Object.keys(COLOR_HEX).map(c => <option key={c}>{c}</option>)}
        </select>
        <div className="spacer"/>
        <div className="kf-toolbar-info num">{filtered.length} / {data.length} wires · {filtered.filter(w => w.shield).length} shielded · {filtered.filter(w => w.twisted).length} twisted</div>
      </div>

      {/* Table */}
      <div className="kf-table-wrap">
        {filtered.length === 0 ? (
          <EmptyState icon="wires"
            title={filter ? 'No wires match this filter' : 'No wires in this harness yet'}
            hint={filter ? 'Try a different search term, or clear the active filters.' : 'Add wires manually, import from a CSV/Komax, or trace pin-to-pin in Wire mode on the Layout tab.'}
            action={!filter && <Btn kind="primary" icon="plus" onClick={() => setShowCreate(true)}>Add wire</Btn>}
            secondary={!filter && <Btn kind="outline" icon="import_" onClick={onImportCsv}>Import CSV</Btn>}
          />
        ) : (
          <table className="kf-table">
            <thead>
              <tr>
                <th className="kf-th-sticky">Cav</th>
                <th>Status</th>
                <th>From</th>
                <th>To</th>
                <th>Color</th>
                <th>Gauge</th>
                <th>Spec</th>
                <th className="num">Length (mm)</th>
                <th>Cable</th>
                <th>Net</th>
                <th>Notes</th>
                <th aria-label="actions"/>
              </tr>
            </thead>
            <tbody>
              {filtered.map(w => {
                const isOpen = (w.notes || '').toLowerCase().includes('open');
                return (
                  <tr key={w.id} className={selRow === w.id ? 'sel' : ''} onClick={() => setSelRow(w.id)}>
                    <td className="kf-td-sticky mono">{w.cavity}</td>
                    <td>
                      {isOpen ? (
                        <Chip size="sm" tone="danger" icon="warn">Open</Chip>
                      ) : (
                        <Chip size="sm" tone="success" icon="ok">Routed</Chip>
                      )}
                    </td>
                    <td className="mono"><b>{w.fromConn}</b>:{w.fromPin}</td>
                    <td className="mono"><b>{w.toConn}</b>:{w.toPin}</td>
                    <ColorCell value={w.color} onSave={save(w.id, 'color')}/>
                    <InlineCell mono value={w.gauge} type="select" options={['18 AWG','20 AWG','22 AWG','24 AWG','26 AWG','28 AWG']} onSave={save(w.id, 'gauge')}/>
                    <InlineCell value={w.spec} type="select" options={['Teflon','PVC','XLPE','Silicone','Kapton']} onSave={save(w.id, 'spec')}/>
                    <InlineCell mono align="right" value={w.length} type="number" onSave={save(w.id, 'length')}/>
                    <td>
                      <span className="kf-cable-mini">
                        {w.shield && <span className="kf-cable-dot" style={{ color: 'var(--info)' }} title="Shielded">▓</span>}
                        {w.twisted && <span className="kf-cable-dot" style={{ color: 'var(--violet)' }} title="Twisted">∿</span>}
                        {w.cable}
                      </span>
                    </td>
                    <td className="mono"><b>{w.net}</b></td>
                    <InlineCell value={w.notes} onSave={save(w.id, 'notes')}/>
                    <td>
                      <div className="kf-row-actions">
                        <IconBtn icon="copy"  label={`Duplicate wire ${w.cavity}`}/>
                        <IconBtn icon="trash" label={`Delete wire ${w.cavity}`} danger onClick={() => del(w)}/>
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </div>

      {/* Confirm modal */}
      {confirm && (
        <ConfirmModal
          {...confirm}
          danger
          confirmLabel="Delete wire"
          onClose={() => setConfirm(null)}/>
      )}

      {/* Create modal */}
      {showCreate && (
        <CreateWireModal
          connectors={connectors}
          onCancel={() => setShowCreate(false)}
          onCreate={createWire}/>
      )}
    </div>
  );
};

/* ---------- Create wire modal — controlled form, calls backend on submit ---------- */
const CreateWireModal = ({ connectors=[], onCreate, onCancel }) => {
  const [draft, setDraft] = useState({
    fromConn: connectors[0]?.id || '',
    fromPin: '1',
    toConn:  connectors[1]?.id || connectors[0]?.id || '',
    toPin:   '1',
    color:   'Black',
    gauge:   '22 AWG',
    spec:    '',
    length:  500,
    cable:   'Single core',
    net:     '',
    shield:  false,
    twisted: false,
    notes:   '',
  });
  const setF = (k, v) => setDraft(d => ({ ...d, [k]: v }));
  const canSubmit = !!(draft.fromConn && draft.toConn && draft.fromPin !== '' && draft.toPin !== '');
  return (
    <Modal title="New wire" onClose={onCancel} footer={
      <>
        <Btn kind="ghost" onClick={onCancel}>Cancel</Btn>
        <AsyncBtn kind="primary" icon="plus" disabled={!canSubmit} busyLabel="Saving…"
                  onClick={async () => { if (canSubmit) await onCreate(draft); }}>
          Create wire
        </AsyncBtn>
      </>
    }>
      <form className="kf-form" onSubmit={e => e.preventDefault()}>
        <div className="kf-form-row">
          <div className="kf-field">
            <label htmlFor="nw-color">Color</label>
            <select id="nw-color" className="kf-input" value={draft.color} onChange={e => setF('color', e.target.value)}>
              {Object.keys(COLOR_HEX).map(c => <option key={c}>{c}</option>)}
            </select>
          </div>
          <div className="kf-field">
            <label htmlFor="nw-gauge">Gauge</label>
            <select id="nw-gauge" className="kf-input" value={draft.gauge} onChange={e => setF('gauge', e.target.value)}>
              {['18 AWG','20 AWG','22 AWG','24 AWG','26 AWG','28 AWG'].map(g => <option key={g}>{g}</option>)}
            </select>
          </div>
        </div>
        <div className="kf-form-row">
          <div className="kf-field">
            <label htmlFor="nw-from">From connector</label>
            <select id="nw-from" className="kf-input" value={draft.fromConn} onChange={e => setF('fromConn', e.target.value)}>
              {connectors.map(c => <option key={c.id} value={c.id}>{c.id}{c.label && c.label.includes(' — ') ? ' — ' + c.label.split(' — ')[1] : ''}</option>)}
            </select>
          </div>
          <div className="kf-field">
            <label htmlFor="nw-fpin">From pin</label>
            <input id="nw-fpin" type="text" className="kf-input num"
                   value={draft.fromPin} onChange={e => setF('fromPin', e.target.value)}/>
          </div>
        </div>
        <div className="kf-form-row">
          <div className="kf-field">
            <label htmlFor="nw-to">To connector</label>
            <select id="nw-to" className="kf-input" value={draft.toConn} onChange={e => setF('toConn', e.target.value)}>
              {connectors.map(c => <option key={c.id} value={c.id}>{c.id}{c.label && c.label.includes(' — ') ? ' — ' + c.label.split(' — ')[1] : ''}</option>)}
            </select>
          </div>
          <div className="kf-field">
            <label htmlFor="nw-tpin">To pin</label>
            <input id="nw-tpin" type="text" className="kf-input num"
                   value={draft.toPin} onChange={e => setF('toPin', e.target.value)}/>
          </div>
        </div>
        <div className="kf-form-row">
          <div className="kf-field" style={{ flex: 1 }}>
            <label htmlFor="nw-net">Net / signal</label>
            <input id="nw-net" type="text" placeholder="e.g. SENSE-B" className="kf-input"
                   value={draft.net} onChange={e => setF('net', e.target.value)}/>
          </div>
          <div className="kf-field">
            <label htmlFor="nw-len">Length (mm)</label>
            <input id="nw-len" type="number" className="kf-input num"
                   value={draft.length} onChange={e => setF('length', +e.target.value || 0)}/>
          </div>
        </div>
        <div className="kf-form-row">
          <div className="kf-field" style={{ flex: 1 }}>
            <label htmlFor="nw-notes">Notes</label>
            <input id="nw-notes" type="text" className="kf-input"
                   value={draft.notes} onChange={e => setF('notes', e.target.value)}/>
          </div>
        </div>
        <div className="kf-form-row">
          <div className="kf-checkfield">
            <input id="nw-shield" type="checkbox" checked={draft.shield} onChange={e => setF('shield', e.target.checked)}/>
            <label htmlFor="nw-shield">Shielded</label>
          </div>
          <div className="kf-checkfield">
            <input id="nw-tw" type="checkbox" checked={draft.twisted} onChange={e => setF('twisted', e.target.checked)}/>
            <label htmlFor="nw-tw">Twisted pair</label>
          </div>
        </div>
      </form>
    </Modal>
  );
};

/* ---------- Shared view header ---------- */
const ViewHeader = ({ title, hint, count, countTotal, actions, badge }) => (
  <div className="kf-view-head">
    <div className="kf-view-head-l">
      <h1>{title}</h1>
      {badge}
      {count !== undefined && (
        <span className="kf-view-count num">
          {count}{countTotal !== undefined && count !== countTotal && <span style={{color:'var(--t-3)'}}> / {countTotal}</span>}
        </span>
      )}
    </div>
    {hint && <div className="kf-view-hint">{hint}</div>}
    <div className="kf-view-head-r">{actions}</div>
  </div>
);

const STYLE = `
.kf-view { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.kf-view-head {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 18px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-1);
  flex-wrap: wrap;
}
.kf-view-head-l { display: flex; align-items: baseline; gap: 12px; min-width: 0; }
.kf-view-head-l h1 { font-family: var(--f-display); font-size: 20px; font-weight: 700; letter-spacing: -.3px; }
.kf-view-count { font-size: 13px; color: var(--t-2); font-weight: 500; }
.kf-view-hint  { font-size: 12px; color: var(--t-3); }
.kf-view-head-r { margin-left: auto; display: flex; gap: 6px; }

.kf-toolbar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 18px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--line);
  font-size: 12px;
}
.kf-toolbar-info { color: var(--t-3); font-size: 11px; }

.kf-search {
  position: relative;
  display: flex; align-items: center; gap: 7px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  padding: 0 8px 0 10px;
  min-width: 320px;
  height: 32px;
}
.kf-search input {
  flex: 1;
  background: transparent; border: none; outline: none;
  color: var(--t-1); font-size: 12.5px; font-family: var(--f-sans);
}
.kf-search input::placeholder { color: var(--t-4); }
.kf-search-clear {
  background: transparent; border: none; color: var(--t-3);
  cursor: pointer; display: flex; align-items: center;
  padding: 4px; border-radius: 3px;
}
.kf-search-clear:hover { background: var(--bg-3); color: var(--t-1); }
.kf-search-kbd { display: flex; align-items: center; padding-left: 4px; border-left: 1px solid var(--line); margin-left: 2px; }

.kf-select {
  height: 32px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  color: var(--t-1);
  font-size: 12px;
  padding: 0 8px;
  font-family: var(--f-sans);
}

/* Table */
.kf-table-wrap { flex: 1; overflow: auto; }
.kf-table {
  width: 100%;
  border-collapse: separate; border-spacing: 0;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.kf-table th {
  position: sticky; top: 0; z-index: 2;
  background: var(--bg-2);
  color: var(--t-3);
  font-size: 9.5px; font-weight: 700; letter-spacing: .8px; text-transform: uppercase;
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--line-strong);
  white-space: nowrap;
}
.kf-table th.num { text-align: right; }
.kf-table th.kf-th-sticky { position: sticky; left: 0; z-index: 3; background: var(--bg-2); }
.kf-table td {
  padding: 7px 10px;
  height: var(--density-row);
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
  color: var(--t-1);
  white-space: nowrap;
}
.kf-table td.kf-td-sticky { position: sticky; left: 0; background: var(--bg-1); color: var(--t-3); font-weight: 600; }
.kf-table tr:hover td { background: rgba(74,158,255,.05); }
.kf-table tr:hover td.kf-td-sticky { background: rgba(74,158,255,.08); }
.kf-table tr.sel td { background: rgba(74,158,255,.12) !important; }
.kf-table td.mono { font-family: var(--f-mono); }
.kf-table td b { color: var(--t-1); font-weight: 600; }

.kf-color-cell { display: inline-flex; align-items: center; gap: 8px; }
.kf-color-sw   { width: 22px; height: 10px; border-radius: 2px; border: 1px solid rgba(255,255,255,.1); }
.kf-color-code { font-family: var(--f-mono); font-size: 11px; font-weight: 700; color: var(--t-2); min-width: 18px; }
.kf-color-name { color: var(--t-2); }

.kf-cable-mini { color: var(--t-2); display: inline-flex; align-items: center; gap: 6px; }
.kf-cable-dot  { font-family: var(--f-mono); font-size: 14px; line-height: 1; }

.kf-row-actions { display: flex; gap: 2px; opacity: .35; transition: opacity .15s; }
.kf-table tr:hover .kf-row-actions { opacity: 1; }

/* Form */
.kf-form { display: flex; flex-direction: column; gap: 14px; }
.kf-form-row { display: flex; gap: 12px; }
.kf-field { flex: 1; display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.kf-field label {
  font-size: 10px; text-transform: uppercase; letter-spacing: .6px; font-weight: 700;
  color: var(--t-3);
}
.kf-input {
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  color: var(--t-1);
  font-size: 13px;
  padding: 8px 10px;
  font-family: var(--f-sans);
  height: 36px;
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
}
textarea.kf-input { height: auto; min-height: 60px; resize: vertical; }
.kf-form-row { display: flex; gap: 12px; flex-wrap: wrap; }
.kf-form-row > .kf-field { min-width: 200px; }
.kf-field-hint { font-size: 11.5px; color: var(--t-3); line-height: 1.4; margin-top: 2px; }
.kf-card-sub { font-size: 12px; color: var(--t-3); margin-left: 8px; font-weight: 400; }
.kf-input:focus { border-color: var(--info); box-shadow: 0 0 0 3px var(--info-soft); outline: none; }
.kf-checkfield { display: flex; align-items: center; gap: 8px; }
.kf-checkfield input { width: 16px; height: 16px; accent-color: var(--info); }
.kf-checkfield label { font-size: 13px; color: var(--t-1); cursor: pointer; }
`;
document.head.appendChild(Object.assign(document.createElement('style'), { textContent: STYLE }));

window.WiresView = WiresView;
window.ViewHeader = ViewHeader;
