// Live Monitoring Command Center

// Map a track (by camera) to a representative event so we can show bbox + zone
function cameraToTrack(cam) {
  // pick first track on that camera, deterministic
  return TRACKS.find((t) => t.camera_id === cam.id);
}
function cameraToZone(cam) {
  return ZONES.find((z) => z.camera_id === cam.id);
}
function cameraStateBadge(cam) {
  // sample state derived from latest events
  const e = EVENTS.find((ev) => ev.camera_id === cam.id);
  if (cam.status === 'offline') return { kind: 'offline', label: 'OFFLINE' };
  if (cam.status === 'degraded') return { kind: 'degraded', label: 'DEGRADADO' };
  if (e?.severity === 'critical') return { kind: 'critical', label: 'ALERTA' };
  if (e?.kind === 'identity_recognized') return { kind: 'identified', label: 'IDENTIFICADO' };
  if (e) return { kind: 'motion', label: 'MOVIMENTO' };
  return { kind: 'ok', label: 'NORMAL' };
}

function CameraTile({ camera, layout, onClick, focused }) {
  const { t } = useI18n();
  const track = cameraToTrack(camera);
  const zone = cameraToZone(camera);
  const state = cameraStateBadge(camera);
  const offline = camera.status === 'offline';
  const now = new Date();

  // Live timestamp - update every second
  const [tick, setTick] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => setTick((v) => v + 1), 1000);
    return () => clearInterval(id);
  }, []);
  const ts = new Date(Date.now());

  const stateClass = {
    critical: 'bg-red-500/90 text-white',
    motion: 'bg-amber-500/90 text-navy-950',
    identified: 'bg-forest-500/90 text-navy-950',
    offline: 'bg-slate-700 text-slate-300',
    degraded: 'bg-orange-500/80 text-navy-950',
    ok: 'bg-slate-800/70 text-slate-300',
  }[state.kind];

  return (
    <button
      onClick={onClick}
      className={`group relative rounded-md overflow-hidden border transition-all text-left ${
        focused ? 'border-forest-500 ring-2 ring-forest-500/40' : 'border-slate-700/70 hover:border-slate-500'
      } ${offline ? 'opacity-70' : ''}`}
      style={{ aspectRatio: '16 / 9' }}
    >
      {/* Feed */}
      <div className="absolute inset-0">
        <SyntheticThumb camera={camera} track={!offline && track} className="absolute inset-0" />
        {!offline && zone && <ZoneOverlay zone={zone} faint />}
        {offline && (
          <div className="absolute inset-0 flex items-center justify-center text-slate-500 flex-col gap-2 bg-navy-950/60">
            <Icons.WifiOff size={28} />
            <span className="text-[11px] uppercase tracking-wider font-medium">{t('grid.tile.offline')}</span>
          </div>
        )}
      </div>

      {/* Top bar overlay */}
      <div className="absolute inset-x-0 top-0 px-2 py-1.5 flex items-center justify-between gap-1 text-[10px] font-mono pointer-events-none">
        <div className="flex items-center gap-1.5 min-w-0">
          <span className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-sm font-semibold tracking-wide ${stateClass}`}>
            {state.kind === 'critical' && <span className="w-1 h-1 rounded-full bg-white animate-pulseDot" />}
            {state.kind === 'motion' && <span className="w-1 h-1 rounded-full bg-navy-950 animate-pulseDot" />}
            {state.label}
          </span>
        </div>
        <span className="text-white/80 bg-black/40 px-1.5 py-0.5 rounded-sm">
          {ts.toLocaleTimeString('pt-PT', { hour: '2-digit', minute: '2-digit', second: '2-digit' })}
        </span>
      </div>

      {/* Bottom bar overlay */}
      <div className="absolute inset-x-0 bottom-0 px-2 py-1.5 flex items-center justify-between gap-1 text-[11px] pointer-events-none">
        <div className="flex items-center gap-1.5 min-w-0 text-white/90">
          {!offline && <span className="w-1.5 h-1.5 rounded-full bg-red-500 animate-pulseDot shrink-0" />}
          <span className="truncate font-medium drop-shadow">{camera.name}</span>
        </div>
        <span className="text-white/70 font-mono shrink-0 drop-shadow">{camera.short}</span>
      </div>

      {/* Hover expand affordance */}
      <div className="absolute inset-0 flex items-center justify-center pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity">
        <div className="w-10 h-10 rounded-full bg-black/40 border border-white/30 backdrop-blur-sm flex items-center justify-center">
          <Icons.Expand size={16} className="text-white" />
        </div>
      </div>
    </button>
  );
}

function CameraGrid({ cameras, layout, onTileClick, focusedId }) {
  const cols = layout === 1 ? 1 : layout === 4 ? 2 : layout === 9 ? 3 : 4;
  const visible = cameras.slice(0, layout);
  return (
    <div className="grid gap-2 w-full" style={{ gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` }}>
      {visible.map((c) => (
        <CameraTile
          key={c.id}
          camera={c}
          layout={layout}
          onClick={() => onTileClick(c)}
          focused={focusedId === c.id}
        />
      ))}
    </div>
  );
}

// Live event row
function EventRow({ event, onClick, isNew }) {
  const { t } = useI18n();
  const cam = lookupCamera(event.camera_id);
  const zone = lookupZone(event.zone_id);
  const trk = lookupTrack(event.track_id);
  const identity = lookupIdentity(event.identity_id);
  const sev = SEVERITY[event.severity];

  return (
    <button
      onClick={onClick}
      className={`w-full text-left px-3 py-2 border-b border-slate-800/70 hover:bg-slate-850/80 transition-colors group flex items-start gap-3 ${
        isNew ? 'animate-slideIn bg-forest-500/5' : ''
      }`}
    >
      {/* Thumb */}
      <div className="w-16 h-9 rounded overflow-hidden bg-slate-800 shrink-0 relative border border-slate-700/60">
        <SyntheticThumb camera={cam} track={trk} className="absolute inset-0" showBox={true} />
      </div>
      <div className="min-w-0 flex-1">
        <div className="flex items-center gap-1.5 flex-wrap">
          <SeverityDot severity={event.severity} pulse={event.severity === 'critical'} size={6} />
          <KindIcon kind={event.kind} size={12} className={sev.text} />
          <span className="text-[12px] text-slate-100 font-medium truncate">{t(`kind.${event.kind}`)}</span>
          {trk?.class && trk.class !== 'person' && (
            <Pill tone="ghost" className="!text-[10px] !py-0">
              <ClassIcon cls={trk.class} size={10} />{t(`class.${trk.class}`)}
            </Pill>
          )}
        </div>
        <div className="flex items-center gap-1 text-[11px] text-slate-400 mt-0.5 flex-wrap">
          <span className="truncate">{cam?.name}</span>
          {zone && (
            <>
              <Icons.ChevronRight size={9} className="text-slate-600" />
              <span className="inline-flex items-center gap-1">
                <span className="w-1 h-1 rounded-full" style={{ background: ZONE_ROLES[zone.semantic_role]?.color }} />
                {zone.name}
              </span>
            </>
          )}
        </div>
        <div className="flex items-center justify-between gap-2 mt-1">
          <span className="text-[11px] text-slate-300 inline-flex items-center gap-1.5 min-w-0">
            {identity ? (
              <>
                <IdentityAvatar identity={identity} size={14} />
                <span className="truncate">{identity.name}</span>
              </>
            ) : (
              <span className="text-slate-500 italic">{t('modal.unknown')}</span>
            )}
          </span>
          <span className="font-mono text-[10px] text-slate-500 shrink-0">{relTime(event.ts)}</span>
        </div>
      </div>
    </button>
  );
}

// Alert row — compact single-row form for the triage strip
function AlertRow({ alert, state, onAck, onEscalate, onDismiss, onOpen }) {
  const { t } = useI18n();
  const cam = lookupCamera(alert.camera_id);
  const zone = lookupZone(alert.zone_id);
  const trk = lookupTrack(alert.track_id);
  const ackd = state?.ackd;

  const tone =
    ackd
      ? 'bg-slate-850/40 border-slate-700/60 opacity-60'
      : alert.severity === 'critical'
      ? 'bg-red-500/8 border-red-500/40'
      : 'bg-orange-500/5 border-orange-500/40';

  return (
    <div className={`border rounded-md px-2.5 py-2 flex items-center gap-2.5 transition-all ${tone}`}>
      {/* Thumb */}
      <button onClick={onOpen} className="w-14 h-9 rounded overflow-hidden bg-slate-800 shrink-0 relative border border-slate-700/60 group">
        <SyntheticThumb camera={cam} track={trk} className="absolute inset-0" showBox />
        <div className="absolute inset-0 flex items-center justify-center bg-black/0 group-hover:bg-black/30 transition-colors">
          <Icons.Play size={12} className="text-white opacity-0 group-hover:opacity-100" />
        </div>
      </button>
      {/* Body */}
      <div className="min-w-0 flex-1">
        <div className="flex items-center gap-1.5 flex-wrap">
          <SeverityBadge severity={alert.severity} />
          <span className="text-[12px] text-slate-100 font-medium truncate">
            {alert.payload?.rule || trk?.caption || t(`kind.${alert.kind}`)}
          </span>
        </div>
        <div className="flex items-center gap-1.5 text-[10px] text-slate-400 mt-0.5 font-mono">
          <span className="truncate">{cam?.name}</span>
          {zone && (
            <>
              <Icons.ChevronRight size={9} className="text-slate-600 shrink-0" />
              <span className="inline-flex items-center gap-1">
                <span className="w-1 h-1 rounded-full" style={{ background: ZONE_ROLES[zone.semantic_role]?.color }} />
                {zone.name}
              </span>
            </>
          )}
          <span className="ml-auto text-slate-500 shrink-0">{relTime(alert.ts)}</span>
        </div>
      </div>
      {/* Actions */}
      <div className="flex items-center gap-1 shrink-0">
        {ackd ? (
          <span className="inline-flex items-center gap-1 text-[10px] text-slate-400 px-1.5">
            <Icons.Check size={11} className="text-forest-400" />
            <IdentityAvatar identity={IDENTITIES[2] || IDENTITIES[0]
              || { name: 'Operador', initials: 'OP' }} size={12} />
            <span className="font-mono">{state.ackAt}</span>
          </span>
        ) : (
          <>
            <IconButton icon={Icons.Check} label={t('alerts.acknowledge')} size="sm" onClick={onAck} className="text-forest-400 hover:bg-forest-500/20" />
            <IconButton icon={Icons.ArrowUp} label={t('alerts.escalate')} size="sm" onClick={onEscalate} className="text-orange-300 hover:bg-orange-500/20" />
            <IconButton icon={Icons.X} label={t('alerts.dismiss')} size="sm" onClick={onDismiss} className="text-slate-500 hover:bg-slate-800" />
          </>
        )}
      </div>
    </div>
  );
}

// MAIN
function MonitoringView({ siteId, onOpenSearch, onFindAgain }) {
  const { t, lang } = useI18n();
  const [layout, setLayout] = React.useState(4);
  const [focusedCamId, setFocusedCamId] = React.useState(null);
  const [openEvent, setOpenEvent] = React.useState(null);

  // Event stream state — copy of mock + simulate new ones
  const [events, setEvents] = React.useState(() => [...EVENTS]);
  const [filters, setFilters] = React.useState({ severity: null, class: null, zone: null, camera: null });
  const [alertStates, setAlertStates] = React.useState({}); // id -> { ackd, ackAt, dismissed, escalated }
  const [dismissedAlerts, setDismissedAlerts] = React.useState({});

  // Simulate occasional new event
  React.useEffect(() => {
    const id = setInterval(() => {
      // pick a random template event, add fresh ts, prepend
      const template = EVENTS[Math.floor(Math.random() * Math.min(EVENTS.length, 8))];
      const newEvt = { ...template, id: `evt-live-${Date.now()}`, ts: Date.now(), _new: true };
      setEvents((prev) => [newEvt, ...prev].slice(0, 60));
    }, 9000);
    return () => clearInterval(id);
  }, []);

  // Filter cameras by site
  const visibleCams = React.useMemo(() => {
    return siteId ? CAMERAS.filter((c) => c.site_id === siteId) : CAMERAS;
  }, [siteId]);

  // Focus a camera first if set
  const orderedCams = React.useMemo(() => {
    if (!focusedCamId) return visibleCams;
    const focused = visibleCams.find((c) => c.id === focusedCamId);
    const rest = visibleCams.filter((c) => c.id !== focusedCamId);
    return focused ? [focused, ...rest] : visibleCams;
  }, [visibleCams, focusedCamId]);

  // Filter events
  const filteredEvents = React.useMemo(() => {
    return events.filter((e) => {
      const cam = lookupCamera(e.camera_id);
      if (siteId && cam?.site_id !== siteId) return false;
      if (filters.severity && e.severity !== filters.severity) return false;
      if (filters.zone && e.zone_id !== filters.zone) return false;
      if (filters.camera && e.camera_id !== filters.camera) return false;
      if (filters.class) {
        const trk = lookupTrack(e.track_id);
        if (trk?.class !== filters.class) return false;
      }
      return true;
    });
  }, [events, filters, siteId]);

  // Alerts: high + critical, unconfirmed first
  const alerts = React.useMemo(() => {
    return events
      .filter((e) => (e.severity === 'critical' || e.severity === 'high') && !dismissedAlerts[e.id])
      .filter((e) => {
        const cam = lookupCamera(e.camera_id);
        return !siteId || cam?.site_id === siteId;
      });
  }, [events, dismissedAlerts, siteId]);

  const camerasOnline = visibleCams.filter((c) => c.status === 'online').length;
  const camerasTotal = visibleCams.length;
  const onlinePct = Math.round((camerasOnline / Math.max(1, camerasTotal)) * 100);

  function ackAlert(id) {
    setAlertStates((s) => ({ ...s, [id]: { ackd: true, ackAt: new Date().toLocaleTimeString('pt-PT', { hour: '2-digit', minute: '2-digit' }) } }));
  }
  function escalateAlert(id) {
    setAlertStates((s) => ({ ...s, [id]: { ...(s[id] || {}), escalated: true } }));
  }
  function dismissAlert(id) {
    setDismissedAlerts((s) => ({ ...s, [id]: true }));
  }

  const layoutBtn = (n) => (
    <button
      key={n}
      onClick={() => setLayout(n)}
      className={`h-7 w-9 inline-flex items-center justify-center rounded text-[11px] font-mono font-medium border transition-colors ${
        layout === n ? 'bg-forest-600 border-forest-500 text-white' : 'bg-slate-850 border-slate-700 text-slate-300 hover:bg-slate-800'
      }`}
    >
      {n === 1 ? '1' : n === 4 ? '2×2' : n === 9 ? '3×3' : '4×4'}
    </button>
  );

  const pendingAlerts = alerts.filter((a) => !alertStates[a.id]?.ackd);
  const [alertsOpen, setAlertsOpen] = React.useState(true);

  return (
    <div className="flex flex-col h-full min-h-0">
      {/* Compact KPI strip */}
      <div className="px-4 pt-3 pb-2 grid grid-cols-2 lg:grid-cols-4 gap-2 shrink-0">
        <KPI label={t('kpi.events')} value={KPIS.eventsToday.toLocaleString('pt-PT')} icon={Icons.Bell} trend="+12% hoje" />
        <KPI
          label={t('kpi.alerts')}
          value={pendingAlerts.length}
          suffix={`/ ${alerts.length}`}
          icon={Icons.Alert}
          accent={pendingAlerts.length ? 'text-red-400' : 'text-forest-400'}
          trend={pendingAlerts.filter(a => a.severity === 'critical').length ? `${pendingAlerts.filter(a => a.severity === 'critical').length} críticos` : 'tudo limpo'}
        />
        <KPI label={t('kpi.cameras')} value={`${camerasOnline}/${camerasTotal}`} suffix={`${onlinePct}%`} icon={Icons.Video} />
        <KPI label={t('kpi.response')} value={`${KPIS.avgResponseSec}s`} icon={Icons.Clock} trend="-4s vs sem." />
      </div>

      {/* Body: grid + right rail (rail shows at lg+ for more density) */}
      <div className="flex-1 min-h-0 px-4 pb-4 grid grid-cols-1 lg:grid-cols-[1fr_340px] gap-3 overflow-hidden">
        {/* Center: alerts + grid */}
        <div className="flex flex-col min-h-0 gap-3">
          {/* Critical alerts banner — collapsible, capped height */}
          {alerts.length > 0 && (
            <div className={`shrink-0 border rounded-md ${pendingAlerts.length ? 'bg-red-500/[0.04] border-red-500/30' : 'bg-slate-850/40 border-slate-700/60'} flex flex-col min-h-0`}>
              <button
                onClick={() => setAlertsOpen((o) => !o)}
                className="flex items-center justify-between px-3 py-2 w-full text-left hover:bg-white/[0.02] transition-colors"
              >
                <div className="flex items-center gap-2">
                  <Icons.Alert size={13} className={pendingAlerts.length ? 'text-red-400' : 'text-slate-500'} />
                  <span className="font-display text-[11px] uppercase tracking-[0.12em] text-slate-200 font-semibold">{t('alerts.title')}</span>
                  {pendingAlerts.length > 0 ? (
                    <span className="inline-flex items-center gap-1 text-[10px] font-mono text-red-300 bg-red-500/10 border border-red-500/30 rounded-full px-1.5">
                      <span className="w-1 h-1 rounded-full bg-red-500 animate-pulseDot" />
                      {pendingAlerts.length} pendente{pendingAlerts.length === 1 ? '' : 's'}
                    </span>
                  ) : (
                    <span className="text-[10px] font-mono text-forest-400">tudo confirmado</span>
                  )}
                  {!alertsOpen && pendingAlerts[0] && (
                    <span className="text-[11px] text-slate-300 truncate ml-2 hidden sm:inline max-w-[420px]">
                      → {pendingAlerts[0].payload?.rule || lookupTrack(pendingAlerts[0].track_id)?.caption || t(`kind.${pendingAlerts[0].kind}`)}
                    </span>
                  )}
                </div>
                <span className="text-slate-400">
                  <Icons.ChevronDown size={14} className={`transition-transform ${alertsOpen ? '' : '-rotate-90'}`} />
                </span>
              </button>
              {alertsOpen && (
                <div className="overflow-y-auto px-2 pb-2 space-y-1.5 border-t border-current/10" style={{ maxHeight: 180 }}>
                  {alerts.map((a) => (
                    <AlertRow
                      key={a.id}
                      alert={a}
                      state={alertStates[a.id]}
                      onAck={() => ackAlert(a.id)}
                      onEscalate={() => escalateAlert(a.id)}
                      onDismiss={() => dismissAlert(a.id)}
                      onOpen={() => setOpenEvent(a)}
                    />
                  ))}
                </div>
              )}
            </div>
          )}

          {/* Camera grid */}
          <Section
            title={
              <>
                <Icons.Grid size={13} />
                <span>Câmaras ao vivo</span>
                <Pill tone="ghost" className="ml-1">
                  <span className="w-1.5 h-1.5 rounded-full bg-red-500 animate-pulseDot" />
                  {t('feed.live')}
                </Pill>
              </>
            }
            action={
              <div className="flex items-center gap-1">
                {[1, 4, 9, 16].map(layoutBtn)}
              </div>
            }
            dense
            className="flex-1 min-h-0"
          >
            <div className="p-2.5 overflow-auto h-full">
              <CameraGrid
                cameras={orderedCams}
                layout={layout}
                onTileClick={(c) => {
                  if (layout === 1) {
                    setFocusedCamId(null);
                    setLayout(4);
                  } else {
                    setFocusedCamId(c.id);
                    setLayout(1);
                  }
                }}
                focusedId={focusedCamId}
              />
            </div>
          </Section>
        </div>

        {/* Right rail */}
        <Section
          title={
            <>
              <Icons.List size={13} />
              <span>{t('feed.title')}</span>
              <span className="ml-1 inline-flex items-center gap-1 text-[10px] font-mono text-red-300">
                <span className="w-1.5 h-1.5 rounded-full bg-red-500 animate-pulseDot" />
                {t('feed.live')}
              </span>
            </>
          }
          action={<span className="text-[10px] font-mono text-slate-500">{filteredEvents.length} / {events.length}</span>}
          dense
          className="min-h-0"
        >
          <div className="flex flex-col h-full min-h-0">
            {/* Filter chips */}
            <div className="px-3 py-2 border-b border-slate-800/70 flex flex-wrap gap-1.5 shrink-0">
              <Chip active={!filters.severity} onClick={() => setFilters((f) => ({ ...f, severity: null }))}>
                {t('feed.all')}
              </Chip>
              {['critical', 'high', 'medium', 'low', 'info'].map((s) => (
                <Chip key={s} active={filters.severity === s} onClick={() => setFilters((f) => ({ ...f, severity: f.severity === s ? null : s }))}>
                  <SeverityDot severity={s} size={6} /> {t(`sev.${s}`)}
                </Chip>
              ))}
              <div className="basis-full h-0" />
              {['person', 'vehicle', 'animal'].map((c) => (
                <Chip key={c} active={filters.class === c} onClick={() => setFilters((f) => ({ ...f, class: f.class === c ? null : c }))}>
                  <ClassIcon cls={c} size={10} /> {t(`class.${c}`)}
                </Chip>
              ))}
            </div>
            {/* Stream */}
            <div className="overflow-y-auto flex-1 min-h-0">
              {filteredEvents.length === 0 ? (
                <div className="text-center text-[12px] text-slate-500 py-8 px-4">{t('feed.empty')}</div>
              ) : (
                filteredEvents.map((e, i) => (
                  <EventRow key={e.id} event={e} onClick={() => setOpenEvent(e)} isNew={i === 0 && e._new} />
                ))
              )}
            </div>
          </div>
        </Section>
      </div>

      {openEvent && (
        <ClipModal
          event={openEvent}
          onClose={() => setOpenEvent(null)}
          onFindAgain={(trk) => {
            setOpenEvent(null);
            onFindAgain?.(trk);
          }}
        />
      )}
    </div>
  );
}

window.MonitoringView = MonitoringView;
