/* ============================================================
   Pantalla — Candado (plan táctico)
   - Borrador: construye plan con checkpoints seleccionados.
   - Ejecutar: dispara alertas simuladas a comandancia + patrullas
     (canales WhatsApp + SMS al PDA).
   - Activos: lista los planes en curso con opción de cancelar.
   ============================================================ */

// Sin planes pre-cargados: la bandeja de activos arranca vacía.
const __SEED_ACTIVE_PLANS = [];

const CandadoScreen = ({ plate, elapsedMin, showDiscarded, onNavigate, alertStatus, onResolveAlert, onViewPlan, onFinishAlert }) => {
  const [selected, setSelected] = React.useState(new Set());
  const [exportOpen, setExportOpen] = React.useState(false);
  const [shareToast, setShareToast] = React.useState(false);
  const [activePlans, setActivePlans] = React.useState(__SEED_ACTIVE_PLANS);
  const [tab, setTab] = React.useState("borrador");  // "borrador" | "activos"
  const [executeFlow, setExecuteFlow] = React.useState(null);  // null | "confirming" | "sending" | "done"
  const [pendingPlan, setPendingPlan] = React.useState(null);

  const [projection, setProjection] = React.useState(null);
  const [checkpoints, setCheckpoints] = React.useState([]);
  React.useEffect(() => {
    if (!plate) { setProjection(null); setCheckpoints([]); return; }
    let cancelled = false;
    (async () => {
      const proj = await window.SonarAPI.getProjection(plate.placa);
      if (cancelled) return;
      setProjection(proj);
      const cps = await window.SonarAPI.getCheckpoints(plate.placa);
      if (!cancelled) setCheckpoints(cps || []);
    })();
    return () => { cancelled = true; };
  }, [plate]);

  const toggle = (id) => {
    const next = new Set(selected);
    if (next.has(id)) next.delete(id); else next.add(id);
    setSelected(next);
  };

  const totalCritical = checkpoints.filter(c => c.prioridad === "crítica").length;
  const selCount = selected.size;
  const selByPriority = checkpoints.reduce((acc, c) => {
    if (selected.has(c.id)) acc[c.prioridad] = (acc[c.prioridad] || 0) + 1;
    return acc;
  }, {});
  const selectedCheckpointObjects = checkpoints.filter(c => selected.has(c.id));

  // ¿La placa actual ya tiene un plan en ejecución? → modo "actualizar".
  const existingPlan = plate
    ? activePlans.find(p => window.SONAR_normalizePlate(p.placa) === window.SONAR_normalizePlate(plate.placa))
    : null;

  // Al cambiar de placa: si esa placa ya tiene un plan activo, precargamos
  // SUS puntos en el borrador (para verlo tal como se creó). Si no, dejamos
  // la selección sugerida por defecto.
  const lastPlateRef = React.useRef(null);
  React.useEffect(() => {
    const key = plate ? window.SONAR_normalizePlate(plate.placa) : null;
    if (key === lastPlateRef.current) return;
    lastPlateRef.current = key;
    if (!plate) return;
    if (existingPlan) {
      setSelected(new Set(existingPlan.checkpoints.map(c => c.id)));
      setTab("borrador");
    }
    // Sin plan previo: la selección por defecto (puntos críticos) la pone el
    // efecto de checkpoints en cuanto el backend los devuelve.
  }, [plate, existingPlan]);

  // Default de borrador: preseleccionar los checkpoints críticos cuando llegan.
  const defaultedRef = React.useRef(null);
  React.useEffect(() => {
    if (!plate || existingPlan || !checkpoints.length) return;
    const key = window.SONAR_normalizePlate(plate.placa);
    if (defaultedRef.current === key) return;
    defaultedRef.current = key;
    setSelected(new Set(checkpoints.filter(c => c.prioridad === "crítica").map(c => c.id)));
  }, [plate, existingPlan, checkpoints]);

  // ¿La selección difiere del plan activo? Sólo entonces tiene sentido actualizar.
  const planIds = existingPlan ? new Set(existingPlan.checkpoints.map(c => c.id)) : null;
  const selectionChanged = existingPlan
    ? (planIds.size !== selected.size || [...selected].some(id => !planIds.has(id)))
    : true;

  const doShare = () => {
    setShareToast(true);
    setTimeout(() => setShareToast(false), 2400);
  };

  const startExecute = () => {
    setExecuteFlow("confirming");
  };
  const confirmExecute = () => {
    setExecuteFlow("sending");
    const isUpdate = !!existingPlan;
    // Si ya hay un plan para esta placa, conservamos su id (actualización);
    // si no, generamos uno nuevo.
    const newPlan = {
      id: isUpdate ? existingPlan.id : `CAN-2026-${String(Math.floor(Math.random() * 9000) + 1000)}`,
      isUpdate,
      placa: plate.placa,
      motivo: plate.marcaciones.length > 0 ? plate.marcaciones[0].motivo : "Vehículo en seguimiento operacional",
      activatedAt: window.SONAR_fmtTime(window.SONAR_NOW),
      activatedAgo: 0,
      checkpoints: selectedCheckpointObjects.map(c => ({ id: c.id, nombre: c.nombre, prioridad: c.prioridad })),
      unitCount: selCount * 2,
      channels: [
        { type: "whatsapp", target: "Comando Policía Quindío",  status: "pending", ts: "—" },
        { type: "whatsapp", target: "GAULA Eje Cafetero",   status: "pending", ts: "—" },
        { type: "whatsapp", target: "SIJIN Armenia",        status: "pending", ts: "—" },
        { type: "sms",      target: `PDA Patrulla ${10 + Math.floor(Math.random() * 30)}`, status: "pending", ts: "—" },
        { type: "sms",      target: `PDA Patrulla ${10 + Math.floor(Math.random() * 30)}`, status: "pending", ts: "—" },
      ],
    };
    setPendingPlan(newPlan);
    setTimeout(() => {
      // Mark all channels delivered
      const delivered = {
        ...newPlan,
        channels: newPlan.channels.map((c, i) => ({
          ...c, status: i < 3 ? "read" : "delivered",
          ts: newPlan.activatedAt,
        })),
      };
      setPendingPlan(delivered);
      setExecuteFlow("done");
    }, 4200);
  };
  const finishExecute = () => {
    if (pendingPlan) {
      // Actualización: reemplaza el plan existente conservando su posición.
      if (pendingPlan.isUpdate) {
        setActivePlans(prev => prev.map(p => p.id === pendingPlan.id ? pendingPlan : p));
      } else {
        setActivePlans(prev => [pendingPlan, ...prev]);
      }
      setSelected(new Set());
      setTab("activos");
    }
    if (onResolveAlert) onResolveAlert("ejecutada");
    setPendingPlan(null);
    setExecuteFlow(null);
  };
  const closeExecute = () => {
    setPendingPlan(null);
    setExecuteFlow(null);
  };

  const cancelPlan = (planId) => {
    setActivePlans(prev => prev.filter(p => p.id !== planId));
    // Cancelar también descarta cualquier ventana de envío/animación abierta.
    setPendingPlan(null);
    setExecuteFlow(null);
  };
  // Finalizar plan (vehículo localizado / tiempo excedido) → notifica cierre,
  // retira el plan activo y marca la alerta como "finalizada".
  const finishPlan = (planId, reason) => {
    const plan = activePlans.find(p => p.id === planId);
    if (plan && onFinishAlert) onFinishAlert(plan.placa);
    setActivePlans(prev => prev.filter(p => p.id !== planId));
  };
  // Ver un plan activo en el mapa: carga su placa, precarga SUS puntos y abre
  // el borrador. Funciona aunque la placa ya esté cargada.
  const viewPlanOnMap = (plan) => {
    if (onViewPlan) onViewPlan(plan.placa);
    lastPlateRef.current = window.SONAR_normalizePlate(plan.placa);
    setSelected(new Set(plan.checkpoints.map(c => c.id)));
    setTab("borrador");
  };

  // Sin placa cargada: la sección sigue activa. Mostramos los planes
  // activos (o un vacío) y un aviso para ir al Mapa a elegir una placa.
  if (!plate) {
    return (
      <div className="fade-in" style={{
        height: "100%", display: "grid",
        gridTemplateColumns: "minmax(0, 1fr) 480px",
        minHeight: 0, position: "relative",
      }}>
        {/* Izquierda: prompt para elegir placa */}
        <div style={{ position: "relative", overflow: "hidden", background: "var(--s-map-bg)", display: "grid", placeItems: "center", padding: 40 }}>
          <div style={{ maxWidth: 380, textAlign: "center" }}>
            <div style={{
              width: 64, height: 64, borderRadius: "50%", margin: "0 auto 20px",
              background: "rgba(242, 198, 29, 0.12)", display: "grid", placeItems: "center",
            }}>
              <window.Icon name="lock" size={28} color="var(--g-signal-yellow)"/>
            </div>
            <h2 className="ds-h3" style={{ fontSize: 22, fontWeight: 600, color: "var(--g-text-cream)", letterSpacing: -0.3 }}>
              Sin plan en preparación
            </h2>
            <p style={{ fontSize: 14, color: "var(--g-text-mute-dark)", marginTop: 10, lineHeight: 1.55 }}>
              Para armar un plan candado primero consulta una placa en el Mapa. Con la última captura, Sonar proyecta los corredores y sugiere puntos de control.
            </p>
            <button className="btn btn--primary" style={{ marginTop: 20, padding: "11px 18px" }} onClick={() => onNavigate("mapa")}>
              <window.Icon name="map" size={15}/> Ir al Mapa a elegir placa
              <window.Icon name="arrow-right" size={15} style={{ marginLeft: 6 }}/>
            </button>
          </div>
        </div>

        {/* Derecha: planes activos (persisten sin placa) */}
        <div style={{
          borderLeft: "1px solid var(--g-border-on-dark)",
          background: "var(--s-panel)",
          display: "flex", flexDirection: "column", minHeight: 0,
        }}>
          <div style={{
            display: "flex", borderBottom: "1px solid var(--g-border-on-dark)", flexShrink: 0,
          }}>
            <TabBtn label="Activos" active={true} onClick={() => {}}
              badge={activePlans.length}
              badgeColor={activePlans.length > 0 ? "var(--g-signal-green)" : null}
              pulse={activePlans.length > 0}/>
          </div>
          <ActivosPanel plans={activePlans} onCancel={cancelPlan} onFinish={finishPlan} onViewPlan={viewPlanOnMap} onCreateNew={() => onNavigate("mapa")}/>
        </div>
      </div>
    );
  }

  return (
    <div className="fade-in" style={{
      height: "100%",
      display: "grid",
      gridTemplateColumns: "minmax(0, 1fr) 480px",
      minHeight: 0,
      position: "relative",
    }}>
      {/* MAP */}
      <div style={{ position: "relative", overflow: "hidden", background: "var(--s-map-bg)", minWidth: 0 }}>
        {/* Header */}
        <div style={{
          position: "absolute", top: 18, left: 18, zIndex: 10,
          padding: "12px 16px",
          background: "var(--s-glass)",
          backdropFilter: "blur(12px)",
          border: "1px solid var(--g-border-on-dark)",
          borderRadius: "var(--g-radius-card)",
          display: "flex", alignItems: "center", gap: 14,
        }}>
          <div style={{
            width: 36, height: 36, borderRadius: "50%",
            background: "rgba(242, 198, 29, 0.15)",
            display: "grid", placeItems: "center",
          }}>
            <window.Icon name="lock" style={{ width: 18, height: 18, color: "var(--g-signal-yellow)" }}/>
          </div>
          <div>
            <div className="eyebrow eyebrow--accent" style={{ marginBottom: 2 }}>
              {tab === "borrador" ? "Plan candado · borrador" : "Planes candado · en ejecución"}
            </div>
            <div style={{ fontSize: 15, fontWeight: 500, color: "var(--g-text-cream)", letterSpacing: -0.2 }}>
              <span className="plate plate--sm" style={{ marginRight: 8, verticalAlign: "middle" }}>{plate.placa}</span>
              {tab === "borrador"
                ? `${selCount} ${selCount === 1 ? "punto seleccionado" : "puntos seleccionados"} de ${checkpoints.length}`
                : `${activePlans.length} ${activePlans.length === 1 ? "plan activo" : "planes activos"}`}
            </div>
          </div>
        </div>

        {/* Legend */}
        <div style={{
          position: "absolute", bottom: 18, left: 18, zIndex: 10,
          padding: "12px 14px",
          background: "var(--s-glass)",
          backdropFilter: "blur(12px)",
          border: "1px solid var(--g-border-on-dark)",
          borderRadius: "var(--g-radius-card)",
          display: "flex", flexDirection: "column", gap: 8,
          fontSize: 11, color: "var(--g-text-mute-dark)",
        }}>
          <div className="eyebrow" style={{ marginBottom: 2 }}>Prioridad punto candado</div>
          <PrioLegendItem color="#E5333F" label="Crítica · cuello de botella"/>
          <PrioLegendItem color="#F2C61D" label="Alta · intersección clave"/>
          <PrioLegendItem color="#4FD4FF" label="Media · sin cobertura ANPR"/>
        </div>

        <window.QuindioMap
          mode="candado"
          plate={plate}
          projection={projection}
          checkpoints={checkpoints}
          selectedCheckpoints={selected}
          onToggleCheckpoint={toggle}
          showDiscarded={showDiscarded}
          fillToBorder={true}
        />
      </div>

      {/* RIGHT PANEL */}
      <div style={{
        borderLeft: "1px solid var(--g-border-on-dark)",
        background: "var(--s-panel)",
        display: "flex", flexDirection: "column",
        minHeight: 0,      // critical: lets the flex child scroll
        overflow: "hidden",
      }}>
        {/* Tabs */}
        <div style={{
          display: "flex",
          borderBottom: "1px solid var(--g-border-on-dark)",
          flexShrink: 0,
        }}>
          <TabBtn
            label="Borrador"
            active={tab === "borrador"}
            onClick={() => setTab("borrador")}
            badge={selCount > 0 ? selCount : null}
          />
          <TabBtn
            label="Activos"
            active={tab === "activos"}
            onClick={() => setTab("activos")}
            badge={activePlans.length}
            badgeColor={activePlans.length > 0 ? "var(--g-signal-green)" : null}
            pulse={activePlans.length > 0}
          />
        </div>

        {tab === "borrador" && (
          <BorradorPanel
            checkpoints={checkpoints}
            selected={selected}
            toggle={toggle}
            selByPriority={selByPriority}
            selCount={selCount}
            totalCritical={totalCritical}
            onExport={() => setExportOpen(true)}
            onShare={doShare}
            onExecute={startExecute}
            onNavigate={onNavigate}
            enRevision={alertStatus === "revision"}
            isUpdate={!!existingPlan}
            selectionChanged={selectionChanged}
            onDeselect={() => setSelected(new Set())}
            onArchivar={() => { if (onResolveAlert) onResolveAlert("archivada"); onNavigate("mapa"); }}
          />
        )}

        {tab === "activos" && (
          <ActivosPanel
            plans={activePlans}
            onCancel={cancelPlan}
            onFinish={finishPlan}
            onViewPlan={viewPlanOnMap}
            onCreateNew={() => setTab("borrador")}
          />
        )}
      </div>

      {/* Execute confirmation / sending flow */}
      {executeFlow && (
        <ExecuteFlowModal
          stage={executeFlow}
          plate={plate}
          checkpoints={selectedCheckpointObjects}
          unitCount={selCount * 2}
          pendingPlan={pendingPlan}
          isUpdate={!!existingPlan}
          onConfirm={confirmExecute}
          onCancel={closeExecute}
          onDone={finishExecute}
        />
      )}

      {/* Export modal */}
      {exportOpen && (
        <ExportModal
          plate={plate}
          checkpoints={selectedCheckpointObjects}
          projection={projection}
          onClose={() => setExportOpen(false)}
        />
      )}

      {/* Share toast */}
      {shareToast && (
        <div className="fade-in" style={{
          position: "absolute", bottom: 30, left: "50%", transform: "translateX(-50%)",
          padding: "12px 20px",
          background: "rgba(74, 222, 128, 0.12)",
          border: "1px solid rgba(74, 222, 128, 0.4)",
          color: "var(--g-signal-green)",
          borderRadius: "var(--g-radius-card)",
          fontSize: 13, fontWeight: 500,
          display: "flex", alignItems: "center", gap: 10,
          backdropFilter: "blur(12px)",
          zIndex: 50,
        }}>
          <window.Icon name="check-circle-2" style={{ width: 16, height: 16 }}/>
          Plan compartido al canal operativo del Quindío
        </div>
      )}
    </div>
  );
};

/* ──────────────────────────────────────────────────────────── */
/*                    PANELS (Borrador / Activos)               */
/* ──────────────────────────────────────────────────────────── */

const BorradorPanel = ({
  checkpoints, selected, toggle, selByPriority, selCount, totalCritical,
  onExport, onShare, onExecute, onNavigate, enRevision, onArchivar, isUpdate, selectionChanged, onDeselect,
}) => {
  return (
    <>
      {/* Banner de decisión forzada cuando el flujo viene de una alerta */}
      {enRevision && (
        <div style={{
          padding: "12px var(--density-pad)",
          borderBottom: "1px solid var(--g-border-on-dark)",
          background: "rgba(242, 198, 29, 0.08)",
          display: "flex", alignItems: "flex-start", gap: 10,
          flexShrink: 0,
        }}>
          <window.Icon name="alert-triangle" size={15} color="var(--g-signal-yellow)" style={{ marginTop: 1, flexShrink: 0 }}/>
          <div style={{ fontSize: 11.5, color: "var(--g-text-cream)", lineHeight: 1.5 }}>
            <strong style={{ fontWeight: 600 }}>Decisión requerida.</strong>
            <span style={{ color: "var(--g-text-mute-dark)" }}> El vehículo está en revisión. Debes <strong style={{ color: "var(--g-text-cream)", fontWeight: 600 }}>ejecutar</strong> el plan candado o <strong style={{ color: "var(--g-text-cream)", fontWeight: 600 }}>archivarlo</strong> para cerrar el flujo sin perderlo de vista.</span>
          </div>
        </div>
      )}

      {/* Summary */}
      <div style={{ padding: "16px var(--density-pad)", borderBottom: "1px solid var(--g-border-on-dark)", flexShrink: 0 }}>
        <div className="eyebrow eyebrow--accent">Resumen del plan</div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8, marginTop: 12 }}>
          <SummaryStat label="Críticos" value={selByPriority["crítica"] || 0} total={totalCritical} color="red"/>
          <SummaryStat label="Altos" value={selByPriority["alta"] || 0} total={checkpoints.filter(c => c.prioridad === "alta").length} color="yellow"/>
          <SummaryStat label="Otros" value={(selByPriority["media"] || 0) + (selByPriority["baja"] || 0)} total={checkpoints.filter(c => c.prioridad === "media" || c.prioridad === "baja").length} color="cyan"/>
        </div>
        <div style={{
          marginTop: 12,
          display: "flex", alignItems: "center", gap: 8,
          fontSize: 11, color: "var(--g-text-mute-dark)",
        }}>
          <window.Icon name="users" style={{ width: 12, height: 12 }}/>
          <span>Estimado: <strong style={{ color: "var(--g-text-cream)" }}>{selCount * 2} unidades</strong> · cobertura corredores Este + Sur</span>
        </div>
      </div>

      {/* Checkpoints list */}
      <div className="scroll" style={{ flex: 1, minHeight: 0, overflowY: "auto" }}>
        {checkpoints.filter(cp => cp.tipo !== "puesto-control").map(cp => (
          <CheckpointRow
            key={cp.id}
            cp={cp}
            selected={selected.has(cp.id)}
            onToggle={() => toggle(cp.id)}
          />
        ))}
        {checkpoints.some(cp => cp.tipo === "puesto-control") && (
          <>
            <div style={{
              display: "flex", alignItems: "center", gap: 8,
              padding: "12px var(--density-pad) 8px",
              borderTop: "1px solid var(--g-border-on-dark)",
              marginTop: 4,
            }}>
              <window.Icon name="shield" size={13} color="var(--g-signal-yellow)"/>
              <span style={{ fontSize: 10, letterSpacing: 1.3, textTransform: "uppercase", fontWeight: 600, color: "var(--g-signal-yellow)" }}>
                Puestos de control fijos
              </span>
              <span style={{ marginLeft: "auto", fontSize: 10, color: "var(--g-text-mute-dark)" }}>
                ya en terreno
              </span>
            </div>
            {checkpoints.filter(cp => cp.tipo === "puesto-control").map(cp => (
              <CheckpointRow
                key={cp.id}
                cp={cp}
                selected={selected.has(cp.id)}
                onToggle={() => toggle(cp.id)}
              />
            ))}
          </>
        )}
      </div>

      {/* Actions */}
      <div style={{
        padding: "var(--density-pad)",
        borderTop: "1px solid var(--g-border-on-dark)",
        display: "grid", gap: 8,
        flexShrink: 0,
      }}>
        <button
          className="btn btn--primary"
          style={{ justifyContent: "center", padding: "13px",
            background: (selCount > 0 && (!isUpdate || selectionChanged)) ? (isUpdate ? "var(--g-signal-yellow)" : "var(--g-signal-red)") : undefined,
            color: (selCount > 0 && (!isUpdate || selectionChanged)) ? (isUpdate ? "#1a1505" : "#fff") : undefined,
            opacity: (selCount === 0 || (isUpdate && !selectionChanged)) ? 0.45 : 1,
            cursor: (selCount === 0 || (isUpdate && !selectionChanged)) ? "default" : "pointer" }}
          disabled={selCount === 0 || (isUpdate && !selectionChanged)}
          onClick={onExecute}
        >
          <window.Icon name={isUpdate ? "refresh-cw" : "siren"} color={(selCount > 0 && isUpdate && selectionChanged) ? "#1a1505" : undefined}/>
          {isUpdate
            ? (selectionChanged ? `Actualizar plan · ${selCount} ${selCount === 1 ? "punto" : "puntos"}` : "Sin cambios en el plan")
            : `Ejecutar candado · ${selCount} ${selCount === 1 ? "punto" : "puntos"}`}
          <window.Icon name="arrow-right" style={{ marginLeft: "auto" }} color={(selCount > 0 && isUpdate && selectionChanged) ? "#1a1505" : undefined}/>
        </button>
        {enRevision ? (
          <button className="btn" style={{ justifyContent: "center", padding: "11px" }} onClick={onArchivar}>
            <window.Icon name="archive"/> Archivar · no ejecutar
          </button>
        ) : (
          <button className="btn" style={{ justifyContent: "center", padding: "11px" }} onClick={() => onNavigate("rebote")}>
            <window.Icon name="arrow-left"/> Volver a Inferencia
          </button>
        )}
        {selCount > 0 && (
          <button className="btn btn--ghost" style={{ justifyContent: "center", padding: "10px" }} onClick={onDeselect}>
            <window.Icon name="x"/> Cerrar
          </button>
        )}
      </div>
    </>
  );
};

const ActivosPanel = ({ plans, onCancel, onCreateNew, onFinish, onViewPlan }) => {
  if (plans.length === 0) {
    return (
      <div style={{ flex: 1, display: "grid", placeItems: "center", padding: 40, textAlign: "center", minHeight: 0 }}>
        <div style={{ maxWidth: 280 }}>
          <window.Icon name="shield-off" style={{ width: 32, height: 32, color: "var(--g-text-mute-dark)" }}/>
          <h3 className="ds-h3" style={{ marginTop: 16, fontSize: 18, color: "var(--g-text-cream)" }}>
            Sin planes activos
          </h3>
          <p style={{ marginTop: 8, fontSize: 12, color: "var(--g-text-mute-dark)", lineHeight: 1.5 }}>
            Los planes que ejecutes aparecerán aquí. Podrás monitorearlos y cancelarlos.
          </p>
        </div>
      </div>
    );
  }
  return (
    <>
      <div className="scroll" style={{ flex: 1, minHeight: 0, overflowY: "auto", padding: "12px var(--density-pad)" }}>
        {plans.map(p => (
          <ActivePlanCard key={p.id} plan={p} onCancel={() => onCancel(p.id)} onFinish={(reason) => onFinish(p.id, reason)} onViewPlan={() => onViewPlan && onViewPlan(p)}/>
        ))}
      </div>
    </>
  );
};

const ActivePlanCard = ({ plan, onCancel, onFinish, onViewPlan }) => {
  const [confirming, setConfirming] = React.useState(false);
  const [expanded, setExpanded] = React.useState(false);
  const [mode, setMode] = React.useState(null);        // null | "cancel" | "finish"
  const [finishReason, setFinishReason] = React.useState(null); // "localizado" | "tiempo"
  const [finishSending, setFinishSending] = React.useState(false);

  // Cierre de cierre — al notificar, anima el envío y luego retira el plan.
  const cierreChannels = React.useMemo(() => plan.channels.map(c => ({ ...c, status: "pending" })), [plan]);
  const doNotifyClose = () => {
    setFinishSending(true);
    setTimeout(() => onFinish(finishReason), 3600);
  };

  const FINISH_MSG = {
    localizado: "Vehículo localizado · cierre del operativo. Repliegue de unidades de los puntos de control.",
    tiempo: "Tiempo estimado de fuga excedido · cierre del operativo. El vehículo pudo salir del área de cobertura. Repliegue de unidades.",
  };

  return (
    <div className="fade-in" style={{
      marginBottom: 12,
      background: "rgba(74, 222, 128, 0.04)",
      border: "1px solid rgba(74, 222, 128, 0.28)",
      borderRadius: "var(--g-radius-card)",
      overflow: "hidden",
    }}>
      {/* Header — toda la fila es seleccionable */}
      <button onClick={() => setExpanded(v => !v)} style={{
        width: "100%", textAlign: "left",
        padding: "12px 14px",
        display: "flex", alignItems: "center", gap: 10,
        borderBottom: expanded ? "1px solid var(--g-border-on-dark)" : "none",
        background: "transparent", border: 0, cursor: "pointer",
        fontFamily: "var(--font-sans)",
      }}>
        <div style={{
          width: 8, height: 8, borderRadius: "50%",
          background: "var(--g-signal-green)",
          boxShadow: "0 0 8px var(--g-signal-green)",
          animation: "alertPulse 1.6s ease-in-out infinite",
          flexShrink: 0,
        }}/>
        {(() => {
          const pl = window.SONAR_findPlate(plan.placa);
          const cap = pl && pl.captura;
          return cap ? (
            <img src={cap} alt="" style={{
              width: 76, height: 52, flexShrink: 0, borderRadius: 7, objectFit: "cover",
              border: "1px solid var(--g-border-on-dark)",
            }}/>
          ) : (
            <div style={{
              width: 76, height: 52, flexShrink: 0, borderRadius: 7,
              border: "1px dashed var(--g-border-on-dark)", background: "rgba(127,134,142,0.05)",
              display: "grid", placeItems: "center", color: "var(--g-text-mute-dark)",
            }}>
              <window.Icon name="image" size={16}/>
            </div>
          );
        })()}
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 2 }}>
            <span style={{ fontSize: 10, letterSpacing: 1.4, color: "var(--g-signal-green)", fontWeight: 500 }}>{plan.id}</span>
            <span style={{ fontSize: 9, letterSpacing: 1.2, color: "var(--g-text-mute-dark)" }}>· EN EJECUCIÓN</span>
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span className="plate plate--sm">{plan.placa}</span>
            <span style={{ fontSize: 11, color: "var(--g-text-mute-dark)", fontVariantNumeric: "tabular-nums" }}>
              hace {plan.activatedAgo} min · {plan.checkpoints.length} pts · {plan.unitCount} und.
            </span>
          </div>
        </div>
        <window.Icon name={expanded ? "chevron-up" : "chevron-down"} size={16} color="var(--g-text-mute-dark)"/>
      </button>

      {expanded && (
        <div className="fade-in">
        {/* Quick stats */}
        <div style={{
          display: "grid",
          gridTemplateColumns: "1fr 1fr 1fr",
          gap: 0,
          background: "rgba(7, 9, 12, 0.35)",
        }}>
          <QuickStat label="Puntos" value={plan.checkpoints.length}/>
          <QuickStat label="Unidades" value={plan.unitCount}/>
          <QuickStat label="Canales" value={`${plan.channels.filter(c => c.status === "read" || c.status === "delivered").length}/${plan.channels.length}`}/>
        </div>

        <div style={{ padding: "12px 14px", borderTop: "1px solid var(--g-border-on-dark)" }}>
          {/* Motivo */}
          <div style={{ fontSize: 11, color: "var(--g-text-mute-dark)", marginBottom: 12, lineHeight: 1.4 }}>
            <window.Icon name="alert-octagon" size={11} style={{ verticalAlign: "middle", marginRight: 6, color: "var(--g-signal-red-soft)" }}/>
            {plan.motivo}
          </div>

          {/* Checkpoints */}
          <div className="eyebrow" style={{ marginBottom: 6 }}>Puntos activos</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 4, marginBottom: 14 }}>
            {plan.checkpoints.map(cp => (
              <div key={cp.id} style={{
                display: "flex", alignItems: "center", gap: 8,
                fontSize: 11, color: "var(--g-text-cream)",
                padding: "4px 0",
              }}>
                <div style={{
                  width: 6, height: 6, borderRadius: "50%",
                  background: cp.prioridad === "crítica" ? "var(--g-signal-red)" :
                              cp.prioridad === "alta"    ? "var(--g-signal-yellow)" :
                                                           "var(--accent, var(--g-celadon))",
                }}/>
                <span style={{ flex: 1, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{cp.nombre}</span>
                <span style={{ fontSize: 9, letterSpacing: 1.2, color: "var(--g-text-mute-dark)", textTransform: "uppercase" }}>{cp.prioridad}</span>
              </div>
            ))}
          </div>

          {/* Alert log */}
          <div className="eyebrow" style={{ marginBottom: 6 }}>Notificaciones · activación {plan.activatedAt}</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 4, marginBottom: 14 }}>
            {plan.channels.map((ch, i) => (
              <ChannelRow key={i} channel={ch}/>
            ))}
          </div>

          {/* Acciones */}
          {mode === "finish" ? (
            <div style={{
              padding: 12,
              background: "var(--g-surface-on-dark)",
              border: "1px solid var(--g-border-on-dark)",
              borderRadius: "var(--g-radius-cta)",
            }}>
              {finishSending ? (
                <>
                  <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 10 }}>
                    <window.Icon name="send" size={14} color="var(--accent, var(--g-celadon))"/>
                    <span style={{ fontSize: 12, color: "var(--g-text-cream)", fontWeight: 500 }}>
                      Notificando cierre a las unidades…
                    </span>
                  </div>
                  <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
                    {cierreChannels.map((c, i) => (
                      <SendingRow key={i} channel={c} delay={i * 450}/>
                    ))}
                  </div>
                </>
              ) : (
                <>
                  <div style={{ fontSize: 12, color: "var(--g-text-cream)", marginBottom: 10, fontWeight: 500 }}>
                    Finalizar plan {plan.id}
                  </div>
                  <div style={{ fontSize: 11, color: "var(--g-text-mute-dark)", marginBottom: 10 }}>
                    Motivo del cierre — se notifica a las unidades por WhatsApp y SMS:
                  </div>
                  <div style={{ display: "flex", flexDirection: "column", gap: 6, marginBottom: 10 }}>
                    <FinishReasonBtn
                      active={finishReason === "localizado"} icon="check-circle-2"
                      label="Vehículo localizado" onClick={() => setFinishReason("localizado")}
                      accent="var(--g-celadon)" accentSoft="rgba(79, 212, 255, 0.12)"/>
                    <FinishReasonBtn
                      active={finishReason === "tiempo"} icon="clock"
                      label="Tiempo de fuga excedido" onClick={() => setFinishReason("tiempo")}
                      accent="var(--g-signal-orange)" accentSoft="rgba(229, 130, 40, 0.14)"/>
                  </div>
                  {finishReason && (
                    <div className="fade-in" style={{
                      fontSize: 11, color: "var(--g-text-mute-dark)", lineHeight: 1.45,
                      padding: "8px 10px", marginBottom: 10,
                      background: "var(--g-surface-on-dark)", borderRadius: 8,
                      borderLeft: `2px solid ${finishReason === "localizado" ? "var(--g-celadon)" : "var(--g-signal-orange)"}`,
                    }}>
                      <window.Icon name="message-circle" size={11} style={{ verticalAlign: "middle", marginRight: 5, color: "var(--g-signal-whatsapp)" }}/>
                      {FINISH_MSG[finishReason]}
                    </div>
                  )}
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6 }}>
                    <button className="btn" onClick={() => { setMode(null); setFinishReason(null); }} style={{ justifyContent: "center", padding: "8px", fontSize: 11 }}>
                      Volver
                    </button>
                    <button onClick={doNotifyClose} disabled={!finishReason} style={{
                      padding: "8px",
                      background: finishReason ? "var(--g-celadon)" : "var(--g-surface-on-dark)",
                      color: finishReason ? "#04212b" : "var(--g-text-mute-dark)",
                      border: 0, borderRadius: "var(--g-radius-cta)",
                      fontFamily: "var(--font-sans)", fontSize: 11, fontWeight: 600, letterSpacing: 0.3,
                      cursor: finishReason ? "pointer" : "not-allowed",
                      display: "flex", alignItems: "center", justifyContent: "center", gap: 6,
                    }}>
                      <window.Icon name="send" size={12} color={finishReason ? "#04212b" : undefined}/> Notificar cierre
                    </button>
                  </div>
                </>
              )}
            </div>
          ) : mode === "cancel" ? (
            <div style={{
              padding: 12,
              background: "rgba(229, 51, 63, 0.08)",
              border: "1px solid rgba(229, 51, 63, 0.35)",
              borderRadius: "var(--g-radius-cta)",
            }}>
              <div style={{ fontSize: 12, color: "var(--g-text-cream)", marginBottom: 10, lineHeight: 1.5 }}>
                ¿Cancelar plan candado <strong>{plan.id}</strong>? Se notificará a las unidades el repliegue.
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6 }}>
                <button className="btn" onClick={() => setMode(null)} style={{ justifyContent: "center", padding: "8px", fontSize: 11 }}>
                  Mantener
                </button>
                <button onClick={onCancel} style={{
                  padding: "8px",
                  background: "var(--g-signal-red)",
                  color: "#fff",
                  border: 0,
                  borderRadius: "var(--g-radius-cta)",
                  fontFamily: "var(--font-sans)",
                  fontSize: 11, fontWeight: 500,
                  letterSpacing: 0.3,
                  cursor: "pointer",
                  display: "flex", alignItems: "center", justifyContent: "center", gap: 6,
                }}>
                  <window.Icon name="x-octagon" size={12}/> Confirmar cancelación
                </button>
              </div>
            </div>
          ) : (
            <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              <button
                onClick={onViewPlan}
                className="btn"
                style={{
                  width: "100%", justifyContent: "center", padding: "10px 12px",
                  borderColor: "rgba(79,212,255,0.4)", color: "var(--g-celadon)",
                }}>
                <window.Icon name="map" size={15} color="var(--g-celadon)"/> Ver en el mapa
              </button>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
                <button
                  onClick={() => { setMode("finish"); setFinishReason(null); }}
                  style={{
                    padding: "10px 12px",
                    background: "var(--g-signal-green)",
                    border: 0, color: "#04150b",
                    borderRadius: "var(--g-radius-cta)",
                    fontFamily: "var(--font-sans)",
                    fontSize: 12, fontWeight: 700, letterSpacing: 0.2,
                    cursor: "pointer",
                    display: "flex", alignItems: "center", justifyContent: "center", gap: 7,
                  }}>
                  <window.Icon name="flag" size={14} color="#04150b"/> Finalizar
                </button>
                <button
                  onClick={() => setMode("cancel")}
                  style={{
                    padding: "10px 12px",
                    background: "transparent",
                    border: "1px solid rgba(229, 51, 63, 0.45)",
                    color: "var(--g-signal-red-soft)",
                    borderRadius: "var(--g-radius-cta)",
                    fontFamily: "var(--font-sans)",
                    fontSize: 12, fontWeight: 500, letterSpacing: 0.2,
                    cursor: "pointer",
                    display: "flex", alignItems: "center", justifyContent: "center", gap: 7,
                    transition: "all 160ms",
                  }}
                  onMouseEnter={e => e.currentTarget.style.background = "rgba(229, 51, 63, 0.08)"}
                  onMouseLeave={e => e.currentTarget.style.background = "transparent"}
                >
                  <window.Icon name="x-octagon" size={14} color="var(--g-signal-red-soft)"/> Cancelar
                </button>
              </div>
            </div>
          )}
        </div>
        </div>
      )}
    </div>
  );
};

const FinishReasonBtn = ({ active, icon, label, onClick, accent = "var(--g-celadon)", accentSoft = "rgba(79, 212, 255, 0.12)" }) => (
  <button onClick={onClick} style={{
    display: "flex", alignItems: "center", gap: 8,
    padding: "9px 11px",
    background: active ? accentSoft : "var(--g-surface-on-dark)",
    border: `1px solid ${active ? accent : "var(--g-border-on-dark)"}`,
    borderRadius: 8,
    color: active ? "var(--g-text-cream)" : "var(--g-text-mute-dark)",
    fontFamily: "var(--font-sans)", fontSize: 12, fontWeight: 500,
    cursor: "pointer", textAlign: "left", transition: "all 140ms",
  }}>
    <window.Icon name={icon} size={14} color={active ? accent : "var(--g-text-mute-dark)"}/>
    <span style={{ flex: 1 }}>{label}</span>
    {active && <window.Icon name="check" size={13} color={accent}/>}
  </button>
);

const ChannelRow = ({ channel }) => {
  const isWA = channel.type === "whatsapp";
  const statusColor =
    channel.status === "read"      ? "var(--g-signal-green)" :
    channel.status === "delivered" ? "var(--accent, var(--g-celadon))" :
    channel.status === "pending"   ? "var(--g-signal-yellow)" :
                                     "var(--g-signal-red-soft)";
  const statusLabel =
    channel.status === "read"      ? "Leído" :
    channel.status === "delivered" ? "Entregado" :
    channel.status === "pending"   ? "Enviando…" :
                                     "Falló";
  return (
    <div style={{
      display: "grid",
      gridTemplateColumns: "auto 1fr auto auto",
      gap: 8,
      alignItems: "center",
      fontSize: 11,
      padding: "5px 0",
    }}>
      <div style={{
        width: 18, height: 18, borderRadius: "50%",
        display: "grid", placeItems: "center",
        background: isWA ? "rgba(37, 211, 102, 0.16)" : "rgba(79, 212, 255, 0.12)",
        color: isWA ? "var(--g-signal-whatsapp)" : "var(--accent, var(--g-celadon))",
        flexShrink: 0,
      }}>
        <window.Icon name={isWA ? "message-circle" : "smartphone"} size={11}/>
      </div>
      <div style={{ minWidth: 0, color: "var(--g-text-cream)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
        {channel.target}
      </div>
      <div style={{ fontSize: 9, color: statusColor, letterSpacing: 1.2, fontWeight: 500, textTransform: "uppercase" }}>
        {statusLabel}
      </div>
      <div style={{ fontSize: 10, color: "var(--g-text-mute-dark)", fontVariantNumeric: "tabular-nums" }}>
        {channel.ts}
      </div>
    </div>
  );
};

const QuickStat = ({ label, value }) => (
  <div style={{
    padding: "10px 12px",
    borderRight: "1px solid var(--g-border-on-dark)",
    textAlign: "center",
  }}>
    <div style={{ fontSize: 9, letterSpacing: 1.4, color: "var(--g-text-mute-dark)", textTransform: "uppercase" }}>
      {label}
    </div>
    <div style={{
      fontSize: 16, fontWeight: 500, marginTop: 4,
      color: "var(--g-text-cream)",
      fontVariantNumeric: "tabular-nums",
      letterSpacing: -0.3,
    }}>{value}</div>
  </div>
);

const TabBtn = ({ label, active, onClick, badge, badgeColor, pulse }) => (
  <button onClick={onClick} style={{
    flex: 1,
    padding: "13px 16px",
    background: active ? "rgba(79, 212, 255, 0.06)" : "transparent",
    border: 0,
    borderBottom: active ? "2px solid var(--accent, var(--g-celadon))" : "2px solid transparent",
    color: active ? "var(--g-text-cream)" : "var(--g-text-mute-dark)",
    fontFamily: "var(--font-sans)",
    fontSize: 12, fontWeight: 500,
    letterSpacing: 0.6,
    textTransform: "uppercase",
    cursor: "pointer",
    display: "flex", alignItems: "center", justifyContent: "center", gap: 8,
    transition: "all 160ms",
    position: "relative",
  }}>
    {label}
    {badge != null && (
      <span style={{
        padding: "1px 7px",
        borderRadius: "var(--g-radius-pill)",
        background: badgeColor || "rgba(79, 212, 255, 0.15)",
        color: badgeColor ? "#0B0F14" : "var(--g-text-cream)",
        fontSize: 10,
        fontWeight: 600,
        letterSpacing: 0,
        minWidth: 18,
        textAlign: "center",
        boxShadow: pulse && badgeColor ? `0 0 8px ${badgeColor}` : "none",
      }}>{badge}</span>
    )}
  </button>
);

/* ──────────────────────────────────────────────────────────── */
/*                       EXECUTE FLOW MODAL                     */
/* ──────────────────────────────────────────────────────────── */

const ExecuteFlowModal = ({ stage, plate, checkpoints, unitCount, pendingPlan, isUpdate, onConfirm, onCancel, onDone }) => {
  return (
    <div style={{
      position: "absolute", inset: 0, zIndex: 100,
      background: "rgba(0, 0, 0, 0.6)",
      backdropFilter: "blur(6px)",
      display: "grid", placeItems: "center",
    }} onClick={stage === "confirming" ? onCancel : undefined}>
      <div onClick={e => e.stopPropagation()} style={{
        background: "var(--s-panel)",
        border: "1px solid var(--g-border-on-dark)",
        borderRadius: "var(--g-radius-card)",
        padding: 28,
        width: 520, maxWidth: "92%",
        maxHeight: "88vh", overflowY: "auto",
        boxShadow: "var(--g-shadow-alert)",
      }}>

        {stage === "confirming" && (
          <>
            <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 16 }}>
              <div style={{
                width: 44, height: 44, borderRadius: "50%",
                background: isUpdate ? "rgba(242, 198, 29, 0.15)" : "rgba(229, 51, 63, 0.15)",
                display: "grid", placeItems: "center",
              }}>
                <window.Icon name={isUpdate ? "refresh-cw" : "siren"} style={{ width: 22, height: 22, color: isUpdate ? "var(--g-signal-yellow)" : "var(--g-signal-red)" }}/>
              </div>
              <div>
                <div className="eyebrow eyebrow--accent">{isUpdate ? "Actualizar plan candado" : "Activar plan candado"}</div>
                <h3 style={{ fontSize: 20, fontWeight: 500, color: "var(--g-text-cream)", letterSpacing: -0.3, marginTop: 2 }}>
                  {isUpdate ? "Confirmar actualización" : "Confirmar ejecución"}
                </h3>
              </div>
            </div>

            <div style={{ fontSize: 13, color: "var(--g-text-mute-dark)", lineHeight: 1.55, marginBottom: 18 }}>
              {isUpdate
                ? <>Se reenviará el plan <strong style={{ color: "var(--g-text-cream)" }}>actualizado</strong> a las unidades por <strong style={{ color: "var(--g-signal-whatsapp)" }}>WhatsApp</strong> y <strong style={{ color: "var(--accent, var(--g-celadon))" }}>SMS al PDA</strong>, con los nuevos puntos de control. No se crea un plan nuevo.</>
                : <>Al confirmar se enviarán alertas operacionales por <strong style={{ color: "var(--g-signal-whatsapp)" }}>WhatsApp</strong> a las comandancias y por <strong style={{ color: "var(--accent, var(--g-celadon))" }}>SMS al PDA</strong> de las patrullas asignadas. El plan quedará activo hasta su cancelación manual.</>}
            </div>

            <div style={{
              padding: 14,
              background: "var(--g-surface-on-dark)",
              border: "1px solid var(--g-border-on-dark)",
              borderRadius: "var(--g-radius-card)",
              marginBottom: 18,
            }}>
              <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 8 }}>
                <span className="plate plate--sm">{plate.placa}</span>
                {plate.marcaciones.length > 0 && (
                  <span className="badge badge--alert">{plate.marcaciones[0].tipo}</span>
                )}
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 12 }}>
                <Mini label="Puntos" value={checkpoints.length}/>
                <Mini label="Unidades" value={unitCount}/>
                <Mini label="Canales" value="5"/>
              </div>
            </div>

            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
              <button className="btn" onClick={onCancel} style={{ justifyContent: "center", padding: "12px" }}>
                Cancelar
              </button>
              <button onClick={onConfirm} style={{
                padding: "12px",
                background: "var(--g-signal-red)",
                color: "#fff",
                border: 0,
                borderRadius: "var(--g-radius-cta)",
                fontFamily: "var(--font-sans)",
                fontSize: 13, fontWeight: 500, letterSpacing: 0.4,
                cursor: "pointer",
                display: "flex", alignItems: "center", justifyContent: "center", gap: 8,
              }}>
                <window.Icon name={isUpdate ? "refresh-cw" : "siren"} size={14}/> {isUpdate ? "Confirmar y reenviar" : "Confirmar y notificar"}
              </button>
            </div>
          </>
        )}

        {(stage === "sending" || stage === "done") && pendingPlan && (
          <>
            <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 14 }}>
              <div style={{
                width: 44, height: 44, borderRadius: "50%",
                background: stage === "done" ? "rgba(74, 222, 128, 0.16)" : "rgba(79, 212, 255, 0.15)",
                display: "grid", placeItems: "center",
                transition: "background 300ms",
              }}>
                <window.Icon name={stage === "done" ? "check-circle-2" : "send"}
                  style={{ width: stage === "done" ? 22 : 20, height: stage === "done" ? 22 : 20,
                    color: stage === "done" ? "var(--g-signal-green)" : "var(--accent, var(--g-celadon))" }}/>
              </div>
              <div>
                <div className="eyebrow eyebrow--accent" style={stage === "done" ? { color: "var(--g-signal-green)" } : null}>
                  {stage === "done" ? "Plan activo" : "Notificando comandos"}
                </div>
                <h3 style={{ fontSize: 20, fontWeight: 500, color: "var(--g-text-cream)", letterSpacing: -0.3, marginTop: 2 }}>
                  {stage === "done" ? `${pendingPlan.id} ${pendingPlan.isUpdate ? "actualizado" : "en ejecución"}` : (pendingPlan.isUpdate ? "Reenviando alertas…" : "Enviando alertas…")}
                </h3>
              </div>
            </div>
            <div style={{ fontSize: 12, color: "var(--g-text-mute-dark)", marginBottom: 16, lineHeight: 1.5 }}>
              WhatsApp a comandancias · SMS al PDA de patrullas
            </div>

            <div style={{
              padding: 14,
              background: "var(--g-surface-on-dark)",
              border: "1px solid var(--g-border-on-dark)",
              borderRadius: "var(--g-radius-card)",
              display: "flex", flexDirection: "column", gap: 6,
            }}>
              {pendingPlan.channels.map((c, i) => (
                <SendingRow key={i} channel={c} delay={i * 500}/>
              ))}
            </div>

            {/* Resumen "en ejecución" — aparece bajo los envíos al completar */}
            {stage === "done" && (
              <div className="fade-in" style={{ marginTop: 16 }}>
                <div style={{
                  display: "flex", alignItems: "flex-start", gap: 10,
                  padding: "12px 14px",
                  background: "rgba(74, 222, 128, 0.08)",
                  border: "1px solid rgba(74, 222, 128, 0.3)",
                  borderRadius: "var(--g-radius-card)",
                  marginBottom: 14,
                }}>
                  <window.Icon name="shield-check" size={16} color="var(--g-signal-green)" style={{ marginTop: 1, flexShrink: 0 }}/>
                  <div style={{ fontSize: 12.5, color: "var(--g-text-mute-dark)", lineHeight: 1.5 }}>
                    <strong style={{ color: "var(--g-text-cream)" }}>{pendingPlan.channels.length} notificaciones entregadas.</strong> Las unidades ya están en ruta a sus <strong style={{ color: "var(--g-text-cream)" }}>{pendingPlan.checkpoints.length} puntos</strong> asignados. Monitorea o cancela el plan en la pestaña Activos.
                  </div>
                </div>
                <button onClick={onDone} className="btn btn--primary" style={{
                  width: "100%", justifyContent: "center", padding: "13px",
                }}>
                  <window.Icon name="arrow-right"/> Ir a planes activos
                </button>
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
};

const SendingRow = ({ channel, delay }) => {
  const [phase, setPhase] = React.useState("pending"); // pending → delivered
  React.useEffect(() => {
    const id = setTimeout(() => setPhase("delivered"), delay + 1200);
    return () => clearTimeout(id);
  }, [delay]);
  const isWA = channel.type === "whatsapp";
  const c = phase === "pending" ? "var(--g-signal-yellow)" : (isWA ? "var(--g-signal-whatsapp)" : "var(--accent, var(--g-celadon))");
  return (
    <div style={{
      display: "grid",
      gridTemplateColumns: "auto 1fr auto",
      gap: 10, alignItems: "center",
      fontSize: 12,
      padding: "4px 0",
    }}>
      <div style={{
        width: 20, height: 20, borderRadius: "50%",
        display: "grid", placeItems: "center",
        background: isWA ? "rgba(37, 211, 102, 0.16)" : "rgba(79, 212, 255, 0.12)",
        color: isWA ? "var(--g-signal-whatsapp)" : "var(--accent, var(--g-celadon))",
      }}>
        <window.Icon name={isWA ? "message-circle" : "smartphone"} size={12}/>
      </div>
      <div style={{ color: "var(--g-text-cream)" }}>
        <span style={{ fontWeight: 500 }}>{channel.target}</span>
        <span style={{ marginLeft: 6, fontSize: 10, letterSpacing: 1.2, color: "var(--g-text-mute-dark)", textTransform: "uppercase" }}>
          · {isWA ? "WhatsApp" : "SMS PDA"}
        </span>
      </div>
      <div style={{ fontSize: 10, letterSpacing: 1.2, color: c, fontWeight: 500, textTransform: "uppercase", display: "flex", alignItems: "center", gap: 4 }}>
        {phase === "pending" ? (
          <>
            <window.Icon name="loader" size={11} style={{ animation: "spin 1.2s linear infinite" }}/>
            Enviando
          </>
        ) : (
          <>
            <window.Icon name="check-check" size={11}/>
            Entregado
          </>
        )}
      </div>
    </div>
  );
};

const Mini = ({ label, value }) => (
  <div>
    <div style={{ fontSize: 9, letterSpacing: 1.4, color: "var(--g-text-mute-dark)", textTransform: "uppercase" }}>
      {label}
    </div>
    <div style={{
      fontSize: 18, fontWeight: 500, marginTop: 4,
      color: "var(--g-text-cream)",
      fontVariantNumeric: "tabular-nums",
      letterSpacing: -0.3,
    }}>{value}</div>
  </div>
);

/* ──────────────────────────────────────────────────────────── */
/*                  SHARED HELPERS (existing)                   */
/* ──────────────────────────────────────────────────────────── */

const PrioLegendItem = ({ color, label }) => (
  <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
    <div style={{ position: "relative", width: 16, height: 16 }}>
      <div style={{
        position: "absolute", inset: 0, borderRadius: "50%",
        border: `1px solid ${color}`,
        borderStyle: "dashed",
      }}/>
      <div style={{
        position: "absolute", left: "50%", top: "50%",
        transform: "translate(-50%, -50%)",
        width: 4, height: 4, borderRadius: "50%",
        background: color,
      }}/>
    </div>
    <span>{label}</span>
  </div>
);

const SummaryStat = ({ label, value, total, color }) => {
  const c = color === "red"    ? "var(--g-signal-red-soft)" :
            color === "yellow" ? "var(--g-signal-yellow)" :
                                 "var(--accent, var(--g-celadon))";
  return (
    <div className="surface" style={{ padding: "10px 12px" }}>
      <div style={{ fontSize: 10, letterSpacing: 1.4, textTransform: "uppercase", color: "var(--g-text-mute-dark)" }}>
        {label}
      </div>
      <div style={{
        display: "flex", alignItems: "baseline", gap: 4, marginTop: 4,
      }}>
        <span style={{ fontSize: 22, fontWeight: 500, color: c, fontVariantNumeric: "tabular-nums", letterSpacing: -0.4 }}>
          {value}
        </span>
        <span style={{ fontSize: 12, color: "var(--g-text-mute-dark)" }}>/ {total}</span>
      </div>
    </div>
  );
};

const CheckpointRow = ({ cp, selected, onToggle }) => {
  const prioColor = cp.prioridad === "crítica" ? "var(--g-signal-red-soft)" :
                    cp.prioridad === "alta"    ? "var(--g-signal-yellow)" :
                    cp.prioridad === "media"   ? "var(--accent, var(--g-celadon))" :
                                                 "var(--g-text-mute-dark)";
  const tipoIcon = cp.tipo === "nodo-anpr"     ? "router" :
                   cp.tipo === "interseccion"  ? "git-merge" :
                   cp.tipo === "puesto-control" ? "shield" :
                                                 "alert-triangle";
  return (
    <button onClick={onToggle} style={{
      width: "100%",
      display: "block",
      background: selected ? "rgba(79, 212, 255, 0.06)" : "transparent",
      border: 0, borderTop: "1px solid var(--g-border-on-dark)",
      padding: "12px var(--density-pad)",
      color: "var(--g-text-cream)",
      textAlign: "left",
      fontFamily: "var(--font-sans)",
      cursor: "pointer",
      position: "relative",
      transition: "background 140ms",
    }}>
      {selected && <div style={{
        position: "absolute", left: 0, top: 8, bottom: 8, width: 2,
        background: "var(--accent, var(--g-celadon))",
        boxShadow: "0 0 8px var(--accent, var(--g-celadon))",
      }}/>}
      <div style={{ display: "grid", gridTemplateColumns: "22px 1fr auto", gap: 12, alignItems: "flex-start" }}>
        {/* Checkbox */}
        <div style={{
          width: 18, height: 18, borderRadius: 4,
          border: `1.5px solid ${selected ? prioColor : "var(--g-border-on-dark)"}`,
          background: selected ? prioColor : "transparent",
          display: "grid", placeItems: "center",
          marginTop: 2,
          transition: "all 160ms",
        }}>
          {selected && <window.Icon name="check" style={{ width: 12, height: 12, color: "#0B0F14", strokeWidth: 3 }}/>}
        </div>

        <div>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
            <window.Icon name={tipoIcon} style={{ width: 12, height: 12, color: prioColor }}/>
            <span style={{ fontSize: 9, letterSpacing: 1.4, color: prioColor, fontWeight: 500, textTransform: "uppercase" }}>
              {cp.prioridad}
            </span>
            <span style={{ fontSize: 9, letterSpacing: 1.4, color: "var(--g-text-mute-dark)", textTransform: "uppercase" }}>
              · {cp.tipo.replace("-", " ")}
            </span>
          </div>
          <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 4, letterSpacing: -0.1 }}>
            {cp.nombre}
          </div>
          <div style={{ fontSize: 11, color: "var(--g-text-mute-dark)", lineHeight: 1.5 }}>
            {cp.razon}
          </div>
        </div>

        <span style={{ fontSize: 9, letterSpacing: 1.4, color: "var(--g-text-mute-dark)" }}>{cp.id}</span>
      </div>
    </button>
  );
};

const ExportModal = ({ plate, checkpoints, projection, onClose }) => {
  const [format, setFormat] = React.useState("pdf");
  const [done, setDone] = React.useState(false);

  const doExport = () => {
    setDone(true);
    setTimeout(() => { setDone(false); onClose(); }, 1600);
  };

  return (
    <div style={{
      position: "absolute", inset: 0, zIndex: 100,
      background: "rgba(0, 0, 0, 0.55)",
      backdropFilter: "blur(4px)",
      display: "grid", placeItems: "center",
    }} onClick={onClose}>
      <div onClick={e => e.stopPropagation()} style={{
        background: "var(--s-panel)",
        border: "1px solid var(--g-border-on-dark)",
        borderRadius: "var(--g-radius-card)",
        padding: 28,
        width: 480,
        maxWidth: "90%",
        boxShadow: "var(--g-shadow-alert)",
      }}>
        <div style={{ display: "flex", alignItems: "center", marginBottom: 10 }}>
          <div className="eyebrow eyebrow--accent">Exportar plan candado</div>
          <button className="btn btn--ghost" onClick={onClose} style={{ marginLeft: "auto", padding: 4 }}>
            <window.Icon name="x"/>
          </button>
        </div>
        <h3 style={{ fontSize: 22, fontWeight: 500, color: "var(--g-text-cream)", letterSpacing: -0.3, marginBottom: 6 }}>
          Reporte · placa {plate.placa}
        </h3>
        <div style={{ fontSize: 13, color: "var(--g-text-mute-dark)", marginBottom: 18, lineHeight: 1.55 }}>
          {checkpoints.length} puntos · última captura hace ≈ {Math.round((projection.elapsed_s || 0) / 60)} min · {(projection.routes || []).length} rutas proyectadas
        </div>

        <div className="eyebrow" style={{ marginBottom: 8 }}>Formato</div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8, marginBottom: 18 }}>
          {[
            { id: "pdf", label: "PDF", icon: "file-text" },
            { id: "geojson", label: "GeoJSON", icon: "globe" },
            { id: "csv", label: "CSV", icon: "table" },
          ].map(f => (
            <button key={f.id} onClick={() => setFormat(f.id)} style={{
              padding: "12px 8px",
              background: format === f.id ? "rgba(79, 212, 255, 0.08)" : "transparent",
              border: format === f.id ? "1px solid var(--accent, var(--g-celadon))" : "1px solid var(--g-border-on-dark)",
              borderRadius: "var(--g-radius-cta)",
              color: format === f.id ? "var(--accent, var(--g-celadon))" : "var(--g-text-cream)",
              fontFamily: "var(--font-sans)",
              fontSize: 13, fontWeight: 500,
              cursor: "pointer",
              display: "flex", flexDirection: "column", alignItems: "center", gap: 6,
            }}>
              <window.Icon name={f.icon} style={{ width: 18, height: 18 }}/>
              {f.label}
            </button>
          ))}
        </div>

        <div className="eyebrow" style={{ marginBottom: 8 }}>Compartir con</div>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 24 }}>
          {["Comando Policía Quindío", "GAULA Eje Cafetero", "SIJIN Armenia", "Estación Calarcá"].map(g => (
            <span key={g} className="surface" style={{
              padding: "6px 10px", fontSize: 11, letterSpacing: 0.3,
              color: "var(--g-text-cream)",
            }}>{g}</span>
          ))}
        </div>

        <button onClick={doExport} className="btn btn--primary" style={{
          width: "100%", justifyContent: "center", padding: "14px",
          background: done ? "var(--g-signal-green)" : undefined,
        }}>
          {done ? (
            <><window.Icon name="check-circle-2"/> Reporte generado</>
          ) : (
            <><window.Icon name="file-down"/> Generar y descargar</>
          )}
        </button>
      </div>
    </div>
  );
};

window.CandadoScreen = CandadoScreen;
