// Shared components: Topbar, Tabs, Toast, Modal, Badge, ProgressBar, Icons

// --------- Tiny icon set (inline SVG) ----------
const Icon = ({ name, size = 14, color = "currentColor" }) => {
  const paths = {
    chevron: <polyline points="6 9 12 15 18 9" />,
    chevronRight: <polyline points="9 6 15 12 9 18" />,
    plus: <><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></>,
    close: <><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></>,
    target: <><circle cx="12" cy="12" r="9" /><circle cx="12" cy="12" r="3" fill="currentColor" stroke="none" /></>,
    edit: <><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" /></>,
    arrowUp: <><line x1="12" y1="19" x2="12" y2="5" /><polyline points="5 12 12 5 19 12" /></>,
    bell: <><path d="M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9" /><path d="M13.7 21a2 2 0 0 1-3.4 0" /></>,
    search: <><circle cx="11" cy="11" r="7" /><line x1="21" y1="21" x2="16.65" y2="16.65" /></>,
    settings: <><circle cx="12" cy="12" r="3" /><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" /></>,
    inProgress: <><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></>,
    check: <polyline points="20 6 9 17 4 12" />,
    pause: <><rect x="6" y="4" width="4" height="16" /><rect x="14" y="4" width="4" height="16" /></>,
    clipboard: <><path d="M9 2h6a2 2 0 0 1 2 2v2H7V4a2 2 0 0 1 2-2z" /><rect x="5" y="6" width="14" height="16" rx="2" /></>,
    layers: <><polygon points="12 2 2 7 12 12 22 7 12 2" /><polyline points="2 17 12 22 22 17" /><polyline points="2 12 12 17 22 12" /></>,
    tree: <><circle cx="6" cy="6" r="2" /><circle cx="18" cy="6" r="2" /><circle cx="12" cy="18" r="2" /><line x1="6" y1="8" x2="12" y2="16" /><line x1="18" y1="8" x2="12" y2="16" /></>,
    calendar: <><rect x="3" y="4" width="18" height="18" rx="2" /><line x1="16" y1="2" x2="16" y2="6" /><line x1="8" y1="2" x2="8" y2="6" /><line x1="3" y1="10" x2="21" y2="10" /></>,
    inbox: <><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" /><path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" /></>,
    flame: <><path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z" /></>,
    activity: <polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />,
    zap: <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />,
    sun: <><circle cx="12" cy="12" r="4.5" /><line x1="12" y1="2" x2="12" y2="4"/><line x1="12" y1="20" x2="12" y2="22"/><line x1="4.93" y1="4.93" x2="6.34" y2="6.34"/><line x1="17.66" y1="17.66" x2="19.07" y2="19.07"/><line x1="2" y1="12" x2="4" y2="12"/><line x1="20" y1="12" x2="22" y2="12"/><line x1="4.93" y1="19.07" x2="6.34" y2="17.66"/><line x1="17.66" y1="6.34" x2="19.07" y2="4.93"/></>,
    moon: <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />,
    sliders: <><line x1="4" y1="21" x2="4" y2="14"/><line x1="4" y1="10" x2="4" y2="3"/><line x1="12" y1="21" x2="12" y2="12"/><line x1="12" y1="8" x2="12" y2="3"/><line x1="20" y1="21" x2="20" y2="16"/><line x1="20" y1="12" x2="20" y2="3"/><line x1="1" y1="14" x2="7" y2="14"/><line x1="9" y1="8" x2="15" y2="8"/><line x1="17" y1="16" x2="23" y2="16"/></>,
    map: <><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6" /><line x1="8" y1="2" x2="8" y2="18" /><line x1="16" y1="6" x2="16" y2="22" /></>,
  };
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      {paths[name]}
    </svg>
  );
};

// --------- Topbar ----------
const ThemeToggle = () => {
  const [theme, setTheme] = React.useState(() => document.documentElement.dataset.theme || 'light');
  const toggle = () => {
    const next = theme === 'dark' ? 'light' : 'dark';
    document.documentElement.dataset.theme = next;
    try { localStorage.setItem('tz-theme', next); } catch(e){}
    setTheme(next);
  };
  return (
    <button className="theme-toggle" onClick={toggle} title={theme === 'dark' ? 'Cambiar a modo claro' : 'Cambiar a modo oscuro'}>
      <Icon name={theme === 'dark' ? 'sun' : 'moon'} size={16} />
    </button>
  );
};

// --------- Settings Modal ----------
const SETTINGS_DEFAULTS = {
  userName: "Ricardo García",
  userRole: "Especialista IA",
  brandTitle: "Ecosistema IA · Termiz",
  sprintLabel: "Sprint 19 · Mayo 2026",
  density: "regular",   // compact / regular / comfy
  fontSize: 12,
  accent: "#02396B",
  notifications: true,
  showLive: true,
};

const loadSettings = () => {
  try {
    const raw = localStorage.getItem("tz-settings");
    if (!raw) return { ...SETTINGS_DEFAULTS };
    return { ...SETTINGS_DEFAULTS, ...JSON.parse(raw) };
  } catch (e) { return { ...SETTINGS_DEFAULTS }; }
};
const saveSettings = (s) => {
  try { localStorage.setItem("tz-settings", JSON.stringify(s)); } catch (e) {}
};
const applySettings = (s) => {
  const r = document.documentElement;
  r.style.setProperty("--azul-info", s.accent);
  r.style.setProperty("--user-font-size", s.fontSize + "px");
  document.body.style.fontSize = s.fontSize + "px";
  r.dataset.density = s.density;
};

// ── Planner Sync section (dentro de Settings) — solo pull ─────
const PlannerSyncSection = ({ onClose }) => {
  const [log,  setLog]  = React.useState([]);
  const [busy, setBusy] = React.useState(false);
  const toast = useToast();

  const addLog = (msg) => setLog((prev) => [...prev.slice(-40), msg]);

  const handlePull = async () => {
    if (!window.Planner?.pull) { toast.push("Módulo Planner no disponible", { color: "var(--rojo-suave)" }); return; }
    if (!window.SP?.isConnected()) { toast.push("Inicia sesión primero con Microsoft", { color: "var(--ambar)" }); return; }
    if (!confirm("¿Recargar proyectos desde Microsoft Planner?\n\nSe reemplazarán los datos locales actuales.")) return;
    setBusy(true); setLog([]);
    try {
      const { projects } = await window.Planner.pull(addLog);
      window.__applyRemoteData?.(projects, window.__getInboxSnapshot?.() || []);
      toast.push(`✅ ${projects.length} proyectos cargados desde Planner`);
      onClose?.();
    } catch (e) {
      addLog("❌ " + e.message);
      toast.push("Error al cargar desde Planner", { color: "var(--rojo-suave)", icon: "close" });
    } finally { setBusy(false); }
  };

  return (
    <div className="settings-section">
      <div className="settings-section-title">Microsoft Planner</div>
      <div style={{ fontSize: 11, color: "var(--text-2)", marginBottom: 10, lineHeight: 1.5 }}>
        Importa el plan <strong>Grupo Multifuncional</strong> al dashboard.
        Cada bucket es un proyecto; los prefijos F1, F2, F3… se agrupan como epics.
      </div>
      <button
        type="button" className="btn-primary"
        onClick={handlePull} disabled={busy}
        style={{ background: "var(--azul-info)" }}
      >
        {busy ? "Importando…" : "↻ Sincronizar desde Planner"}
      </button>
      {log.length > 0 && (
        <div style={{
          marginTop: 10, padding: "8px 12px", borderRadius: 8,
          background: "var(--bg-deep)", fontSize: 10.5,
          color: "var(--text-1)", fontFamily: "var(--font-mono, monospace)",
          maxHeight: 160, overflowY: "auto", lineHeight: 1.7, whiteSpace: "pre-wrap",
        }}>
          {log.join("\n")}
        </div>
      )}
    </div>
  );
};

// ── Botón rápido de sync Planner en el Topbar ─────────────────
const PlannerSyncButton = () => {
  const [status, setStatus] = React.useState(null);
  const toast = useToast();

  React.useEffect(() => {
    const handler = (e) => setStatus(e.detail?.status ?? null);
    window.addEventListener("planner-sync-status", handler);
    return () => window.removeEventListener("planner-sync-status", handler);
  }, []);

  const handleClick = () => {
    if (!window.SP?.isConnected()) {
      toast.push("Conecta primero con Microsoft", { color: "var(--ambar)" });
      return;
    }
    window.__plannerSync?.();
  };

  const isLoading = status === "loading";
  const isOk      = status === "ok";
  const isError   = status === "error";

  return (
    <button
      className="sp-connect-btn"
      onClick={handleClick}
      disabled={isLoading}
      title={isOk ? "Planner sincronizado" : isError ? "Error al sincronizar Planner — clic para reintentar" : "Importar datos de Microsoft Planner"}
      style={{
        display: "inline-flex", alignItems: "center", gap: 6,
        padding: "4px 10px", borderRadius: 999, fontSize: 10, fontWeight: 700,
        border: "1px solid",
        borderColor: isOk    ? "rgba(74,222,128,.4)"
                   : isError ? "rgba(248,113,113,.4)"
                   :           "var(--border-default)",
        background:  isOk    ? "rgba(74,222,128,.12)"
                   : isError ? "rgba(248,113,113,.1)"
                   :           "var(--bg-panel)",
        color:       isOk    ? "#4ADE80"
                   : isError ? "var(--rojo-suave)"
                   :           "var(--text-2)",
        cursor: isLoading ? "wait" : "pointer",
        transition: "all .2s", flexShrink: 0,
      }}
    >
      {isLoading ? (
        <span style={{ width: 8, height: 8, borderRadius: "50%", border: "1.5px solid currentColor", borderTopColor: "transparent", animation: "spin .6s linear infinite", display: "inline-block" }} />
      ) : (
        <span style={{ fontSize: 11 }}>{isOk ? "✓" : isError ? "!" : "↻"}</span>
      )}
      {isLoading ? "Sincronizando…" : "Planner"}
    </button>
  );
};

const SettingsModal = ({ open, onClose, settings, setSettings }) => {
  const [draft, setDraft] = React.useState(settings);
  React.useEffect(() => { if (open) setDraft(settings); }, [open]);
  const toast = useToast();
  if (!open) return null;

  const update = (k, v) => setDraft((d) => ({ ...d, [k]: v }));
  const apply = () => {
    setSettings(draft);
    saveSettings(draft);
    applySettings(draft);
    toast.push("Configuración guardada");
    onClose();
  };
  const reset = () => {
    if (!confirm("¿Restaurar la configuración por defecto?")) return;
    setDraft({ ...SETTINGS_DEFAULTS });
  };
  const exportData = () => {
    const blob = new Blob([JSON.stringify({ settings: draft, projects: window.__getProjectsSnapshot?.() || [], inbox: window.__getInboxSnapshot?.() || [] }, null, 2)], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url; a.download = "termiz-dashboard-" + new Date().toISOString().slice(0,10) + ".json"; a.click();
    URL.revokeObjectURL(url);
    toast.push("Datos exportados");
  };
  const accents = ["#02396B", "#1E5BAF", "#2EB5A0", "#9B7FE6", "#E8A317", "#D14A4F"];

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal settings-modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div className="modal-title" style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <span style={{ width: 28, height: 28, borderRadius: 9, display: "grid", placeItems: "center", background: "rgba(63,122,201,.14)", color: "var(--azul-info)" }}>
              <Icon name="settings" size={15} />
            </span>
            Configuración
          </div>
          <button className="icon-btn" onClick={onClose}><Icon name="close" /></button>
        </div>
        <div className="modal-body" style={{ maxHeight: "70vh", overflowY: "auto" }}>
          <div className="settings-section">
            <div className="settings-section-title">Identidad</div>
            <div className="field"><label>Nombre</label><input type="text" value={draft.userName} onChange={(e) => update("userName", e.target.value)} /></div>
            <div className="field"><label>Rol</label><input type="text" value={draft.userRole} onChange={(e) => update("userRole", e.target.value)} /></div>
            <div className="field"><label>Título del proyecto</label><input type="text" value={draft.brandTitle} onChange={(e) => update("brandTitle", e.target.value)} /></div>
          </div>

          <div className="settings-section">
            <div className="settings-section-title">Sprint</div>
            <div className="field"><label>Etiqueta de sprint actual</label><input type="text" value={draft.sprintLabel} onChange={(e) => update("sprintLabel", e.target.value)} /></div>
            <div className="field"><label>Mostrar indicador LIVE</label>
              <div className="toggle-row"><Switch on={draft.showLive} onChange={(v) => update("showLive", v)} /><span className="toggle-hint">{draft.showLive ? "Visible" : "Oculto"}</span></div>
            </div>
          </div>

          <div className="settings-section">
            <div className="settings-section-title">Apariencia</div>
            <div className="field">
              <label>Color de acento</label>
              <div className="swatch-row">
                {accents.map((c) => (
                  <button key={c} type="button" className={"swatch" + (draft.accent === c ? " sel" : "")} style={{ background: c }} onClick={() => update("accent", c)} title={c} />
                ))}
              </div>
            </div>
            <div className="field">
              <label>Densidad</label>
              <div className="seg-toggle" style={{ width: "fit-content" }}>
                {["compact","regular","comfy"].map((d) => (
                  <button key={d} type="button" className={"seg-btn" + (draft.density === d ? " active" : "")} onClick={() => update("density", d)}>
                    {d === "compact" ? "Compacta" : d === "regular" ? "Regular" : "Amplia"}
                  </button>
                ))}
              </div>
            </div>
            <div className="field">
              <label>Tamaño base de fuente: <span style={{ color: "var(--text-1)", fontWeight: 700 }}>{draft.fontSize}px</span></label>
              <input type="range" min="11" max="15" step="1" value={draft.fontSize} onChange={(e) => update("fontSize", parseInt(e.target.value))} style={{ width: "100%" }} />
            </div>
          </div>

          <div className="settings-section">
            <div className="settings-section-title">Notificaciones</div>
            <div className="field">
              <label>Mostrar toasts al guardar / mover / eliminar</label>
              <div className="toggle-row"><Switch on={draft.notifications} onChange={(v) => update("notifications", v)} /><span className="toggle-hint">{draft.notifications ? "Activadas" : "Silenciadas"}</span></div>
            </div>
          </div>

          <div className="settings-section">
            <div className="settings-section-title">Datos locales</div>
            <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
              <button type="button" className="btn-secondary" onClick={exportData}>⤓ Exportar JSON</button>
              <button type="button" className="btn-secondary" onClick={reset}>↻ Restaurar por defecto</button>
            </div>
            <div style={{ fontSize: 11, color: "var(--text-2)", marginTop: 10, lineHeight: 1.5 }}>
              Exporta una copia de la configuración, proyectos e inbox para respaldo.
            </div>
          </div>

          <PlannerSyncSection onClose={onClose} />
        </div>
        <div className="modal-foot">
          <button className="btn-secondary" onClick={onClose}>Cancelar</button>
          <button className="btn-primary" onClick={apply}>Guardar cambios</button>
        </div>
      </div>
    </div>
  );
};

const Switch = ({ on, onChange }) => (
  <button type="button" className={"tz-switch" + (on ? " on" : "")} onClick={() => onChange(!on)} aria-pressed={on}>
    <span className="tz-switch-knob" />
  </button>
);

// ── Microsoft account pill ────────────────────────────────────
const MSConnectButton = () => {
  const [connected, setConnected] = React.useState(() => window.SP?.isConnected() || false);
  const [loading,   setLoading]   = React.useState(false);
  const toast = useToast();

  const handleClick = async () => {
    if (!window.SP) { toast.push("Módulo de autenticación no disponible", { color: "var(--rojo-suave)" }); return; }
    setLoading(true);
    try {
      if (connected) {
        window.SP.logout();
        setConnected(false);
        toast.push("Sesión cerrada");
      } else {
        await window.SP.login();
        setConnected(true);
        const acc = window.SP.getAccount();
        toast.push(`✅ Conectado como ${acc?.username || acc?.name || "usuario"}`);
      }
    } catch (e) {
      toast.push(`Error: ${e.message}`, { color: "var(--rojo-suave)", icon: "close" });
    } finally { setLoading(false); }
  };

  const username = window.SP?.getAccount()?.username?.split("@")[0] || "Microsoft";

  return (
    <button
      className="sp-connect-btn"
      onClick={handleClick}
      title={connected ? `Sesión activa: ${window.SP?.getAccount()?.username} — clic para cerrar sesión` : "Iniciar sesión con Microsoft 365"}
      style={{
        display: "inline-flex", alignItems: "center", gap: 6,
        padding: "4px 10px", borderRadius: 999, fontSize: 10, fontWeight: 700,
        border: "1px solid",
        borderColor: connected ? "rgba(74,222,128,.4)"  : "var(--border-default)",
        background:  connected ? "rgba(74,222,128,.12)" : "var(--bg-panel)",
        color:       connected ? "#4ADE80"              : "var(--text-2)",
        cursor: "pointer", transition: "all .2s", flexShrink: 0,
      }}
    >
      {loading
        ? <span style={{ width: 8, height: 8, borderRadius: "50%", border: "1.5px solid currentColor", borderTopColor: "transparent", animation: "spin .6s linear infinite", display: "inline-block" }} />
        : <span style={{ width: 8, height: 8, borderRadius: "50%", background: connected ? "#4ADE80" : "var(--text-3)" }} />
      }
      {connected ? username : "Iniciar sesión"}
    </button>
  );
};

const Topbar = () => {
  const [settings, setSettings] = React.useState(() => loadSettings());
  const [open, setOpen] = React.useState(false);
  const [notifOpen, setNotifOpen] = React.useState(false);
  const { history, clearHistory, unreadCount, markAsRead } = useToast();

  React.useEffect(() => { applySettings(settings); }, []);

  const toggleNotifs = () => {
    setNotifOpen(!notifOpen);
    if (!notifOpen) markAsRead();
  };

  return (
    <>
      <div className="topbar">
        <div className="logo-tz">TZ</div>
        <div className="flex-col">
          <div className="brand-title">{settings.brandTitle}</div>
          <div className="brand-sub">{settings.userName} — {settings.userRole}</div>
        </div>
        <div className="topbar-spacer" />
        <MSConnectButton />
        <PlannerSyncButton />
        <button className="icon-btn" title="Buscar"><Icon name="search" /></button>

        <div style={{ position: "relative" }}>
          <button className="icon-btn" title="Notificaciones" onClick={toggleNotifs}>
            <Icon name="bell" />
            {unreadCount > 0 && <span className="notif-badge">{unreadCount}</span>}
          </button>
          {notifOpen && (
            <NotificationPanel history={history} onClear={clearHistory} onClose={() => setNotifOpen(false)} />
          )}
        </div>

        <ThemeToggle />
        <button className="icon-btn" title="Ajustes" onClick={() => setOpen(true)}><Icon name="settings" /></button>
        <div className="sprint-pill">
          <Icon name="zap" size={11} /> {settings.sprintLabel}
        </div>
        {settings.showLive && <div className="live-dot">LIVE</div>}
      </div>
      <SettingsModal open={open} onClose={() => setOpen(false)} settings={settings} setSettings={setSettings} />
    </>
  );
};

const NotificationPanel = ({ history, onClear, onClose }) => {
  React.useEffect(() => {
    const handleKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", handleKey);
    return () => window.removeEventListener("keydown", handleKey);
  }, [onClose]);

  return (
    <div className="notif-panel">
      <div className="np-head">
        <div className="np-title">Notificaciones</div>
        <button className="np-clear" onClick={onClear}>Limpiar</button>
      </div>
      <div className="np-body">
        {history.length === 0 ? (
          <div className="np-empty">No hay notificaciones recientes</div>
        ) : (
          history.map((n, i) => (
            <div key={n.id} className="np-item" style={{ "--notif-color": n.color }}>
              <div className="np-icon"><Icon name={n.icon} size={11} /></div>
              <div className="np-content">
                <div className="np-msg">{n.msg}</div>
                <div className="np-time">{n.time}</div>
              </div>
            </div>
          ))
        )}
      </div>
    </div>
  );
};

// --------- Tabs ----------
const Tabs = ({ active, onChange, counts }) => {
  const items = [
    { key: "overview", label: "Overview",  icon: "activity",   count: null },
    { key: "tree",     label: "Árbol de Proyectos", icon: "tree", count: counts.projects },
    { key: "gantt",    label: "Gantt",      icon: "calendar",  count: null },
    { key: "roadmap",  label: "Roadmap",    icon: "map",       count: null },
    { key: "inbox",    label: "Inbox",      icon: "inbox",     count: counts.inbox },
  ];
  return (
    <div className="tabs">
      {items.map((t) => (
        <button
          key={t.key}
          className={"tab " + (active === t.key ? "active" : "")}
          onClick={() => onChange(t.key)}
        >
          <Icon name={t.icon} size={13} />
          <span>{t.label}</span>
          {t.count != null && <span className="count">{t.count}</span>}
        </button>
      ))}
    </div>
  );
};

// --------- Badge ----------
const StatusBadge = ({ status, onClick, selected }) => {
  const cfg = window.STATUS_OPTIONS.find((s) => s.key === status) || window.STATUS_OPTIONS[3];
  return (
    <span
      className={"badge " + cfg.className + (selected ? " selected" : "")}
      onClick={onClick}
      style={onClick ? { cursor: "pointer" } : null}
    >
      {cfg.label}
    </span>
  );
};

const TipoTag = ({ tipo }) => {
  const cfg = window.TIPO_OPTIONS.find((t) => t.key === tipo) || window.TIPO_OPTIONS[1];
  return <span className={"tag " + cfg.className}>{cfg.label}</span>;
};

// --------- Toast system ----------
const ToastContext = React.createContext({ push: () => {}, history: [], clearHistory: () => {}, unreadCount: 0, markAsRead: () => {} });

const ToastProvider = ({ children }) => {
  const [toasts, setToasts] = React.useState([]);
  const [history, setHistory] = React.useState([]);
  const [unreadCount, setUnreadCount] = React.useState(0);
  const lastPush = React.useRef({ msg: "", time: 0 });

  const push = React.useCallback((msg, opts = {}) => {
    // Duplicate prevention: ignore same message if pushed within 500ms
    const now = Date.now();
    if (msg === lastPush.current.msg && (now - lastPush.current.time) < 500) return;
    lastPush.current = { msg, time: now };

    const id = Math.random().toString(36).slice(2);
    const color = opts.color || "var(--azul-info)";
    const icon = opts.icon || "check";
    const time = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
    
    const newNotif = { id, msg, color, icon, time };
    setToasts((t) => [...t, newNotif]);
    setHistory((h) => [newNotif, ...h].slice(0, 50));
    setUnreadCount((c) => c + 1);
    
    setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 2400);
  }, []);

  const clearHistory = () => { setHistory([]); setUnreadCount(0); };
  const markAsRead = () => setUnreadCount(0);

  return (
    <ToastContext.Provider value={{ push, history, clearHistory, unreadCount, markAsRead }}>
      {children}
      <div className="toast-stack">
        {toasts.map((t) => (
          <div className="toast" key={t.id} style={{ "--toast-color": t.color }}>
            <div className="ic"><Icon name={t.icon} size={12} /></div>
            <div>{t.msg}</div>
          </div>
        ))}
      </div>
    </ToastContext.Provider>
  );
};

const useToast = () => React.useContext(ToastContext);

// --------- Modal ----------
const Modal = ({ title, onClose, children, footer }) => {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);
  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div className="modal-title">{title}</div>
          <button className="icon-btn" onClick={onClose}><Icon name="close" /></button>
        </div>
        <div className="modal-body">{children}</div>
        <div className="modal-foot">{footer}</div>
      </div>
    </div>
  );
};

Object.assign(window, {
  Icon, Topbar, ThemeToggle, Tabs, StatusBadge, TipoTag,
  ToastContext, ToastProvider, useToast, Modal,
});
