// ============================================================
//  Velonics Hub — Smart RO Monitor Detail Screen
//  Tabs: Live | Maintenance | Settings
// ============================================================

// ── Safety Score ─────────────────────────────────────────────
function _roSafetyScore(tank) {
  const { outletTDS = 0, saltRejection = 0, temp = 25 } = tank;
  let score = 100;
  // TDS penalty: 0 ppm = 0 pts off; 100 ppm = 30 pts off; 200 ppm = 60 pts off
  if (outletTDS > 0) score -= Math.min(60, outletTDS * 0.3);
  // Salt rejection penalty: perfect (97%) = 0 off; 90% = 10 off; 80% = 25 off
  if (saltRejection > 0 && saltRejection < 97)
    score -= Math.min(25, (97 - saltRejection) * 0.7);
  // Temp risk: 30°C+ starts penalty
  if (temp > 30) score -= Math.min(15, (temp - 30) * 3);
  return Math.max(0, Math.round(score));
}

function _safetyColor(score) {
  return score >= 85 ? 'var(--green)' : score >= 65 ? 'var(--amber)' : 'var(--red)';
}

function _safetyLabel(score) {
  return score >= 85 ? 'Excellent' : score >= 65 ? 'Acceptable' : 'Poor';
}

// ── Filter life helpers ───────────────────────────────────────
function _filterColor(pct) {
  return pct == null ? 'var(--text-3)' : pct > 40 ? 'var(--green)' : pct > 15 ? 'var(--amber)' : 'var(--red)';
}

function _filterLabel(pct) {
  if (pct == null) return '—';
  if (pct > 40) return 'Good';
  if (pct > 15) return 'Replace soon';
  return 'Replace now';
}

// ── Mini stat row ─────────────────────────────────────────────
const _StatRow = ({ icon, label, value, unit, color }) => (
  <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '9px 0',
    borderBottom: '1px solid rgba(255,255,255,0.05)' }}>
    <div style={{ width: 28, height: 28, borderRadius: 8, background: 'rgba(255,255,255,0.05)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
      <Ic name={icon} size={14} color={color || 'var(--text-2)'}/>
    </div>
    <span style={{ flex: 1, fontSize: 13, color: 'var(--text-2)' }}>{label}</span>
    <span style={{ fontWeight: 600, fontSize: 13, color: color || 'var(--text)' }}>
      {value}<span style={{ fontSize: 11, color: 'var(--text-3)', marginLeft: 3 }}>{unit}</span>
    </span>
  </div>
);

// ── Filter bar ────────────────────────────────────────────────
const _FilterBar = ({ label, pct, capL, usedL, onReplace }) => {
  const c = _filterColor(pct);
  const w = pct != null ? `${pct}%` : '0%';
  return (
    <div style={{ padding: '12px 0', borderBottom: '1px solid rgba(255,255,255,0.05)' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
        <span style={{ fontWeight: 600, fontSize: 13 }}>{label}</span>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ fontSize: 12, color: c, fontWeight: 600 }}>
            {pct != null ? `${pct}% remaining` : 'No data'}
          </span>
          <button onClick={onReplace} style={{
            padding: '4px 10px', borderRadius: 8, fontSize: 11, fontWeight: 600,
            background: 'rgba(255,255,255,0.06)', border: '1px solid var(--border)',
            color: 'var(--text-2)', cursor: 'pointer',
          }}>Replaced</button>
        </div>
      </div>
      <div style={{ height: 6, borderRadius: 3, background: 'rgba(255,255,255,0.08)', overflow: 'hidden' }}>
        <div style={{ height: '100%', width: w, background: c, borderRadius: 3, transition: 'width 600ms ease' }}/>
      </div>
      {capL != null && usedL != null && (
        <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 4 }}>
          {usedL.toLocaleString()} L used of {capL.toLocaleString()} L capacity
          {' · '}{_filterLabel(pct)}
        </div>
      )}
    </div>
  );
};

const _ROLE_LVL_RO = { viewer: 0, operator: 1, admin: 2, owner: 3 };

// ── Live Tab ──────────────────────────────────────────────────
const _LiveTab = ({ tank, issueCmd, pendingCmds = {}, updateTank }) => {
  const [showFlushConfirm, setShowFlushConfirm] = useState(false);
  const pending  = pendingCmds[tank.id] || {};
  const score    = _roSafetyScore(tank);
  const scoreC   = _safetyColor(score);
  const myRoleRO = tank.myRole || 'owner';
  const canCtrlRO = (_ROLE_LVL_RO[myRoleRO] ?? 3) >= _ROLE_LVL_RO['operator'];
  const _isVirtualRO = !tank.deviceId || !!tank.virtual;

  const isOnline  = !!tank.online;
  const motorOn   = !!tank.motor;

  const _roRef = useRef(tank);
  useEffect(() => { _roRef.current = tank; });
  useEffect(() => {
    if (tank.deviceId && !tank.virtual) return;
    const id = setInterval(() => {
      const t = _roRef.current;
      if (t.deviceId && !t.virtual) return;
      const motorOn = t.motor;
      if (!motorOn) return;
      const inletFlow = parseFloat((1.8 + (Math.random() - 0.5) * 0.2).toFixed(2));
      const outletFlow = parseFloat((0.5 + (Math.random() - 0.5) * 0.05).toFixed(2));
      const recoveryRate = parseFloat((outletFlow / inletFlow * 100).toFixed(1));
      const inletTDS = Math.round((t.inletTDS || 820) + (Math.random() - 0.5) * 20);
      const outletTDS = Math.round((t.outletTDS || 22) + (Math.random() - 0.5) * 4);
      const saltRejection = parseFloat((100 - (outletTDS / inletTDS * 100)).toFixed(1));
      updateTank(t.id, {
        inletFlow, outletFlow, recoveryRate, inletTDS, outletTDS, saltRejection,
        temp: parseFloat((26 + (Math.random() - 0.5) * 2).toFixed(1)),
        purifiedToday: parseFloat(((t.purifiedToday || 0) + outletFlow * 2 / 60).toFixed(2)),
        inletVolTotal: parseFloat(((t.inletVolTotal || 0) + inletFlow * 2 / 60).toFixed(2)),
      });
    }, 2000);
    return () => clearInterval(id);
  }, [tank.deviceId, tank.virtual]); // eslint-disable-line

  const handleMotorToggle = () => {
    if (!canCtrlRO) return;
    if (_isVirtualRO) {
      updateTank(tank.id, { motor: !motorOn, cycles: motorOn ? (tank.cycles || 0) : (tank.cycles || 0) + 1 });
      window.__toast?.(`Motor ${!motorOn ? 'started' : 'stopped'}`, { kind: 'success' });
      return;
    }
    if (!isOnline || !tank.deviceId) return;
    issueCmd(tank.id, 'motor', () => MQ.publishCmd(tank.deviceId, 'motor', !motorOn));
  };

  const handleFlush = () => {
    if (!canCtrlRO) return;
    setShowFlushConfirm(false);
    if (_isVirtualRO) {
      window.__toast?.('Flush cycle started (virtual)', { kind: 'info' });
      return;
    }
    if (!isOnline || !tank.deviceId) return;
    MQ.publishCmd(tank.deviceId, 'flush', tank.roFlushDuration ?? 180);
  };

  return (
    <div>
      {/* Safety score hero */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 20, padding: '16px 0 12px' }}>
        <div style={{ position: 'relative', flexShrink: 0 }}>
          <svg width={90} height={90} viewBox="0 0 90 90">
            <circle cx={45} cy={45} r={38} fill="none" stroke="rgba(255,255,255,0.07)" strokeWidth={9}/>
            <circle cx={45} cy={45} r={38} fill="none" stroke={scoreC} strokeWidth={9}
              strokeDasharray={`${2 * Math.PI * 38 * score / 100} ${2 * Math.PI * 38}`}
              strokeLinecap="round" transform="rotate(-90 45 45)" style={{ transition: 'stroke-dasharray 800ms ease' }}/>
            <text x={45} y={49} textAnchor="middle" fill={scoreC} fontSize={20} fontWeight={700}>{score}</text>
            <text x={45} y={62} textAnchor="middle" fill="rgba(255,255,255,0.45)" fontSize={9}>Safety</text>
          </svg>
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 700, fontSize: 20, color: scoreC }}>{_safetyLabel(score)}</div>
          <div style={{ fontSize: 12, color: 'var(--text-3)', marginTop: 3 }}>
            {score >= 85 ? 'Water meets quality standards' :
             score >= 65 ? 'Quality acceptable — monitor closely' :
             'Quality below standard — replace membrane'}
          </div>
          <div style={{ marginTop: 8, display: 'flex', gap: 8 }}>
            <Badge color={motorOn ? 'green' : 'default'}>
              <StatusDot kind={motorOn ? 'on' : 'off'} size={6}/>
              {motorOn ? 'Purifying' : 'Standby'}
            </Badge>
            {!isOnline && <Badge color="red">Offline</Badge>}
          </div>
        </div>
      </div>

      {/* TDS panel */}
      <Card style={{ padding: '14px 16px', marginBottom: 12 }}>
        <div style={{ fontSize: 12, color: 'var(--text-3)', fontWeight: 600, marginBottom: 10, letterSpacing: 0.5 }}>TDS — TOTAL DISSOLVED SOLIDS</div>
        <div style={{ display: 'flex', gap: 8 }}>
          <div style={{ flex: 1, textAlign: 'center', background: 'rgba(255,255,255,0.04)', borderRadius: 12, padding: '12px 8px' }}>
            <div style={{ fontSize: 10, color: 'var(--text-3)', marginBottom: 4 }}>INLET</div>
            <div className="num" style={{ fontSize: 28, fontWeight: 700, color: 'var(--text)' }}>{Math.round(tank.inletTDS || 0)}</div>
            <div style={{ fontSize: 11, color: 'var(--text-3)' }}>ppm</div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 4, padding: '0 4px' }}>
            <Ic name="arrowRight" size={16} color="var(--cyan)"/>
            <div style={{ fontSize: 10, color: 'var(--cyan)', fontWeight: 600 }}>
              {(tank.saltRejection || 0).toFixed(1)}%
            </div>
            <div style={{ fontSize: 9, color: 'var(--text-3)' }}>rej.</div>
          </div>
          <div style={{ flex: 1, textAlign: 'center', background: 'rgba(255,255,255,0.04)', borderRadius: 12, padding: '12px 8px' }}>
            <div style={{ fontSize: 10, color: 'var(--text-3)', marginBottom: 4 }}>OUTLET</div>
            <div className="num" style={{ fontSize: 28, fontWeight: 700, color: (tank.outletTDS||0) > 100 ? 'var(--red)' : (tank.outletTDS||0) < 50 ? 'var(--green)' : 'var(--amber)' }}>
              {Math.round(tank.outletTDS || 0)}
            </div>
            <div style={{ fontSize: 11, color: 'var(--text-3)' }}>ppm</div>
          </div>
        </div>
      </Card>

      {/* Flow & recovery */}
      <Card style={{ padding: '14px 16px', marginBottom: 12 }}>
        <div style={{ fontSize: 12, color: 'var(--text-3)', fontWeight: 600, marginBottom: 10, letterSpacing: 0.5 }}>FLOW & RECOVERY</div>
        <div style={{ display: 'flex', gap: 8 }}>
          <div style={{ flex: 1, textAlign: 'center', background: 'rgba(255,255,255,0.04)', borderRadius: 12, padding: '10px 6px' }}>
            <div style={{ fontSize: 10, color: 'var(--text-3)', marginBottom: 3 }}>INLET</div>
            <div className="num" style={{ fontSize: 22, fontWeight: 700 }}>{(tank.inletFlow || 0).toFixed(2)}</div>
            <div style={{ fontSize: 10, color: 'var(--text-3)' }}>L/min</div>
          </div>
          <div style={{ flex: 1, textAlign: 'center', background: 'rgba(255,255,255,0.04)', borderRadius: 12, padding: '10px 6px' }}>
            <div style={{ fontSize: 10, color: 'var(--text-3)', marginBottom: 3 }}>OUTLET</div>
            <div className="num" style={{ fontSize: 22, fontWeight: 700, color: 'var(--cyan)' }}>{(tank.outletFlow || 0).toFixed(2)}</div>
            <div style={{ fontSize: 10, color: 'var(--text-3)' }}>L/min</div>
          </div>
          <div style={{ flex: 1, textAlign: 'center', background: 'rgba(255,255,255,0.04)', borderRadius: 12, padding: '10px 6px' }}>
            <div style={{ fontSize: 10, color: 'var(--text-3)', marginBottom: 3 }}>RECOVERY</div>
            <div className="num" style={{ fontSize: 22, fontWeight: 700, color: 'var(--teal)' }}>{(tank.recoveryRate || 0).toFixed(1)}</div>
            <div style={{ fontSize: 10, color: 'var(--text-3)' }}>%</div>
          </div>
        </div>
      </Card>

      {/* Stats */}
      <Card style={{ padding: '14px 16px', marginBottom: 12 }}>
        <_StatRow icon="droplets" label="Purified today" value={`${(tank.purifiedToday || 0).toFixed(1)}`} unit="L" color="var(--cyan)"/>
        <_StatRow icon="gauge"    label="Total inlet volume" value={(tank.inletVolTotal || 0).toFixed(0)} unit="L"/>
        <_StatRow icon="thermometer" label="Water temperature" value={(tank.temp || 0).toFixed(1)} unit="°C"
          color={(tank.temp || 0) > 30 ? 'var(--red)' : 'var(--text)'}/>
        <_StatRow icon="refresh"  label="Cycles" value={tank.cycles || 0} unit="" color="var(--text-2)"/>
        <_StatRow icon="wifi"     label="Signal" value={tank.rssi || '—'} unit="dBm" color="var(--text-2)"/>
      </Card>

      {/* Controls */}
      <Card style={{ padding: '14px 16px', marginBottom: 12 }}>
        <div style={{ fontSize: 12, color: 'var(--text-3)', fontWeight: 600, marginBottom: 12, letterSpacing: 0.5 }}>CONTROLS</div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          <button onClick={handleMotorToggle} disabled={(!_isVirtualRO && !isOnline) || pending.motor || !canCtrlRO} style={{
            padding: '12px 0', borderRadius: 12, border: `1px solid ${motorOn ? 'rgba(0,230,118,0.4)' : 'var(--border)'}`,
            background: motorOn ? 'rgba(0,230,118,0.12)' : 'rgba(255,255,255,0.04)',
            color: motorOn ? 'var(--green)' : 'var(--text-2)', fontWeight: 600, fontSize: 13,
            cursor: ((!_isVirtualRO && !isOnline) || pending.motor || !canCtrlRO) ? 'not-allowed' : 'pointer',
            opacity: ((!_isVirtualRO && !isOnline) || !canCtrlRO) ? 0.5 : 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          }}>
            {pending.motor ? <PendingDots size="sm" color="var(--green)"/> : <><Ic name={motorOn ? 'pause' : 'play'} size={14}/>{motorOn ? 'Stop Motor' : 'Start Motor'}</>}
          </button>
          <button onClick={() => canCtrlRO && setShowFlushConfirm(true)} disabled={(!_isVirtualRO && !isOnline) || !canCtrlRO} style={{
            padding: '12px 0', borderRadius: 12, border: '1px solid rgba(0,188,212,0.4)',
            background: 'rgba(0,188,212,0.10)', color: 'var(--cyan)',
            fontWeight: 600, fontSize: 13, cursor: ((!_isVirtualRO && !isOnline) || !canCtrlRO) ? 'not-allowed' : 'pointer',
            opacity: ((!_isVirtualRO && !isOnline) || !canCtrlRO) ? 0.5 : 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          }}>
            <Ic name="refreshCw" size={14}/>Flush
          </button>
        </div>
      </Card>

      <Confirm
        open={showFlushConfirm}
        title="Start flush cycle?"
        body={`Run a ${(tank.roFlushDuration ?? 180)}s flush cycle to clean the membrane. The motor will stop automatically.`}
        confirmLabel="Start Flush"
        onCancel={() => setShowFlushConfirm(false)}
        onConfirm={handleFlush}
      />
    </div>
  );
};

// ── Maintenance Tab ───────────────────────────────────────────
const _MaintenanceTab = ({ tank }) => {
  const [filterData, setFilterData] = useState(null);
  const [loading,    setLoading]    = useState(true);
  const [replacing,  setReplacing]  = useState(null); // 'membrane'|'prefilter'|'postfilter'|null

  useEffect(() => {
    if (!tank.id) return;
    setLoading(true);
    API.get(`/api/ro/${tank.id}/filter-events`)
      .then(d => { setFilterData(d); setLoading(false); })
      .catch(() => setLoading(false));
  }, [tank.id]);

  const handleReplace = async (filterType) => {
    setReplacing(filterType);
    try {
      await API.post(`/api/ro/${tank.id}/filter-events`, {
        filterType,
        inletVolL: tank.inletVolTotal || 0,
      });
      const d = await API.get(`/api/ro/${tank.id}/filter-events`);
      setFilterData(d);
      window.__toast?.('Filter replacement logged', { kind: 'success' });
    } catch {
      window.__toast?.('Failed to log replacement', { kind: 'error' });
    }
    setReplacing(null);
  };

  if (loading) return <div style={{ textAlign: 'center', padding: 40, color: 'var(--text-3)' }}>Loading…</div>;

  const h = filterData?.health || {};

  const filters = [
    { key: 'prefilter',  label: 'Pre-filter (Sediment)',    capKey: 'roPrefilterCap' },
    { key: 'membrane',   label: 'RO Membrane',              capKey: 'roMembraneCap'  },
    { key: 'postfilter', label: 'Post-filter (Activated C)', capKey: 'roPostfilterCap' },
  ];

  return (
    <div>
      <Card style={{ padding: '14px 16px', marginBottom: 12 }}>
        <div style={{ fontSize: 12, color: 'var(--text-3)', fontWeight: 600, marginBottom: 4, letterSpacing: 0.5 }}>FILTER HEALTH</div>
        <div style={{ fontSize: 11, color: 'var(--text-3)', marginBottom: 12 }}>
          Tap "Replaced" after physically replacing a filter to reset the counter.
        </div>
        {filters.map(f => {
          const fd  = h[f.key] || {};
          const pct = fd.lifePct;
          return (
            <_FilterBar key={f.key} label={f.label}
              pct={pct} capL={fd.capLitres} usedL={fd.usedLitres}
              onReplace={() => replacing ? null : handleReplace(f.key)}/>
          );
        })}
      </Card>

      <Card style={{ padding: '14px 16px' }}>
        <div style={{ fontSize: 12, color: 'var(--text-3)', fontWeight: 600, marginBottom: 10, letterSpacing: 0.5 }}>REPLACEMENT HISTORY</div>
        {(!filterData?.events || filterData.events.length === 0) ? (
          <div style={{ fontSize: 13, color: 'var(--text-3)', textAlign: 'center', padding: '16px 0' }}>
            No replacements recorded yet.
          </div>
        ) : filterData.events.slice(0, 20).map(ev => (
          <div key={ev.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            padding: '8px 0', borderBottom: '1px solid rgba(255,255,255,0.05)' }}>
            <div>
              <div style={{ fontWeight: 600, fontSize: 13, textTransform: 'capitalize' }}>
                {ev.filter_type.replace('filter', '-filter')}
              </div>
              <div style={{ fontSize: 11, color: 'var(--text-3)' }}>
                {new Date(ev.replaced_at * 1000).toLocaleDateString()}
              </div>
            </div>
            <div style={{ fontSize: 12, color: 'var(--text-3)' }}>
              at {(ev.inlet_vol_l || 0).toLocaleString()} L
            </div>
          </div>
        ))}
      </Card>
    </div>
  );
};

// ── Settings Tab ──────────────────────────────────────────────
const _SettingsTab = ({ tank, updateTank }) => {
  const [draft, setDraft]   = useState(null);
  const [saving, setSaving] = useState(false);
  const canAdminRO = (_ROLE_LVL_RO[tank.myRole || 'owner'] ?? 3) >= _ROLE_LVL_RO['admin'];

  useEffect(() => {
    setDraft({
      roMaxInletTDS:    tank.roMaxInletTDS    ?? 1000,
      roMinRejection:   tank.roMinRejection   ?? 90,
      roMinRecovery:    tank.roMinRecovery     ?? 20,
      roStaleHours:     tank.roStaleHours     ?? 8,
      roMaxTempRisk:    tank.roMaxTempRisk    ?? 30,
      roPumpMaxCurrent: tank.roPumpMaxCurrent ?? 2,
      roFlushDuration:  tank.roFlushDuration  ?? 180,
      roMembraneCap:    tank.roMembraneCap    ?? 5000,
      roPrefilterCap:   tank.roPrefilterCap   ?? 2000,
      roPostfilterCap:  tank.roPostfilterCap  ?? 3000,
    });
  }, [tank.id]);

  if (!draft) return null;

  const set = (k, v) => setDraft(p => ({ ...p, [k]: v }));

  const save = async () => {
    setSaving(true);
    try {
      await API.put(`/api/tanks/${tank.id}/setpoints`, draft);
      updateTank(tank.id, draft);
      if (tank.deviceId && window.MQ) MQ.publishSetpoints(tank.deviceId, draft);
      window.__toast?.('RO settings saved', { kind: 'success' });
    } catch {
      window.__toast?.('Failed to save settings', { kind: 'error' });
    }
    setSaving(false);
  };

  const Field = ({ label, fieldKey, unit, min, max, step = 1 }) => (
    <div style={{ padding: '10px 0', borderBottom: '1px solid rgba(255,255,255,0.05)' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <span style={{ fontSize: 13, color: 'var(--text-2)' }}>{label}</span>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <input type="number" value={draft[fieldKey]} min={min} max={max} step={step}
            onChange={e => set(fieldKey, +e.target.value)}
            style={{ width: 70, textAlign: 'right', background: 'rgba(255,255,255,0.06)',
              border: '1px solid var(--border)', borderRadius: 8, padding: '4px 8px',
              color: 'var(--text)', fontSize: 13, outline: 'none' }}/>
          {unit && <span style={{ fontSize: 12, color: 'var(--text-3)', minWidth: 28 }}>{unit}</span>}
        </div>
      </div>
    </div>
  );

  return (
    <div>
      <Card style={{ padding: '14px 16px', marginBottom: 12 }}>
        <div style={{ fontSize: 12, color: 'var(--text-3)', fontWeight: 600, marginBottom: 6, letterSpacing: 0.5 }}>QUALITY THRESHOLDS</div>
        <Field label="Max inlet TDS"       fieldKey="roMaxInletTDS"    unit="ppm" min={100}  max={2000}/>
        <Field label="Min salt rejection"  fieldKey="roMinRejection"   unit="%"   min={50}   max={99}  step={0.5}/>
        <Field label="Min recovery rate"   fieldKey="roMinRecovery"    unit="%"   min={5}    max={50}/>
      </Card>

      <Card style={{ padding: '14px 16px', marginBottom: 12 }}>
        <div style={{ fontSize: 12, color: 'var(--text-3)', fontWeight: 600, marginBottom: 6, letterSpacing: 0.5 }}>SAFETY ALERTS</div>
        <Field label="Stale water threshold" fieldKey="roStaleHours"    unit="hrs" min={1}  max={72}/>
        <Field label="Bacteria risk temp"    fieldKey="roMaxTempRisk"   unit="°C"  min={20} max={40}/>
        <Field label="Max pump current"      fieldKey="roPumpMaxCurrent" unit="A"  min={0.5} max={10} step={0.1}/>
      </Card>

      <Card style={{ padding: '14px 16px', marginBottom: 12 }}>
        <div style={{ fontSize: 12, color: 'var(--text-3)', fontWeight: 600, marginBottom: 6, letterSpacing: 0.5 }}>FLUSH & FILTER CAPACITY</div>
        <Field label="Flush duration"      fieldKey="roFlushDuration"  unit="s"  min={30}   max={600}/>
        <Field label="Membrane capacity"   fieldKey="roMembraneCap"    unit="L"  min={500}  max={20000} step={100}/>
        <Field label="Pre-filter capacity" fieldKey="roPrefilterCap"   unit="L"  min={500}  max={10000} step={100}/>
        <Field label="Post-filter cap."    fieldKey="roPostfilterCap"  unit="L"  min={500}  max={10000} step={100}/>
      </Card>

      <button onClick={save} disabled={saving || !canAdminRO} style={{
        width: '100%', padding: '14px 0', borderRadius: 14,
        background: (saving || !canAdminRO) ? 'rgba(255,255,255,0.06)' : 'linear-gradient(90deg, var(--cyan), var(--teal))',
        border: 'none', color: (saving || !canAdminRO) ? 'var(--text-3)' : '#0a0e27',
        fontWeight: 700, fontSize: 15, cursor: (saving || !canAdminRO) ? 'not-allowed' : 'pointer',
        transition: 'all 200ms',
      }}>
        {saving ? 'Saving…' : !canAdminRO ? 'Admin role required' : 'Save Settings'}
      </button>
    </div>
  );
};

// ── RODetail — main component ─────────────────────────────────
const RODetail = ({ tank, onBack, updateTank, issueCmd, pendingCmds = {} }) => {
  const [tab, setTab] = useState('live');

  const tabs = [
    { key: 'live',        label: 'Live' },
    { key: 'maintenance', label: 'Maintenance' },
    { key: 'settings',    label: 'Settings' },
  ];

  const swipe = useSwipeTabs(tabs, tab, setTab, onBack);

  return (
    <div onTouchStart={swipe.onTouchStart} onTouchEnd={swipe.onTouchEnd} style={{ minHeight: '100dvh', background: 'var(--bg)', display: 'flex', flexDirection: 'column' }}>
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '14px 16px 10px',
        borderBottom: '1px solid var(--border)', position: 'sticky', top: 0, zIndex: 10,
        background: 'var(--bg)' }}>
        <button onClick={onBack} style={{ background: 'none', border: 'none', cursor: 'pointer',
          color: 'var(--text)', padding: 4, display: 'flex', alignItems: 'center' }}>
          <Ic name="arrowLeft" size={20}/>
        </button>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontWeight: 700, fontSize: 17, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {tank.name}
          </div>
          <div style={{ fontSize: 11, color: 'var(--text-3)' }}>
            Smart RO Monitor{tank.location ? ` · ${tank.location}` : ''}
          </div>
        </div>
        <Badge color={(!tank.deviceId || tank.virtual) ? 'amber' : tank.online ? 'green' : 'default'}>
          <StatusDot kind={(!tank.deviceId || tank.virtual) ? 'amber' : tank.online ? 'on' : 'off'} size={6} pulse={tank.online && !tank.virtual}/>
          {(!tank.deviceId || tank.virtual) ? 'Virtual' : tank.online ? 'Online' : 'Offline'}
        </Badge>
      </div>

      {tank.myRole && tank.myRole !== 'owner' && (
        <div style={{ padding: '9px 16px', background: 'rgba(255,188,0,0.08)',
          borderBottom: '1px solid rgba(255,188,0,0.18)', display: 'flex', alignItems: 'center', gap: 8 }}>
          <Ic name="shield" size={13} color="var(--amber)"/>
          <span style={{ fontSize: 12, color: 'var(--amber)' }}>
            {tank.myRole === 'viewer' ? 'Read-only access — controls are disabled'
           : tank.myRole === 'operator' ? 'Operator access — settings are read-only'
           : 'Admin access'}
          </span>
        </div>
      )}

      {/* Tab bar */}
      <div style={{ display: 'flex', borderBottom: '1px solid var(--border)', background: 'var(--bg)',
        position: 'sticky', top: 53, zIndex: 9 }}>
        {tabs.map(t => (
          <button key={t.key} onClick={() => setTab(t.key)} style={{
            flex: 1, padding: '12px 0', border: 'none', background: 'none', cursor: 'pointer',
            fontSize: 13, fontWeight: tab === t.key ? 700 : 500,
            color: tab === t.key ? 'var(--cyan)' : 'var(--text-3)',
            borderBottom: `2px solid ${tab === t.key ? 'var(--cyan)' : 'transparent'}`,
            transition: 'all 150ms',
          }}>{t.label}</button>
        ))}
      </div>

      {/* Body */}
      <div style={{ flex: 1, overflowY: 'auto', padding: '0 16px 24px' }}>
        {tab === 'live'        && <_LiveTab        tank={tank} issueCmd={issueCmd} pendingCmds={pendingCmds} updateTank={updateTank}/>}
        {tab === 'maintenance' && <_MaintenanceTab tank={tank}/>}
        {tab === 'settings'    && <_SettingsTab    tank={tank} updateTank={updateTank}/>}
      </div>
    </div>
  );
};

window.RODetail = RODetail;
