/* App entry — login gate + router. Sesión por email + password (POST /auth/login)
 * con token persistido en localStorage. Modo demo opcional (sin backend) cuando
 * el usuario clickea "Modo demo" en login.
 */

const ACCENTS = {
  vital:   { color: "#16a34a", soft: "rgba(22, 163, 74, 0.14)",   fg: "#ffffff", label: "Vital green" },
  ember:   { color: "#ea580c", soft: "rgba(234, 88, 12, 0.14)",   fg: "#ffffff", label: "Ember orange" },
  ocean:   { color: "#0284c7", soft: "rgba(2, 132, 199, 0.14)",   fg: "#ffffff", label: "Ocean blue" },
  iron:    { color: "#dc2626", soft: "rgba(220, 38, 38, 0.14)",   fg: "#ffffff", label: "Iron red" },
  mineral: { color: "#0891b2", soft: "rgba(8, 145, 178, 0.14)",   fg: "#ffffff", label: "Mineral teal" },
  mono:    { color: "#1a1a1a", soft: "rgba(0, 0, 0, 0.08)",       fg: "#ffffff", label: "Mono" },
};

const FONT_FAMILIES = {
  system: { sans: "'Geist', 'Inter', system-ui, sans-serif", display: "'Fraunces', serif", label: "Sans + Serif" },
  mono:   { sans: "'JetBrains Mono', ui-monospace, monospace", display: "'JetBrains Mono', monospace", label: "Mono everywhere" },
  serif:  { sans: "'IBM Plex Serif', Georgia, serif", display: "'Fraunces', serif", label: "Editorial serif" },
};

const PREFS_KEY = "api_fit_prefs";

const DEFAULTS = {
  // "auto" sigue al SO (prefers-color-scheme); "dark" / "light" lo fijan.
  // Default auto — el brief §10 prefiere oscuro pero respetamos la
  // preferencia del usuario primero.
  theme: "auto",
  density: "compact",
  dataState: "full",
  accent: "ocean",
  fontFamily: "system",
  showDisclaimer: true,
};

// Helper: tema efectivo (lo que se setea en data-theme).
function resolveTheme(pref) {
  if (pref === "dark" || pref === "light") return pref;
  // auto / cualquier otro
  if (typeof window !== "undefined" && window.matchMedia) {
    return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
  }
  return "dark";
}

function loadPrefs() {
  try {
    const raw = localStorage.getItem(PREFS_KEY);
    if (raw) return { ...DEFAULTS, ...JSON.parse(raw) };
  } catch (_) {}
  return DEFAULTS;
}
function savePrefs(p) {
  try { localStorage.setItem(PREFS_KEY, JSON.stringify(p)); } catch (_) {}
}

function App() {
  // boot status: 'checking' | 'login' | 'authed' | 'demo'
  const [boot, setBoot] = React.useState("checking");
  const [user, setUser] = React.useState(() => API.getUser());
  const [tweaks, setTweaks] = React.useState(loadPrefs);
  const setTweak = (k, v) => setTweaks((p) => {
    const next = (typeof k === "object") ? { ...p, ...k } : { ...p, [k]: v };
    savePrefs(next);
    return next;
  });

  const [route, setRoute] = React.useState("today");
  const [toast, setToast] = React.useState(null);

  // 401 desde cualquier parte → kick a login.
  React.useEffect(() => {
    API.on("unauthorized", () => {
      // En modo demo no hay sesión, así que ignoramos.
      if (API.demoMode()) return;
      setToast({ kind: "bad", msg: "Sesión expirada. Volvé a iniciar sesión." });
      API.clearToken();
      API.clearUser();
      setUser(null);
      setBoot("login");
    });
    API.on("error", (e) => {
      if (e.network) {
        // No hagas spam: solo mostralo una vez por minuto.
        if (!window.__af_last_net_toast || Date.now() - window.__af_last_net_toast > 60_000) {
          window.__af_last_net_toast = Date.now();
          setToast({ kind: "bad", msg: "El backend no responde. Datos de muestra en pantalla." });
        }
      }
    });
  }, []);

  // Boot: decide si vamos directo a la app o al login.
  React.useEffect(() => {
    let alive = true;
    (async () => {
      // 1) Demo mode → entrar con MOCKs sin tocar backend.
      if (API.demoMode()) {
        if (alive) setBoot("demo");
        return;
      }
      // 2) Token presente → validar con /auth/me.
      if (API.getToken()) {
        try {
          const me = await API.authMe();
          if (!alive) return;
          API.setUser(me);
          setUser(me);
          setBoot("authed");
          return;
        } catch (e) {
          if (e.status === 401) {
            API.clearToken();
            API.clearUser();
            if (alive) setBoot("login");
            return;
          }
          // Si el backend está caído, no perdemos la sesión: dejamos al usuario entrar
          // y los componentes caerán a MOCK silenciosamente. El usuario ya tiene un
          // user persistido localmente.
          if (e.network) {
            if (alive) {
              setBoot("authed");
              setToast({ kind: "bad", msg: "El backend no responde. Datos de muestra en pantalla." });
            }
            return;
          }
        }
      }
      // 3) Sin token → ir a login. Login.jsx llama a /auth/has_users para decidir
      //    si arranca en modo register (primera ejecución) o login normal.
      if (alive) setBoot("login");
    })();
    return () => { alive = false; };
  }, []);

  // Permitir a otras pantallas redirigir vía evento (p.ej. CTA "Configurar LLM")
  React.useEffect(() => {
    const onRoute = (e) => setRoute(e.detail);
    window.addEventListener("af-route", onRoute);
    return () => window.removeEventListener("af-route", onRoute);
  }, []);

  // Aplicar tema, densidad, acento, tipografía a <html>. Cuando el usuario
  // elige "auto" además escuchamos prefers-color-scheme para reaccionar en
  // vivo a cambios del SO (modo nocturno automático, switch manual del
  // usuario en Ajustes, etc.).
  React.useEffect(() => {
    const apply = () => {
      document.documentElement.dataset.theme = resolveTheme(tweaks.theme);
    };
    apply();
    if (tweaks.theme === "auto" && typeof window !== "undefined" && window.matchMedia) {
      const mq = window.matchMedia("(prefers-color-scheme: dark)");
      mq.addEventListener("change", apply);
      return () => mq.removeEventListener("change", apply);
    }
  }, [tweaks.theme]);

  React.useEffect(() => {
    document.documentElement.dataset.density = tweaks.density;
    const a = ACCENTS[tweaks.accent] || ACCENTS.vital;
    document.documentElement.style.setProperty("--accent", a.color);
    document.documentElement.style.setProperty("--accent-soft", a.soft);
    document.documentElement.style.setProperty("--accent-fg", a.fg);
    const f = FONT_FAMILIES[tweaks.fontFamily] || FONT_FAMILIES.system;
    document.documentElement.style.setProperty("--font-sans", f.sans);
    document.documentElement.style.setProperty("--font-display", f.display);
  }, [tweaks.density, tweaks.accent, tweaks.fontFamily]);

  // Toast auto-dismiss
  React.useEffect(() => {
    if (!toast) return;
    const t = setTimeout(() => setToast(null), 4500);
    return () => clearTimeout(t);
  }, [toast]);

  if (boot === "checking") {
    return (
      <div style={{
        position: "fixed", inset: 0, display: "grid", placeItems: "center",
        background: "var(--bg)", color: "var(--text-3)",
        fontFamily: "var(--font-mono)", fontSize: 12,
      }}>
        verificando sesión…
      </div>
    );
  }

  if (boot === "login") {
    return (
      <Login
        onAuthenticated={() => {
          setUser(API.getUser());
          setBoot("authed");
          setRoute("today");
        }}
        onRegisteredFirstTime={() => {
          setUser(API.getUser());
          setBoot("authed");
          setRoute("onboarding");
        }}
      />
    );
  }

  const inDemo = boot === "demo" || API.demoMode();

  const exitDemo = () => {
    API.setDemoMode(false);
    setBoot("login");
  };

  const handleLogout = async () => {
    try {
      await API.authLogout();
    } catch (_) {}
    setUser(null);
    setBoot("login");
    setRoute("today");
  };

  const titles = {
    today:      { t: "Hoy",            s: subtitle() },
    metrics:    { t: "Métricas",       s: "Tendencias · histórico" },
    activities: { t: "Actividades",    s: "Tus sincronizaciones recientes" },
    agents:     { t: "Coach",          s: "Coach · Nutricionista · Médico" },
    plans:      { t: "Planes",         s: "Entrenamiento · Nutrición" },
    knowledge:  { t: "Biblioteca",     s: "Libros y apuntes que cita el coach" },
    settings:   { t: "Configuración",  s: "Proveedores · LLM · Privacidad" },
  };

  if (route === "onboarding") {
    return <Onboarding onExit={() => setRoute("today")} />;
  }

  const userLabel = inDemo ? "Demo" : (user?.name || user?.email || "usuario");

  return (
    <div data-screen-label="01 App" style={{ display: "flex", flexDirection: "column", height: "100vh", overflow: "hidden", background: "var(--bg)" }}>
      <MobileNav route={route} setRoute={setRoute} />
      <div style={{ display: "flex", flex: 1, minHeight: 0, overflow: "hidden" }}>
        <Sidebar route={route} setRoute={setRoute} density={tweaks.density} user={user} inDemo={inDemo} />
        <main style={{ flex: 1, overflowY: "auto", display: "flex", flexDirection: "column" }}>
          <TopBar
            title={titles[route]?.t}
            subtitle={titles[route]?.s}
            breadcrumb={`FtiMind / ${titles[route]?.t.toLowerCase()}`}
            density={tweaks.density}
            setDensity={(v) => setTweak("density", v)}
            actions={
              <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
                {inDemo && (
                  <span title="Estás en modo demo: los datos son de muestra, sin backend." style={{
                    padding: "3px 8px", borderRadius: "var(--r-2)",
                    background: "var(--warn-soft)", color: "var(--warn)",
                    fontFamily: "var(--font-mono)", fontSize: 10, fontWeight: 600,
                    letterSpacing: 0.08, border: "1px solid color-mix(in srgb, var(--warn) 30%, transparent)",
                  }}>DEMO</span>
                )}
                <span style={{ fontSize: 11.5, color: "var(--text-3)", maxWidth: 180, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                  {userLabel}
                </span>
                <Btn
                  size="sm" variant="ghost"
                  icon={<Icon name="moon" size={12} />}
                  title={
                    tweaks.theme === "auto"
                      ? `Tema: Auto (sigue al SO · actualmente ${resolveTheme("auto")})`
                      : `Tema: ${tweaks.theme === "dark" ? "Oscuro" : "Claro"} (fijo)`
                  }
                  onClick={() => setTweak("theme",
                    tweaks.theme === "auto" ? "light" :
                    tweaks.theme === "light" ? "dark" : "auto"
                  )}
                >
                  {tweaks.theme === "auto" ? "Auto" : tweaks.theme === "dark" ? "Oscuro" : "Claro"}
                </Btn>
                {inDemo ? (
                  <Btn size="sm" variant="ghost" onClick={exitDemo}>Salir de demo</Btn>
                ) : (
                  <Btn size="sm" variant="ghost" onClick={handleLogout}>Logout</Btn>
                )}
              </div>
            }
          />
          <div data-screen-label={`02 ${titles[route]?.t}`} key={route} className="fade-in">
            {route === "today" && <Today density={tweaks.density} dataState={tweaks.dataState} showDisclaimer={tweaks.showDisclaimer} setRoute={setRoute} inDemo={inDemo} />}
            {route === "metrics" && <Metrics density={tweaks.density} dataState={tweaks.dataState} inDemo={inDemo} />}
            {route === "activities" && <Activities density={tweaks.density} dataState={tweaks.dataState} setRoute={setRoute} inDemo={inDemo} />}
            {route === "agents" && <Agents density={tweaks.density} dataState={tweaks.dataState} showDisclaimer={tweaks.showDisclaimer} inDemo={inDemo} />}
            {route === "plans" && <Plans density={tweaks.density} dataState={tweaks.dataState} setRoute={setRoute} inDemo={inDemo} />}
            {route === "knowledge" && <Knowledge inDemo={inDemo} />}
            {route === "settings" && <Settings density={tweaks.density} inDemo={inDemo} onLogout={handleLogout} setRoute={setRoute} />}
          </div>
        </main>
      </div>

      {/* Floating preferences panel — auto-open con keyboard shortcut Cmd+. */}
      <PrefsPanel tweaks={tweaks} setTweak={setTweak} setRoute={setRoute} onLogout={handleLogout} inDemo={inDemo} exitDemo={exitDemo} />

      {toast && (
        <div className={`af-toast ${toast.kind || ""}`}>
          {toast.msg}
        </div>
      )}
    </div>
  );
}

function subtitle(suffix) {
  const d = new Date();
  const days = ["Dom","Lun","Mar","Mié","Jue","Vie","Sáb"];
  const months = ["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"];
  const head = `${days[d.getDay()]} ${String(d.getDate()).padStart(2,"0")} ${months[d.getMonth()]}`;
  return suffix ? `${head} · ${suffix}` : head;
}

/* Panel flotante de preferencias — versión simplificada del TweaksPanel
 * (sin postMessage al host). Activa con icono ⚙ flotante. */
const PrefsPanel = ({ tweaks, setTweak, setRoute, onLogout, inDemo, exitDemo }) => {
  const [open, setOpen] = React.useState(false);

  React.useEffect(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key === ".") {
        e.preventDefault(); setOpen((v) => !v);
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);

  return (
    <>
      <button
        onClick={() => setOpen((v) => !v)}
        title="Preferencias (⌘.)"
        style={{
          position: "fixed", bottom: 18, right: 18, zIndex: 90,
          width: 38, height: 38, borderRadius: "50%",
          background: "var(--bg-1)", color: "var(--text-2)",
          border: "1px solid var(--line)", boxShadow: "var(--shadow-2)",
          display: "grid", placeItems: "center", cursor: "pointer",
        }}>
        <Icon name="settings" size={15} />
      </button>

      {open && (
        <div style={{
          position: "fixed", bottom: 64, right: 18, zIndex: 90,
          width: 280, padding: 14,
          background: "var(--bg-1)", border: "1px solid var(--line)",
          borderRadius: "var(--r-3)", boxShadow: "var(--shadow-2)",
        }}>
          <div className="eyebrow" style={{ marginBottom: 10 }}>APARIENCIA</div>
          <PrefRow label="Modo">
            <Seg value={tweaks.theme} onChange={(v) => setTweak("theme", v)} options={[
              { value: "auto",  label: "Auto" },
              { value: "light", label: "Claro" },
              { value: "dark",  label: "Oscuro" },
            ]} />
          </PrefRow>
          <PrefRow label="Densidad">
            <Seg value={tweaks.density} onChange={(v) => setTweak("density", v)} options={[
              { value: "compact",     label: "Compact" },
              { value: "comfortable", label: "Normal" },
              { value: "detailed",    label: "Detail" },
            ]} />
          </PrefRow>
          <PrefRow label="Acento">
            <select value={tweaks.accent} onChange={(e) => setTweak("accent", e.target.value)} style={selectStyle}>
              {Object.entries(ACCENTS).map(([k, a]) => <option key={k} value={k}>{a.label}</option>)}
            </select>
          </PrefRow>
          <PrefRow label="Tipografía">
            <select value={tweaks.fontFamily} onChange={(e) => setTweak("fontFamily", e.target.value)} style={selectStyle}>
              {Object.entries(FONT_FAMILIES).map(([k, f]) => <option key={k} value={k}>{f.label}</option>)}
            </select>
          </PrefRow>

          <div className="eyebrow" style={{ marginBottom: 10, marginTop: 14 }}>DATOS (DEMO)</div>
          <PrefRow label="Estado">
            <Seg value={tweaks.dataState} onChange={(v) => setTweak("dataState", v)} options={[
              { value: "full",    label: "Lleno" },
              { value: "partial", label: "Parcial" },
              { value: "empty",   label: "Vacío" },
            ]} />
          </PrefRow>
          <PrefRow label="Disclaimer médico">
            <button onClick={() => setTweak("showDisclaimer", !tweaks.showDisclaimer)} style={{
              width: 32, height: 18, borderRadius: 999,
              background: tweaks.showDisclaimer ? "var(--accent)" : "var(--line)",
              border: "none", padding: 2,
              display: "flex", alignItems: "center",
            }}>
              <div style={{
                width: 14, height: 14, borderRadius: "50%",
                background: "white",
                transform: tweaks.showDisclaimer ? "translateX(14px)" : "translateX(0)",
                transition: "transform 0.15s",
              }} />
            </button>
          </PrefRow>

          <div style={{ paddingTop: 12, marginTop: 12, borderTop: "1px solid var(--line-soft)", display: "flex", flexDirection: "column", gap: 6 }}>
            {inDemo ? (
              <button onClick={exitDemo} style={ghostBtn}>
                ⏻ Salir de demo
              </button>
            ) : (
              <button onClick={onLogout} style={ghostBtn}>
                ⏻ Cerrar sesión
              </button>
            )}
          </div>
        </div>
      )}
    </>
  );
};

const PrefRow = ({ label, children }) => (
  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8, gap: 8 }}>
    <span style={{ fontSize: 11.5, color: "var(--text-2)" }}>{label}</span>
    {children}
  </div>
);

const Seg = ({ value, onChange, options }) => (
  <div style={{ display: "inline-flex", padding: 2, background: "var(--bg-2)", border: "1px solid var(--line)", borderRadius: 5 }}>
    {options.map((o) => (
      <button key={o.value} onClick={() => onChange(o.value)} style={{
        padding: "3px 8px", fontSize: 11, border: "none",
        background: value === o.value ? "var(--bg-3)" : "transparent",
        color: value === o.value ? "var(--text)" : "var(--text-3)",
        borderRadius: 3, fontWeight: 500,
      }}>{o.label}</button>
    ))}
  </div>
);

const selectStyle = {
  padding: "4px 8px", fontSize: 11.5,
  background: "var(--bg-2)", border: "1px solid var(--line)",
  borderRadius: 5, color: "var(--text)", outline: "none",
};

const ghostBtn = {
  padding: "6px 8px", textAlign: "left",
  background: "transparent", border: "none",
  color: "var(--text-2)", fontSize: 12,
  cursor: "pointer", borderRadius: 4,
};

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