// Format a unix-second timestamp in the user's configured timezone.
// Uses en-CA locale (YYYY-MM-DD) for date comparison so timezone boundaries
// are respected correctly — avoids the UTC drift that broke server-side formatting.
function formatAlertTime(ts, tz) {
  if (!ts) return '';
  const diffSec = Math.floor(Date.now() / 1000) - ts;
  if (diffSec <   60) return `${Math.max(0, diffSec)}s ago`;
  if (diffSec < 3600) return `${Math.floor(diffSec / 60)} min ago`;

  const resolvedTz = (!tz || tz === 'auto')
    ? Intl.DateTimeFormat().resolvedOptions().timeZone
    : tz;

  const d       = new Date(ts * 1000);
  const timeStr = d.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true, timeZone: resolvedTz });
  const dDate         = d.toLocaleDateString('en-CA', { timeZone: resolvedTz });
  const todayDate     = new Date().toLocaleDateString('en-CA', { timeZone: resolvedTz });
  const yesterdayDate = new Date(Date.now() - 86400000).toLocaleDateString('en-CA', { timeZone: resolvedTz });

  if (dDate === todayDate)     return timeStr;
  if (dDate === yesterdayDate) return `Yesterday, ${timeStr}`;
  if (diffSec < 7 * 86400)    return `${d.toLocaleDateString('en-US', { weekday: 'short', timeZone: resolvedTz })}, ${timeStr}`;
  return `${d.toLocaleDateString('en-US', { day: 'numeric', month: 'short', timeZone: resolvedTz })}, ${timeStr}`;
}

// Alerts screen
const Alerts = ({ alerts, setAlerts }) => {
  const [filter,        setFilter]        = useState('all');
  const [selectedTanks, setSelectedTanks] = useState([]); // [] = All devices
  const [confirmClear,  setConfirmClear]  = useState(false);
  const [busy,          setBusy]          = useState(false);
  const [busyId,        setBusyId]        = useState(null);
  const [refreshing,    setRefreshing]    = useState(false);
  const toast = useToast();

  // Fetch on mount so navigating here (e.g. tapping a push notification) always shows latest.
  useEffect(() => {
    if (!window.API) return;
    API.get('/api/alerts').then(d => setAlerts(d)).catch(() => {});
  }, []);

  const fetchAlerts = () => {
    if (!window.API || refreshing) return;
    setRefreshing(true);
    API.get('/api/alerts')
      .then(d => { setAlerts(d); toast && toast('Alerts refreshed', { kind: 'success' }); })
      .catch(() => { toast && toast('Could not refresh alerts', { kind: 'error' }); })
      .finally(() => setRefreshing(false));
  };

  const counts = useMemo(() => ({
    all: alerts.length,
    critical: alerts.filter(a => a.sev === 'critical').length,
    warning: alerts.filter(a => a.sev === 'warning').length,
    info: alerts.filter(a => a.sev === 'info').length,
  }), [alerts]);

  const tankNames = useMemo(() => Array.from(new Set(alerts.map(a => a.tank).filter(Boolean))), [alerts]);
  const filtered = alerts.filter(a =>
    (filter === 'all' || a.sev === filter) &&
    (selectedTanks.length === 0 || selectedTanks.includes(a.tank))
  );

  const ack = async (id) => {
    const prevAlerts = alerts;
    setBusyId(id);
    setAlerts(prev => prev.map(a => a.id === id ? { ...a, ack: true } : a));
    try {
      if (window.API) {
        const res = await API.post(`/api/alerts/${id}/ack`, {}, { keepalive: true });
        if (!res.ok) throw new Error('Alert not found');
      }
      toast && toast('Alert acknowledged', { kind: 'success' });
    } catch (err) {
      setAlerts(prevAlerts);
      toast && toast('Could not acknowledge alert', { kind: 'error' });
    } finally {
      setBusyId(null);
    }
  };

  const ackAll = async () => {
    const prevAlerts = alerts;
    setBusy(true);
    setAlerts(prev => prev.map(a => ({ ...a, ack: true }))); // optimistic — instant feedback
    try {
      if (window.API) await API.post('/api/alerts/ack-all', {}, { keepalive: true });
      toast && toast('All alerts acknowledged', { kind: 'success' });
    } catch {
      setAlerts(prevAlerts); // revert only on genuine server error
      toast && toast('Could not acknowledge all alerts', { kind: 'error' });
    } finally {
      setBusy(false);
    }
  };

  const clearAll = async () => {
    const prevAlerts = alerts;
    setBusy(true);
    setAlerts([]); // optimistic — instant feedback
    try {
      if (window.API) await API.del('/api/alerts', { keepalive: true });
      toast && toast('All alerts cleared', { kind: 'success' });
    } catch {
      setAlerts(prevAlerts); // revert only on genuine server error
      toast && toast('Could not clear alerts', { kind: 'error' });
    } finally {
      setBusy(false);
    }
  };

  const saving = busy || busyId !== null;

  return (
    <div style={{ padding: '8px 16px 100px' }}>
      <div style={{ padding: '6px 4px 14px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div>
          <div style={{ fontSize: 22, fontWeight: 600 }}>Alerts</div>
          <div style={{ fontSize: 13, color: 'var(--text-2)', marginTop: 2 }}>{alerts.filter(a => !a.ack).length} unacknowledged</div>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <Btn variant="ghost" icon="check" onClick={ackAll} size="sm" disabled={saving || alerts.length === 0}>Ack all</Btn>
          <Btn variant="ghost" icon="trash" onClick={() => setConfirmClear(true)} size="sm" disabled={saving || alerts.length === 0} style={{ color:'var(--red)', borderColor:'rgba(255,82,82,0.3)' }}>Clear all</Btn>
          <button
            onClick={fetchAlerts}
            disabled={refreshing || saving}
            title="Refresh from server"
            style={{
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              width: 32, height: 32, borderRadius: 10,
              background: 'rgba(255,255,255,0.05)',
              border: '1px solid var(--border)',
              cursor: refreshing ? 'not-allowed' : 'pointer',
              opacity: (refreshing || saving) ? 0.5 : 1,
              flexShrink: 0,
            }}
          >
            <Ic name="refresh" size={15} color="var(--cyan)"
              style={{ animation: refreshing ? 'spin 0.75s linear infinite' : 'none' }}/>
          </button>
        </div>
      </div>

      {saving && (
        <div style={{
          position: 'sticky', top: 0, zIndex: 50,
          display: 'flex', alignItems: 'center', gap: 12,
          background: 'rgba(255,171,64,0.14)',
          border: '1px solid rgba(255,171,64,0.45)',
          borderRadius: 14, padding: '12px 16px', marginBottom: 12,
          backdropFilter: 'blur(10px)',
          animation: 'pop-in 180ms ease both',
        }}>
          <div style={{
            width: 20, height: 20, flexShrink: 0,
            border: '2.5px solid rgba(255,171,64,0.35)',
            borderTopColor: 'var(--amber)',
            borderRadius: '50%',
            animation: 'spin 0.75s linear infinite',
          }}/>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--amber)' }}>Saving to server…</div>
            <div style={{ fontSize: 11, color: 'var(--text-2)', marginTop: 1 }}>Please wait before closing the app</div>
          </div>
        </div>
      )}

      <Confirm open={confirmClear}
        onCancel={() => setConfirmClear(false)}
        onConfirm={() => { setConfirmClear(false); clearAll(); }}
        title="Clear all alerts?"
        body="This permanently deletes all alert history and cannot be undone."
        confirmLabel="Clear all" danger/>

      <div style={{ display: 'flex', gap: 6, marginBottom: 10, overflowX: 'auto', paddingBottom: 4 }}>
        {[
          { id:'all', label:'All', color:'gray' },
          { id:'critical', label:'Critical', color:'red' },
          { id:'warning', label:'Warning', color:'amber' },
          { id:'info', label:'Info', color:'info' },
        ].map(f => (
          <button key={f.id} onClick={() => setFilter(f.id)} style={{
            padding: '6px 12px', borderRadius: 999, whiteSpace: 'nowrap',
            background: filter === f.id
              ? `${f.color === 'red' ? 'rgba(255,82,82,0.15)' : f.color === 'amber' ? 'rgba(255,171,64,0.15)' : f.color === 'info' ? 'rgba(64,196,255,0.15)' : 'rgba(0,212,255,0.15)'}`
              : 'rgba(255,255,255,0.04)',
            border: `1px solid ${filter === f.id
              ? (f.color === 'red' ? 'rgba(255,82,82,0.4)' : f.color === 'amber' ? 'rgba(255,171,64,0.4)' : f.color === 'info' ? 'rgba(64,196,255,0.4)' : 'rgba(0,212,255,0.4)')
              : 'var(--border)'}`,
            color: filter === f.id
              ? (f.color === 'red' ? 'var(--red)' : f.color === 'amber' ? 'var(--amber)' : f.color === 'info' ? 'var(--info)' : 'var(--cyan)')
              : 'var(--text-2)',
            fontSize: 12, fontWeight: 500,
            display: 'inline-flex', alignItems: 'center', gap: 6,
          }}>
            {f.label}
            <span style={{ fontSize: 10, opacity: 0.7 }}>{counts[f.id]}</span>
          </button>
        ))}
      </div>

      <div style={{ marginBottom: 14 }}>
        <DeviceMultiSelect tankNames={tankNames} selected={selectedTanks} onChange={setSelectedTanks}/>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {filtered.map(a => <AlertItem key={a.id} alert={a} onAck={() => ack(a.id)} busy={saving}/>)}
        {filtered.length === 0 && (
          <div style={{ textAlign: 'center', padding: '40px 20px', color: 'var(--text-3)' }}>
            <Ic name="checkCircle" size={36} color="var(--text-3)"/>
            <div style={{ marginTop: 10, fontSize: 14 }}>No alerts match the filter.</div>
          </div>
        )}
      </div>
    </div>
  );
};

const DeviceMultiSelect = ({ tankNames, selected, onChange }) => {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    if (!open) return;
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [open]);

  const label = selected.length === 0 ? 'All devices'
    : selected.length === 1 ? selected[0]
    : `${selected.length} devices`;

  const toggle = (name) => {
    onChange(prev => prev.includes(name) ? prev.filter(n => n !== name) : [...prev, name]);
  };

  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button onClick={() => setOpen(v => !v)} style={{
        display: 'flex', alignItems: 'center', gap: 8, width: '100%',
        background: 'rgba(255,255,255,0.04)', border: `1px solid ${open ? 'rgba(0,212,255,0.4)' : 'var(--border)'}`,
        borderRadius: 10, padding: '10px 12px',
        color: selected.length > 0 ? 'var(--cyan)' : 'var(--text)', fontSize: 13, cursor: 'pointer',
        textAlign: 'left',
      }}>
        <Ic name="filter" size={14} color={selected.length > 0 ? 'var(--cyan)' : 'var(--text-2)'}/>
        <span style={{ flex: 1 }}>{label}</span>
        {selected.length > 0 && (
          <span onClick={e => { e.stopPropagation(); onChange([]); }} style={{
            fontSize: 11, padding: '2px 6px', borderRadius: 99,
            background: 'rgba(0,212,255,0.15)', color: 'var(--cyan)',
            cursor: 'pointer', lineHeight: 1.4,
          }}>Clear</span>
        )}
        <Ic name="chevronDown" size={14} color="var(--text-2)"/>
      </button>
      {open && (
        <div style={{
          position: 'absolute', top: 'calc(100% + 4px)', left: 0, right: 0, zIndex: 200,
          background: 'var(--bg-2)', border: '1px solid var(--border)',
          borderRadius: 14, padding: '6px 0',
          boxShadow: '0 8px 28px rgba(0,0,0,0.55)',
          maxHeight: 260, overflowY: 'auto',
        }} onClick={e => e.stopPropagation()}>
          {/* All devices row */}
          <div onClick={() => { onChange([]); setOpen(false); }} style={{
            display: 'flex', alignItems: 'center', gap: 10,
            padding: '10px 16px', cursor: 'pointer',
            borderBottom: '1px solid var(--border)',
            color: selected.length === 0 ? 'var(--cyan)' : 'var(--text)',
            fontWeight: selected.length === 0 ? 600 : 400,
          }}>
            <div style={{
              width: 18, height: 18, borderRadius: 5, flexShrink: 0,
              border: `2px solid ${selected.length === 0 ? 'var(--cyan)' : 'var(--border)'}`,
              background: selected.length === 0 ? 'var(--cyan)' : 'transparent',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              {selected.length === 0 && <Ic name="check" size={11} color="#0a0e27"/>}
            </div>
            All devices
          </div>
          {tankNames.map(name => (
            <div key={name} onClick={() => toggle(name)} style={{
              display: 'flex', alignItems: 'center', gap: 10,
              padding: '10px 16px', cursor: 'pointer',
              color: selected.includes(name) ? 'var(--cyan)' : 'var(--text)',
            }}>
              <div style={{
                width: 18, height: 18, borderRadius: 5, flexShrink: 0,
                border: `2px solid ${selected.includes(name) ? 'var(--cyan)' : 'var(--border)'}`,
                background: selected.includes(name) ? 'var(--cyan)' : 'transparent',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>
                {selected.includes(name) && <Ic name="check" size={11} color="#0a0e27"/>}
              </div>
              <span style={{ fontSize: 13 }}>{name}</span>
            </div>
          ))}
          {tankNames.length === 0 && (
            <div style={{ padding: '10px 16px', fontSize: 12, color: 'var(--text-3)' }}>No devices with alerts</div>
          )}
        </div>
      )}
    </div>
  );
};

const AlertItem = ({ alert, onAck, busy }) => {
  const map = {
    critical: { color: 'var(--red)', bg: 'rgba(255,82,82,0.10)', icon: 'alert', label: 'CRITICAL' },
    warning:  { color: 'var(--amber)', bg: 'rgba(255,171,64,0.10)', icon: 'zap', label: 'WARNING' },
    info:     { color: 'var(--info)', bg: 'rgba(64,196,255,0.10)', icon: 'info', label: 'INFO' },
  }[alert.sev];
  return (
    <Card style={{ padding: 12, opacity: alert.ack ? 0.6 : 1 }} accent={alert.sev === 'critical' ? 'red' : alert.sev === 'warning' ? 'amber' : undefined}>
      <div style={{ display: 'flex', gap: 10 }}>
        <div style={{
          width: 32, height: 32, borderRadius: 10,
          background: map.bg,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          flexShrink: 0,
        }}>
          <Ic name={map.icon} size={16} color={map.color}/>
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 2 }}>
            <Badge color={alert.sev === 'critical' ? 'red' : alert.sev === 'warning' ? 'amber' : 'info'} size="sm">{map.label}</Badge>
            {!alert.ack && <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--cyan)', animation: 'pulse-dot 1.4s ease-in-out infinite' }}/>}
            <span style={{ fontSize: 11, color: 'var(--text-3)', marginLeft: 'auto' }}>{formatAlertTime(alert.ts, window.PREFS?.timezone)}</span>
          </div>
          <div style={{ fontSize: 14, fontWeight: 600 }}>{alert.title}</div>
          <div style={{ fontSize: 12, color: 'var(--text-2)', marginTop: 2 }}>{alert.desc}</div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 8 }}>
            <div style={{ fontSize: 11, color: 'var(--text-3)' }}>{alert.tank}</div>
            {!alert.ack ? (
              <button onClick={onAck} disabled={busy} style={{ background: 'transparent', border: 'none', color: busy ? 'var(--text-3)' : 'var(--cyan)', fontSize: 12, fontWeight: 600, display: 'inline-flex', alignItems: 'center', gap: 4, cursor: busy ? 'not-allowed' : 'pointer' }}>
                <Ic name="check" size={12}/> {busy ? 'Saving…' : 'Acknowledge'}
              </button>
            ) : (
              <span style={{ fontSize: 11, color: 'var(--text-3)', display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                <Ic name="check" size={12}/> Acknowledged
              </span>
            )}
          </div>
        </div>
      </div>
    </Card>
  );
};

window.Alerts = Alerts;
window.DeviceMultiSelect = DeviceMultiSelect;
