/* ============================================================
   App — Módulo Sonar
   State management + screen routing + Tweaks integration
   ============================================================ */

const SonarApp = () => {
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
    "elapsedMin": 14,
    "showDiscarded": true,
    "currentPlate": "none",
    "density": "equilibrado",
    "accent": "cyan",
    "pulsoLayout": "bottom",
    "apariencia": "minimalista",
    "theme": "oscuro",
    "cardStyle": "con-bordes"
  }/*EDITMODE-END*/;

  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [screen, setScreen] = React.useState("mapa");
  const [plate, setPlate] = React.useState(null);
  // Feature gating: solo navega/renderiza pantallas habilitadas (window.SONAR_FEATURES viene de /api/config).
  const enabledScreens = (window.SONAR_FEATURES && window.SONAR_FEATURES.enabledScreens)
    || ["mapa", "registrar", "alertas", "rebote", "candado", "nodos"];
  const canGo = (id) => enabledScreens.includes(id);
  const navTo = (id) => { if (canGo(id)) setScreen(id); };
  // Estado de cada alerta en el flujo operativo, por placa:
  // "no_leida" → bandeja No leídas | "revision" → abierta, pendiente de decisión
  // "archivada" → resuelta sin plan | "ejecutada" → plan candado activo
  const [alertMap, setAlertMap] = React.useState({});
  // Alertas creadas por el operador desde "Registrar placa".
  const [customAlerts, setCustomAlerts] = React.useState([]);
  // Alertas históricas gestionadas (vía SonarAPI: mock en Parte A, backend en Parte B).
  const [seedGestionadas, setSeedGestionadas] = React.useState([]);
  React.useEffect(() => { window.SonarAPI.getSeedGestionadas().then(setSeedGestionadas).catch(() => {}); }, []);
  // Alertas activas REALES del backend (sonar.alert_inbox). getAlerts embebe su metadata en SONAR_PLATES.
  const [liveAlerts, setLiveAlerts] = React.useState([]);
  React.useEffect(() => {
    window.SonarAPI.getAlerts().then(al => {
      setLiveAlerts(al || []);
      setAlertMap(m => { const n = { ...m }; (al || []).forEach(a => { if (n[a.key] === undefined) n[a.key] = a.status || "no_leida"; }); return n; });
    }).catch(() => {});
  }, []);
  // Arranque en 2 pasos: (1) /api/config público (authEnabled + paneles habilitados), (2) login si
  // hace falta → bootstrap. En local con auth off es transparente (entra directo, como antes).
  const [phase, setPhase] = React.useState("loading");   // loading | login | ready
  const [operador, setOperador] = React.useState(() => {
    const u = window.SonarAPI.getUser ? window.SonarAPI.getUser() : null;
    return (u && u.usuario) || null;
  });
  const arrancarSesion = React.useCallback(async () => {
    await window.SonarAPI.bootstrap();
    setPhase("ready");
  }, []);
  React.useEffect(() => {
    (async () => {
      let cfg = null;
      try { cfg = await window.SonarAPI.getConfig(); } catch (e) {}
      window.SONAR_FEATURES = (cfg && { enabledScreens: cfg.enabledScreens, appVersion: cfg.appVersion })
        || window.SONAR_FEATURES
        || { enabledScreens: ["mapa", "registrar", "alertas", "rebote", "candado", "nodos"] };
      const authOn = !!(cfg && cfg.authEnabled);
      if (authOn && !window.SonarAPI.hasToken()) { setPhase("login"); return; }
      try { await arrancarSesion(); }
      catch (e) {
        if (authOn) { window.SonarAPI.logout(); setOperador(null); setPhase("login"); }
        else setPhase("ready");   // sin auth, un fallo de bootstrap no debe trabar la app
      }
    })();
  }, []);
  const onLogin = async (usuario, clave) => {
    await window.SonarAPI.login(usuario, clave);   // lanza si las credenciales son inválidas
    setOperador(usuario);
    setPhase("loading");        // credenciales OK → pantalla negra "Conectando…" mientras carga el backend
    await arrancarSesion();     // bootstrap → setPhase("ready")
  };
  const onLogout = () => { window.SonarAPI.logout(); window.location.reload(); };
  // Placa precargada al ir a "Registrar placa" desde una búsqueda en el Mapa.
  const [registrarPrefill, setRegistrarPrefill] = React.useState("");
  const goRegister = (placa) => {
    if (!canGo("registrar")) return;
    setRegistrarPrefill(window.SONAR_normalizePlate(placa || ""));
    setScreen("registrar");
  };
  // Búsqueda automática por código en Operatividad (desde el "ver más" del mapa).
  const [nodosBuscar, setNodosBuscar] = React.useState("");
  const irANodoPorCodigo = (codigo) => {
    if (!canGo("nodos")) return;
    setNodosBuscar(codigo || ""); setScreen("nodos");
  };
  // Lista de alertas activas con su estado — TODAS reales (backend + registradas por el operador).
  const alerts = [
    // Alertas activas REALES del backend (sonar.alert_inbox).
    ...liveAlerts.map(a => ({ key: a.key, enabled: true, status: alertMap[a.key] || a.status || "no_leida" })),
    // Históricas ya gestionadas (3 semanas de bandeja).
    ...seedGestionadas.map(g => ({ key: g.key, enabled: true, status: alertMap[g.key] || g.status })),
    ...customAlerts.map(key => ({ key, enabled: true, status: alertMap[key] || "no_leida" })),
  ].filter(a => a.enabled);

  // Alta de una marcación desde el formulario → entra a la bandeja
  // como no leída y lleva al operador a Alertas.
  const onRegisterPlate = (key) => {
    if (!canGo("alertas")) return;
    setAlertMap(m => ({ ...m, [key]: "no_leida" }));
    setCustomAlerts(a => (a.includes(key) ? a : [...a, key]));
    setScreen("alertas");
  };

  // Abrir una alerta no leída → carga el vehículo en el MAPA (análisis primero)
  // y la pasa a "en revisión".
  const onOpenAlert = async (plateKey) => {
    const p = await window.SonarAPI.getPlate(plateKey);
    if (p) { setPlate(p); setTweak("currentPlate", plateKey); }
    setAlertMap(m => ({ ...m, [plateKey]: "revision" }));
    setScreen("mapa");
  };
  // Resuelve la alerta del vehículo actual (desde Candado).
  const onResolveAlert = (status) => {
    if (!plate) return;
    const key = window.SONAR_normalizePlate(plate.placa);
    setAlertMap(m => (m[key] !== undefined ? { ...m, [key]: status } : m));
  };
  // Reactivar una alerta gestionada/archivada → vuelve a "pendiente", carga la
  // placa y lleva a Candado para decidir (reactivar plan o cancelar).
  const onReactivarAlert = async (plateKey) => {
    if (!canGo("candado")) return;
    setAlertMap(m => ({ ...m, [plateKey]: "no_leida" }));
    const p = await window.SonarAPI.getPlate(plateKey);
    if (p) { setPlate(p); setTweak("currentPlate", plateKey); }
    setScreen("candado");
  };
  const currentAlertStatus = plate ? alertMap[window.SONAR_normalizePlate(plate.placa)] : undefined;

  // Switching versión sets that versión's natural default theme,
  // but the footer button can still flip it independently.
  const setVersion = (v) => {
    setTweak({ apariencia: v, theme: v === "minimalista" ? "claro" : "oscuro" });
  };
  const toggleTheme = () => setTweak("theme", t.theme === "claro" ? "oscuro" : "claro");

  // Sync plate ↔ tweak
  React.useEffect(() => {
    if (t.currentPlate === "none") {
      if (plate) setPlate(null);
      return;
    }
    let cancelled = false;
    window.SonarAPI.getPlate(t.currentPlate).then(p => {
      if (cancelled) return;
      if (p && (!plate || plate.placa !== p.placa)) setPlate(p);
    });
    return () => { cancelled = true; };
  }, [t.currentPlate]);

  // Auto-refresh EN VIVO de la placa abierta. Cada 15s re-consulta; si llegó una captura
  // nueva (sube total_capturas) reemplaza el detalle → timeline/historial/instantánea se
  // actualizan solos (la URL del snapshot lleva ?v=epoch, así que la imagen también).
  // Polling y no WebSocket a propósito: la data llega a la nube por el push del edge (cron
  // 1-2 min), así que ~15s es tan fresco como puede ser, sin infra extra.
  React.useEffect(() => {
    if (t.currentPlate === "none") return;
    const id = setInterval(async () => {
      const p = await window.SonarAPI.getPlate(t.currentPlate);
      if (!p) return;
      setPlate(prev => {
        if (!prev || window.SONAR_normalizePlate(prev.placa) !== p.placa) return prev;
        if ((p.total_capturas || 0) <= (prev.total_capturas || 0)) return prev;  // nada nuevo
        return p;   // captura nueva → actualizar en vivo
      });
    }, 15000);
    return () => clearInterval(id);
  }, [t.currentPlate]);

  const onSearchPlate = (p) => {
    setPlate(p);
    if (p) {
      const key = window.SONAR_normalizePlate(p.placa);
      setTweak("currentPlate", key);
    } else {
      setTweak("currentPlate", "none");
    }
  };
  const onClearPlate = () => onSearchPlate(null);

  // (Removed legacy lucide.createIcons() effect — icons are now React components via <Icon name=.../>)

  if (phase === "loading") {
    return (
      <div className="sonar-app" data-theme="oscuro" style={{ display: "grid", placeItems: "center", height: "100vh", color: "var(--g-text-mute-dark)", fontSize: 14, letterSpacing: 0.3 }}>
        Conectando con el backend del Departamento del Quindío…
      </div>
    );
  }
  if (phase === "login") {
    return <window.LoginScreen onLogin={onLogin}/>;
  }

  return (
    <div className="sonar-app" data-density={t.density} data-accent={t.accent}
         data-version={t.apariencia}
         data-theme={t.theme}
         data-cards={t.cardStyle}
         data-screen-label={`0${["mapa","registrar","alertas","rebote","candado","nodos"].indexOf(screen) + 1} ${screen}`}>
      <div className="sonar-shell">
        <div className="sonar-logo">
          <div className="sonar-logo__mark">
            <svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                 strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
              <path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/>
              <path d="m9 12 2 2 4-4"/>
            </svg>
          </div>
          <div className="sonar-logo__text">
            <span className="sonar-logo__brand">GUARDIAN</span>
            <span className="sonar-logo__module">SONAR</span>
          </div>
        </div>

        <window.SonarSidebar current={screen} onNav={navTo} plate={plate} theme={t.theme} onToggleTheme={toggleTheme} unreadAlerts={alerts.filter(a => a.status === "no_leida").length} operador={operador} onLogout={onLogout}/>
        <window.SonarTopbar screen={screen} plate={plate} onClearPlate={onClearPlate} theme={t.theme} onToggleTheme={toggleTheme}/>

        <main className="sonar-main">
          {screen === "mapa" && (
            <window.MapaScreen
              plate={plate}
              onSearch={onSearchPlate}
              onNavigate={navTo}
              pulsoLayout={t.pulsoLayout}
              onRegister={canGo("registrar") ? goRegister : null}
              onVerNodo={canGo("nodos") ? irANodoPorCodigo : null}
            />
          )}
          {screen === "registrar" && (
            <window.RegistrarScreen
              onRegister={onRegisterPlate}
              prefillPlaca={registrarPrefill}
            />
          )}
          {screen === "alertas" && (
            <window.AlertasScreen
              alerts={alerts}
              onOpenAlert={onOpenAlert}
              onReactivar={onReactivarAlert}
            />
          )}
          {screen === "rebote" && (
            <window.ReboteScreen
              plate={plate}
              elapsedMin={t.elapsedMin}
              showDiscarded={t.showDiscarded}
              onNavigate={navTo}
            />
          )}
          {screen === "candado" && (
            <window.CandadoScreen
              plate={plate}
              elapsedMin={t.elapsedMin}
              showDiscarded={t.showDiscarded}
              onNavigate={navTo}
              alertStatus={currentAlertStatus}
              onResolveAlert={onResolveAlert}
              onViewPlan={async (planPlaca) => {
                const key = window.SONAR_normalizePlate(planPlaca);
                const p = await window.SonarAPI.getPlate(key);
                if (p) { setPlate(p); setTweak("currentPlate", key); }
              }}
              onFinishAlert={(planPlaca) => {
                const key = window.SONAR_normalizePlate(planPlaca);
                setAlertMap(m => ({ ...m, [key]: "finalizada" }));
              }}
            />
          )}
          {screen === "nodos" && (
            <window.NodosScreen
              onNavigate={navTo}
              buscar={nodosBuscar}
            />
          )}
        </main>

        <window.SonarStatusBar screen={screen} plate={plate}/>
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Inferencia · proyección"/>
        <TweakSlider
          label="Min desde última captura"
          value={t.elapsedMin}
          min={2} max={60} step={1} unit=" min"
          onChange={v => setTweak("elapsedMin", v)}
        />
        <TweakSection label="Apariencia"/>
        <TweakRadio
          label="Tarjetas"
          value={t.cardStyle}
          options={[
            { value: "con-bordes", label: "Con bordes" },
            { value: "sin-bordes", label: "Sin bordes" },
          ]}
          onChange={v => setTweak("cardStyle", v)}
        />
      </TweaksPanel>
    </div>
  );
};

ReactDOM.createRoot(document.getElementById("root")).render(<SonarApp/>);
