// ─────────────────────────────────────────────────────────
// Settings page — bridge status, commands, response viewer, log
// ─────────────────────────────────────────────────────────
function Settings({ bridge, bridgeState, bridgeIp, lastResp, log, onClearLog, onClearResponses }) {
  const [logFilter, setLogFilter] = React.useState('all');
  const [busy, setBusy] = React.useState(null);

  const filteredLog = log.filter(l => {
    if (logFilter === 'all') return true;
    if (logFilter === 'mqtt') return ['pub', 'sub'].includes(l.dir);
    if (logFilter === 'modem') return ['tx', 'rx', 'urc'].includes(l.dir);
    if (logFilter === 'events') return l.dir === 'evt';
    return true;
  });

  const runCmd = async (name, fn) => {
    if (busy) return;
    setBusy(name);
    try { await fn(); } catch (e) { console.error(e); }
    setTimeout(() => setBusy(null), 300);
  };

  // Newest first, capped to 80 to stay snappy.
  const activity = React.useMemo(
    () => lastResp.slice(-80).reverse(),
    [lastResp]
  );

  return (
    <div className="settings">
      <div className="settings-wrap">
        <div>
          <h1>Bridge</h1>
          <p className="lede">EC200U cellular modem over MQTT · <span style={{fontFamily:'JetBrains Mono,monospace'}}>mqtt.divyessh.my:8884</span></p>
        </div>

        {/* Status card */}
        <div className="card">
          <div className="card-hd">
            <h3>Status</h3>
            <span className="sub">client: msg-relay-server</span>
          </div>
          <div className="status-grid">
            <div className="status-cell">
              <div className="k">Bridge state</div>
              <div className="v"><StatusPill state={bridgeState} /></div>
            </div>
            <div className="status-cell">
              <div className="k">Modem IP</div>
              <div className="v mono">{bridgeIp || <span style={{color:'var(--ink-mute)'}}>—</span>}</div>
            </div>
            <div className="status-cell">
              <div className="k">Serial port</div>
              <div className="v mono">
                <span style={{ width:8, height:8, borderRadius:'50%',
                               background: bridgeState!=='disconnected'?'var(--good)':'var(--bad)' }}/>
                COM27 · 115200
              </div>
            </div>
          </div>
          <div className="btn-row">
            <button className="btn primary"
              disabled={busy}
              onClick={() => runCmd('connect', () => bridge.connect())}>
              {busy === 'connect' ? <Icon name="refresh" size={13} className="spin" /> : <Icon name="plug" size={13} />}
              connect
            </button>
            <button className="btn"
              disabled={busy || bridgeState === 'disconnected'}
              onClick={() => runCmd('setup', () => bridge.setup())}>
              {busy === 'setup' ? <Icon name="refresh" size={13} className="spin" /> : <Icon name="sparkle" size={13} />}
              setup
            </button>
            <button className="btn"
              disabled={busy}
              onClick={() => runCmd('status', () => bridge.status())}>
              <Icon name="eye" size={13} />
              status
            </button>
            <span style={{flex:1}}/>
            <button className="btn"
              disabled={busy || bridgeState === 'disconnected'}
              onClick={() => runCmd('reset', () => bridge.reset())}>
              <Icon name="refresh" size={13} />
              reset
            </button>
            <button className="btn danger"
              disabled={busy || bridgeState === 'disconnected'}
              onClick={() => runCmd('disconnect', () => bridge.disconnect())}>
              <Icon name="power" size={13} />
              disconnect
            </button>
          </div>
        </div>

        {/* Response feed */}
        <div className="card">
          <div className="card-hd">
            <h3>Response feed</h3>
            <div style={{display:'flex',gap:12,alignItems:'center'}}>
              <span className="sub">modem/rsp · newest first · {activity.length}</span>
              <button className="btn" style={{padding:'6px 10px'}}
                      onClick={onClearResponses} disabled={activity.length === 0}>
                clear
              </button>
            </div>
          </div>
          {activity.length === 0 && (
            <div style={{padding:'30px 18px',textAlign:'center',color:'var(--ink-mute)',fontSize:12.5}}>
              No commands sent yet — try <code style={{background:'var(--panel-2)',padding:'1px 6px',borderRadius:4,fontFamily:'JetBrains Mono,monospace'}}>connect</code>
            </div>
          )}
          <div style={{ maxHeight: 520, overflowY: 'auto' }}>
            {activity.map((r) => <ResponseBlock key={r.id ?? r._ts} r={r} />)}
          </div>
        </div>

        {/* Certificates */}
        <div className="card">
          <div className="card-hd">
            <h3>Certificates</h3>
            <span className="sub">mTLS · certs/</span>
          </div>
          <div className="cert-list">
            {[
              ['ca.crt',                 'Broker CA',          'verifies the server'],
              ['MSG_Relay_Server.crt',   'Client certificate', 'identity'],
              ['MSG_Relay_Server.key',   'Client private key', '—'],
            ].map(([f, label, note]) => (
              <div className="cert" key={f}>
                <div className="ci"><Icon name="cert" size={14} /></div>
                <div className="cn">{label} <small>certs/{f} · {note}</small></div>
                <div className="cst">LOADED</div>
              </div>
            ))}
          </div>
        </div>

        {/* Activity log */}
        <div className="card">
          <div className="card-hd">
            <h3>Activity log</h3>
            <div style={{display:'flex',gap:12,alignItems:'center'}}>
              <div className="toggle-grp">
                {['all','mqtt','modem','events'].map(k => (
                  <button key={k} className={logFilter===k?'on':''} onClick={() => setLogFilter(k)}>{k}</button>
                ))}
              </div>
              <button className="btn" style={{padding:'6px 10px'}} onClick={onClearLog}>clear</button>
            </div>
          </div>
          <div className="log">
            {filteredLog.length === 0 && (
              <div className="log-empty">no entries</div>
            )}
            {filteredLog.slice().reverse().map((l, i) => <LogRow key={l.id ?? (l.ts+'-'+i)} l={l} />)}
          </div>
        </div>
      </div>
    </div>
  );
}
window.Settings = Settings;

// ─────────────────────────────────────────────────────────
// Response block
// ─────────────────────────────────────────────────────────
function ResponseBlock({ r }) {
  const tone = r.status === 'success' ? 'success' : r.status === 'event' ? 'event' : 'error';
  const isSetup = r.command === 'setup' && Array.isArray(r.results);
  // Setup is verbose; default to collapsed so the feed stays scannable.
  const [expanded, setExpanded] = React.useState(false);

  // One-line summary that shows the *outcome* inline (state for status,
  // OK count for setup, etc.) so the feed reads like a timeline.
  const summary = oneLineSummary(r);

  return (
    <div className={`resp ${tone}`} style={{ margin: '8px 14px' }}>
      <div className="resp-hd"
           onClick={isSetup ? () => setExpanded(e => !e) : undefined}
           style={isSetup ? { cursor: 'pointer', userSelect: 'none' } : null}>
        {tone === 'success' && <Icon name="check-pill" size={13} />}
        {tone === 'error'   && <Icon name="x-pill"     size={13} />}
        {tone === 'event'   && <Icon name="bell"       size={13} />}
        <span>{r.command || r.event}</span>
        {summary && (
          <>
            <span className="dot-sep">·</span>
            <span style={{opacity:.85, letterSpacing:0, textTransform:'none',
                          fontFamily:'JetBrains Mono,monospace'}}>
              {summary}
            </span>
          </>
        )}
        <span style={{flex:1}}/>
        <span style={{fontFamily:'JetBrains Mono,monospace', fontSize:10.5,
                      color:'var(--ink-mute)', letterSpacing:0, textTransform:'none'}}>
          {fmtClock(r._ts || Date.now())}
        </span>
        {isSetup && (
          <Icon name="chevron" size={11}
                style={{ transform: expanded ? 'rotate(90deg)' : 'none',
                         transition: 'transform .15s' }} />
        )}
      </div>

      {/* setup details — only when expanded */}
      {isSetup && expanded && (
        <div style={{marginTop:8}}>
          {r.results.map((s, i) => (
            <div className="step" key={i}>
              <span className="cmd">{s.cmd}</span>
              <span style={{color:'var(--ink-mute)',fontSize:11,overflow:'hidden',
                            textOverflow:'ellipsis',whiteSpace:'nowrap'}}>
                {(s.lines || []).slice(1).join(' · ')}
                {s.note ? ' · ' + s.note : ''}
                {s.error ? ' · ' + s.error : ''}
              </span>
              <span className={s.ok ? 'ok' : 'bad'}>{s.ok ? 'OK' : 'FAIL'}</span>
            </div>
          ))}
          {r.health_check && (
            <div className="step">
              <span className="cmd">AT <span style={{color:'var(--ink-mute)'}}>(health check)</span></span>
              <span style={{color:'var(--ink-mute)',fontSize:11}}>{(r.health_check.lines || []).join(' · ')}</span>
              <span className={r.health_check.ok ? 'ok' : 'bad'}>{r.health_check.ok ? 'OK' : 'FAIL'}</span>
            </div>
          )}
        </div>
      )}

      {/* connect / disconnect / reset — show the AT lines */}
      {(['connect','disconnect','reset'].includes(r.command)) && r.lines && (
        <pre style={{margin:'6px 0 0',fontSize:11}}>{r.lines.join('\n')}</pre>
      )}

      {/* errors */}
      {r.error && (
        <pre style={{margin:'6px 0 0',color:'var(--bad)',fontSize:11}}>
          {r.error}
        </pre>
      )}
    </div>
  );
}

function oneLineSummary(r) {
  if (r.event === 'usb_connected')    return 'port detected';
  if (r.event === 'usb_disconnected') return 'port disappeared';
  if (r.command === 'status')         return r.state + (r.ip ? ` · ${r.ip}` : '');
  if (r.command === 'setup' && r.results) {
    const total = r.results.length;
    const ok = r.results.filter(s => s.ok).length;
    const hc = r.health_check ? (r.health_check.ok ? ' · AT ok' : ' · AT fail') : '';
    return `${ok}/${total} OK${hc}`;
  }
  if (r.command === 'connect' && r.lines)
    return r.lines.includes('OK') ? 'AT → OK' : 'AT → ' + r.lines.join(' ');
  if (r.command === 'disconnect') return 'port closed';
  if (r.command === 'reset')      return 'AT+CFUN=1,1 → ' + (r.lines || []).join(' ');
  return r.status;
}

// ─────────────────────────────────────────────────────────
// Log row
// ─────────────────────────────────────────────────────────
function LogRow({ l }) {
  const cls = { pub:'pub', sub:'sub', evt:'evt', tx:'pub', rx:'sub', urc:'urc' }[l.dir] || '';
  const labelMap = { pub:'PUB', sub:'SUB', tx:'TX', rx:'RX', urc:'URC', evt:'EVT' };
  return (
    <div className="log-row">
      <span className="lt">{fmtClockMs(l.ts)}</span>
      <span className={`ld ${cls}`}>{labelMap[l.dir] || l.dir.toUpperCase()}</span>
      <span className="lm">{l.msg}</span>
    </div>
  );
}

window.ResponseBlock = ResponseBlock;
window.LogRow = LogRow;
