/* ============================================================
   CultoRD — Root
   ------------------------------------------------------------
   Cada archivo usa IIFE + window para evitar colisiones de
   globales bajo Babel standalone. Sin bundler.
   ============================================================ */
(function () {
  const { useState, useEffect, useRef, useMemo } = React;
  const {
    ThemeProvider, AuthProvider, DataProvider,
    useAuth, useTheme,
    Header, DetailHeader, BottomNav,
    Splash, Login, Home, Mapa, Agenda, Perfil, DetalleIglesia,
    MapaOSM, RegistrarIglesia, AceptarInvitacion, SuperAdmin, AdminIglesia,
    SelectorPerfil, BannerSolicitudPastor, InstalarBanner,
  } = window;

  // Lee el código de invitación de la URL. Soporta /i/XXXXXX (prod, con
  // rewrite de Firebase Hosting) y ?invite=XXXXXX (fallback para dev local
  // sin rewrite). Devuelve string o null.
  function leerCodigoInvitacionDeURL() {
    try {
      const m = window.location.pathname.match(/^\/i\/([^\/\?#]+)$/);
      if (m && m[1]) return decodeURIComponent(m[1]);
      const params = new URLSearchParams(window.location.search);
      const q = params.get("invite");
      if (q) return q;
    } catch (_) { /* noop */ }
    return null;
  }

  function AppFrame({ children }) {
    const { dark } = useTheme();
    return <div className={"app-frame " + (dark ? "dark" : "")}>{children}</div>;
  }

  function SpinnerPantalla({ mensaje }) {
    return (
      <div
        style={{
          minHeight: "100vh",
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          justifyContent: "center",
          gap: 14,
          background: "#FFFFFF",
          padding: 24,
        }}
      >
        <div
          style={{
            width: 36,
            height: 36,
            border: "3px solid #E5E7EB",
            borderTopColor: "#2563EB",
            borderRadius: "50%",
            animation: "spAppPerfil 0.9s linear infinite",
          }}
        />
        <div style={{ fontSize: 14, fontWeight: 800, color: "#4B5563" }}>
          {mensaje || "Cargando..."}
        </div>
        <style>{`@keyframes spAppPerfil { to { transform: rotate(360deg); } }`}</style>
      </div>
    );
  }

  function App() {
    const { user, ready } = useAuth();
    const [tab, setTab] = useState("home");
    // Contador que se bumpea cuando el usuario toca el mismo tab otra vez.
    // Se pasa como key a las screens con sub-estado interno (Perfil → MisIglesias)
    // para que re-monten y reseteen el sub-estado sin lift.
    const [tabResetKey, setTabResetKey] = useState(0);
    const [selected, setSelected] = useState(null);
    const [mapaIglesia, setMapaIglesia] = useState(null);
    const [registrarAbierto, setRegistrarAbierto] = useState(false);
    const [iglesiaEnEdicion, setIglesiaEnEdicion] = useState(null);
    // iglesia { id, nombre, imagen_url } cuando el user inicia "Crear
    // evento" desde el botón + del Header. Se muestra GestionarActividades
    // inline en lugar del tab actual.
    const [creandoActividadEn, setCreandoActividadEn] = useState(null);
    // Panel Superadmin: el super lo abre desde Perfil; se renderiza inline
    // con AppFrame + Header + BottomNav (no overlay, igual que otras
    // pantallas post-login). Se cierra tocando cualquier tab del footer.
    const [panelSuperAbierto, setPanelSuperAbierto] = useState(false);
    // Panel Pastor: el pastor lo abre desde Perfil (igual patrón que super).
    // Antes vivía como tab en BottomNav; se movió para unificar la
    // entrada a paneles administrativos dentro de Perfil → Administración.
    const [panelPastorAbierto, setPanelPastorAbierto] = useState(false);
    // Reclamo de iglesia no-reclamada: cuando el pastor toca "Reclamar"
    // en DetalleIglesia, guardamos aquí la iglesia objetivo y se monta
    // ReclamarIglesiaForm inline.
    const [reclamandoIglesia, setReclamandoIglesia] = useState(null);
    const [iglesiasReales, setIglesiasReales] = useState([]);
    const [codigoInvitacion, setCodigoInvitacion] = useState(() => leerCodigoInvitacionDeURL());
    const [avisoPerfilPublico, setAvisoPerfilPublico] = useState(false);

    // undefined = aún no resolvió la primera respuesta del listener
    // null = resolvió y no existe perfil en RTDB
    // objeto = perfil cargado
    const [miPerfilState, setMiPerfilState] = useState(undefined);

    // Ubicación efectiva del usuario (GPS o manual según su preferencia).
    // La resuelve suscribirUbicacionEfectiva según miPerfilState. Se pasa
    // como prop a Home y Mapa para mostrar el indicador.
    const [ubicacionEfectiva, setUbicacionEfectiva] = useState({ estado: "sin_config" });

    // Suscripción a /solicitudes_pastor/{uid} para banner de estado en Home.
    const [miSolicitud, setMiSolicitud] = useState(null);

    // Snapshot de la preferencia `mostrar_selector_proximo_inicio`.
    // Se captura UNA vez por sesión (al primer snapshot de perfil que llega).
    // Activar el toggle en Perfil después no reabre el selector en esta sesión:
    // se respeta en el próximo login. Al elegir perfil, el flag se apaga en RTDB
    // y el efecto de abajo baja `selectorPorPreferencia` a false.
    const [selectorPorPreferencia, setSelectorPorPreferencia] = useState(false);
    const snapshotPreferenciaCapturado = useRef(false);

    const cerrarInvitacion = () => {
      try { window.history.replaceState(null, "", "/"); } catch (_) { /* noop */ }
      setCodigoInvitacion(null);
    };

    const overlayInvitacion = (codigoInvitacion && AceptarInvitacion)
      ? <AceptarInvitacion
          codigo={codigoInvitacion}
          onCerrar={cerrarInvitacion}
          onRegistrarIglesia={() => setRegistrarAbierto(true)}
        />
      : null;

    // Suscripción al perfil en RTDB cuando hay usuario autenticado.
    useEffect(() => {
      if (!ready || !user || typeof window.suscribirMiPerfil !== "function") {
        setMiPerfilState(undefined);
        return;
      }
      setMiPerfilState(undefined);
      // Reset del snapshot al cambiar de usuario/sesión.
      snapshotPreferenciaCapturado.current = false;
      setSelectorPorPreferencia(false);
      const unsub = window.suscribirMiPerfil(user.uid, (perfil) => {
        setMiPerfilState(perfil);
      });
      return () => {
        if (typeof unsub === "function") unsub();
      };
    }, [ready, user && user.uid]);

    useEffect(() => {
      if (!ready || !user || typeof window.suscribirMiSolicitud !== "function") {
        setMiSolicitud(null);
        return;
      }
      const unsub = window.suscribirMiSolicitud(user.uid, (sol) => {
        setMiSolicitud(sol);
      });
      return () => { if (typeof unsub === "function") unsub(); };
    }, [ready, user && user.uid]);

    // Captura el snapshot de `mostrar_selector_proximo_inicio` la primera vez
    // que llega un perfil no nulo en esta sesión. Cambios posteriores no
    // re-disparan el selector (el toggle en Perfil queda diferido al próximo login).
    useEffect(() => {
      if (snapshotPreferenciaCapturado.current) return;
      if (!miPerfilState) return;
      snapshotPreferenciaCapturado.current = true;
      if (miPerfilState.mostrar_selector_proximo_inicio === true) {
        setSelectorPorPreferencia(true);
      }
    }, [miPerfilState]);

    // Suscripción a ubicación efectiva (GPS o manual) según preferencia del
    // user. La clave de dependencia incluye solo los campos que afectan la
    // fuente de datos (modo + provincia) — así los cambios de alcance_km
    // no reinician el watchPosition.
    const keyUbicacion = (miPerfilState && typeof miPerfilState === "object")
      ? ((miPerfilState.modo_ubicacion || "") + "|" + (miPerfilState.provincia_manual || ""))
      : "__none__";
    useEffect(() => {
      if (!ready || !user) {
        setUbicacionEfectiva({ estado: "sin_config" });
        return;
      }
      if (miPerfilState === undefined) return; // aún no resolvió
      if (typeof window.suscribirUbicacionEfectiva !== "function") return;
      const unsub = window.suscribirUbicacionEfectiva(
        miPerfilState || null,
        function (estado) { setUbicacionEfectiva(estado || { estado: "sin_config" }); }
      );
      return () => { if (typeof unsub === "function") unsub(); };
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [ready, user && user.uid, keyUbicacion]);

    // Si el flag se apaga en RTDB (porque el usuario eligió un perfil en
    // el selector), bajamos la bandera de sesión para cerrar el overlay.
    const flagLive = miPerfilState && miPerfilState.mostrar_selector_proximo_inicio;
    useEffect(() => {
      if (flagLive === false && selectorPorPreferencia) {
        setSelectorPorPreferencia(false);
      }
    }, [flagLive]);

    const isSuper = typeof window.esSuperadmin === "function" && user
      ? window.esSuperadmin(user)
      : false;

    const perfilListo =
      isSuper ||
      (miPerfilState && miPerfilState.onboarding_completado === true);

    // Mostrar selector cuando: (a) hay user, perfil resolvió, no hay invitación
    // y no es super; y además (b) el perfil no está "listo" (usuario nuevo sin
    // onboarding) O la preferencia `mostrar_selector_proximo_inicio` estaba
    // activa al inicio de la sesión.
    const selectorVisible =
      !!user &&
      miPerfilState !== undefined &&
      !codigoInvitacion &&
      !isSuper &&
      (!perfilListo || selectorPorPreferencia);

    const puedePanelSuper = typeof window.puedeVer === "function" && window.puedeVer("panel_super");
    const puedePanelPastor = typeof window.puedeVer === "function" && window.puedeVer("panel_pastor");
    // Ni Panel Superadmin ni Panel Pastor viven en el BottomNav — ambos
    // se abren desde Perfil → Administración. El nav queda limpio con las
    // pestañas estándar (Home, Mapa, Agenda, Perfil).
    const extraTabNav = null;

    // Suscripción a iglesias reales en RTDB cuando hay usuario.
    useEffect(() => {
      if (!ready || !user) { setIglesiasReales([]); return; }
      if (typeof window.suscribirIglesiasActivas !== "function") return;
      try {
        const unsub = window.suscribirIglesiasActivas((arr) => {
          setIglesiasReales(Array.isArray(arr) ? arr : []);
        });
        return typeof unsub === "function" ? unsub : undefined;
      } catch (e) {
        console.warn("[App] suscribirIglesiasActivas falló:", e);
      }
    }, [ready, user]);

    const iglesias = iglesiasReales;

    // Iglesias dentro del alcance del user (según ubicación efectiva).
    // Si la ubicación aún no tiene lat/lng (detectando / denegado /
    // sin config), retorna []. Las iglesias sin coordenadas quedan
    // fuera del descubrimiento por alcance pero siguen en el directorio.
    const alcanceKm = (miPerfilState && typeof miPerfilState.alcance_km === "number")
      ? miPerfilState.alcance_km
      : 5;
    const iglesiasEnRango = useMemo(function () {
      if (typeof window.calcularIglesiasEnRango !== "function") return [];
      return window.calcularIglesiasEnRango(iglesias, ubicacionEfectiva, alcanceKm);
    }, [iglesias, ubicacionEfectiva, alcanceKm]);

    // Deep-link: ?i=<id> al cargar, abre esa iglesia cuando el user esté logueado.
    useEffect(() => {
      if (!ready || !user) return;
      try {
        const params = new URLSearchParams(window.location.search);
        const iglesiaId = params.get("i");
        if (!iglesiaId) return;
        const ig = (iglesias || []).find((x) => String(x.id) === iglesiaId);
        if (ig) setSelected(ig);
        const clean = window.location.pathname + window.location.hash;
        window.history.replaceState({}, "", clean);
      } catch (_) { /* noop */ }
    }, [ready, user, iglesias]);

    if (!ready) return <React.Fragment><AppFrame><Splash /></AppFrame>{overlayInvitacion}</React.Fragment>;
    if (!user)  return (
      <React.Fragment>
        <AppFrame><Login /></AppFrame>
        {/* Banner "Instala CultoRD" también en pre-login: invita al user a
            instalar antes de autenticarse. Sin BottomNav, offsetBottom 20. */}
        {InstalarBanner && !codigoInvitacion && <InstalarBanner offsetBottom={20} />}
        {overlayInvitacion}
      </React.Fragment>
    );

    // User autenticado pero perfil aún no resuelto (y no hay invitación).
    if (miPerfilState === undefined && !codigoInvitacion && !isSuper) {
      return <SpinnerPantalla mensaje="Cargando tu perfil..." />;
    }

    const overlaySelector = (selectorVisible && SelectorPerfil) ? (
      <SelectorPerfil
        uid={user.uid}
        user={user}
        onElegido={() => { /* el listener actualiza miPerfilState solo */ }}
      />
    ) : null;

    const handleTab = (t) => {
      setSelected(null);
      // Salirse de paneles administrativos cuando el user toca cualquier tab.
      if (panelSuperAbierto) setPanelSuperAbierto(false);
      if (panelPastorAbierto) setPanelPastorAbierto(false);
      if (t === tab) {
        // Re-tap del mismo tab → resetea el sub-estado interno de esa screen.
        setTabResetKey((k) => k + 1);
      }
      setTab(t);
    };

    const overlayOSM = mapaIglesia ? (
      <MapaOSM iglesia={mapaIglesia} onClose={() => setMapaIglesia(null)} />
    ) : null;

    const wizardAbierto = registrarAbierto || !!iglesiaEnEdicion;
    const cerrarWizard = () => {
      setRegistrarAbierto(false);
      setIglesiaEnEdicion(null);
    };
    const onWizardCreado = (id) => {
      console.log("[App] iglesia guardada:", id);
      // Si el usuario tenía solicitud aprobada, la limpiamos para que
      // el banner verde desaparezca tras registrar su iglesia.
      if (miSolicitud && miSolicitud.estado === "aprobada" && user && user.uid && window.db) {
        window.db.ref("solicitudes_pastor/" + user.uid).remove()
          .catch((e) => console.warn("[App] no pudimos limpiar solicitud:", e));
      }
    };

    const handleAutorTap = (autorUid) => {
      if (autorUid && user && autorUid === user.uid) {
        setSelected(null);
        setTab("perf");
      } else {
        // TODO: pantalla de perfil público de otro usuario
        setAvisoPerfilPublico(true);
      }
    };

    const ConfirmModal = window.ConfirmModal;
    const overlayAvisoPerfil = ConfirmModal ? (
      <ConfirmModal
        abierto={avisoPerfilPublico}
        titulo="Perfil público"
        mensaje="El perfil público de este usuario estará disponible próximamente."
        textoConfirmar="Entendido"
        textoCancelar={null}
        onConfirmar={() => setAvisoPerfilPublico(false)}
        onCancelar={() => setAvisoPerfilPublico(false)}
      />
    ) : null;

    // Panel Superadmin accedido desde Perfil. Inline dentro de AppFrame.
    if (panelSuperAbierto && puedePanelSuper && SuperAdmin) {
      return (
        <AppFrame>
          <Header
            onAvatar={() => { setPanelSuperAbierto(false); setTab("perf"); }}
            onSelect={setSelected}
            iglesias={iglesias}
            iglesiasEnRango={iglesiasEnRango}
            onCrearEvento={setCreandoActividadEn}
          />
          <SuperAdmin iglesias={iglesias} />
          <BottomNav tab={tab} setTab={handleTab} extraTab={extraTabNav} />
          {overlayOSM}
          {overlayInvitacion}
          {overlaySelector}
          {overlayAvisoPerfil}
        </AppFrame>
      );
    }

    // Panel Pastor accedido desde Perfil (mismo patrón que Superadmin).
    if (panelPastorAbierto && puedePanelPastor && AdminIglesia) {
      return (
        <AppFrame>
          <Header
            onAvatar={() => { setPanelPastorAbierto(false); setTab("perf"); }}
            onSelect={setSelected}
            iglesias={iglesias}
            iglesiasEnRango={iglesiasEnRango}
            onCrearEvento={setCreandoActividadEn}
          />
          <AdminIglesia iglesias={iglesias} />
          <BottomNav tab={tab} setTab={handleTab} extraTab={extraTabNav} />
          {overlayOSM}
          {overlayInvitacion}
          {overlaySelector}
          {overlayAvisoPerfil}
        </AppFrame>
      );
    }

    // Crear evento desde el + del Header: monta GestionarActividades
    // inline con la iglesia seleccionada, manteniendo Header + BottomNav.
    if (creandoActividadEn && window.GestionarActividades) {
      return (
        <AppFrame>
          <Header
            onAvatar={() => setTab("perf")}
            onSelect={setSelected}
            iglesias={iglesias}
            iglesiasEnRango={iglesiasEnRango}
            onCrearEvento={setCreandoActividadEn}
          />
          {React.createElement(window.GestionarActividades, {
            iglesiaId: creandoActividadEn.id,
            iglesia: creandoActividadEn,
            onCerrar: () => setCreandoActividadEn(null),
          })}
          <BottomNav tab={tab} setTab={handleTab} extraTab={extraTabNav} />
          {overlayOSM}
          {overlayInvitacion}
          {overlaySelector}
          {overlayAvisoPerfil}
        </AppFrame>
      );
    }

    // Wizard RegistrarIglesia: inline dentro del body de la app (Header +
    // BottomNav visibles). No es overlay; reemplaza el contenido del tab.
    if (wizardAbierto && RegistrarIglesia) {
      return (
        <AppFrame>
          <Header
            onAvatar={() => setTab("perf")}
            onSelect={setSelected}
            iglesias={iglesias}
            iglesiasEnRango={iglesiasEnRango}
            onCrearEvento={setCreandoActividadEn}
          />
          <RegistrarIglesia
            abierto={true}
            iglesiaInicial={iglesiaEnEdicion}
            onClose={cerrarWizard}
            onCreado={onWizardCreado}
          />
          <BottomNav tab={tab} setTab={handleTab} extraTab={extraTabNav} />
          {overlayOSM}
          {overlayInvitacion}
          {overlaySelector}
          {overlayAvisoPerfil}
        </AppFrame>
      );
    }

    // Formulario de reclamo (inline) cuando el pastor quiere tomar
    // posesión de una iglesia no reclamada. Se monta en lugar del
    // DetalleIglesia actual; al cerrar vuelve a la ficha.
    if (reclamandoIglesia && window.ReclamarIglesiaForm) {
      return (
        <AppFrame>
          <DetailHeader
            title="Reclamar iglesia"
            onBack={() => setReclamandoIglesia(null)}
          />
          {React.createElement(window.ReclamarIglesiaForm, {
            iglesia: reclamandoIglesia,
            onCerrar: () => setReclamandoIglesia(null),
          })}
          <BottomNav tab={tab} setTab={handleTab} extraTab={extraTabNav} />
          {overlayOSM}
          {overlayInvitacion}
          {overlaySelector}
          {overlayAvisoPerfil}
        </AppFrame>
      );
    }

    if (selected) {
      return (
        <AppFrame>
          <DetailHeader title={selected.nombre} onBack={() => setSelected(null)} />
          <DetalleIglesia
            iglesia={selected}
            onAutorTap={handleAutorTap}
            onReclamar={(ig) => setReclamandoIglesia(ig)}
          />
          <BottomNav tab={tab} setTab={handleTab} extraTab={extraTabNav} />
          {overlayOSM}
          {overlayInvitacion}
          {overlaySelector}
          {overlayAvisoPerfil}
        </AppFrame>
      );
    }

    return (
      <AppFrame>
        <Header
          onAvatar={() => setTab("perf")}
          onSelect={setSelected}
          iglesias={iglesias}
          iglesiasEnRango={iglesiasEnRango}
          onCrearEvento={setCreandoActividadEn}
        />
        {tab === "home"   && (
          <Home
            onSelect={setSelected}
            onShowMap={setMapaIglesia}
            iglesias={iglesias}
            iglesiasEnRango={iglesiasEnRango}
            ubicacionEfectiva={ubicacionEfectiva}
            alcanceKm={alcanceKm}
            onConfigurarUbicacion={() => setTab("perf")}
            banner={
              BannerSolicitudPastor && miSolicitud && (
                (miPerfilState && miPerfilState.tipo === "miembro") ||
                (miSolicitud.estado === "aprobada")
              ) ? (
                <BannerSolicitudPastor
                  uid={user.uid}
                  solicitud={miSolicitud}
                  onRegistrarIglesia={() => setRegistrarAbierto(true)}
                />
              ) : null
            }
          />
        )}
        {tab === "mapa"   && (
          <Mapa
            onSelect={setSelected}
            onShowMap={setMapaIglesia}
            iglesias={iglesias}
            iglesiasEnRango={iglesiasEnRango}
            ubicacionEfectiva={ubicacionEfectiva}
            alcanceKm={alcanceKm}
            onCambiarAlcance={(km) => {
              if (user && user.uid && typeof window.actualizarAlcance === "function") {
                window.actualizarAlcance(user.uid, km).catch(function (e) {
                  console.warn("[app] actualizarAlcance falló:", e);
                });
              }
            }}
            onConfigurarUbicacion={() => setTab("perf")}
          />
        )}
        {tab === "agenda" && <Agenda />}
        {tab === "perf"   && (
          <Perfil
            key={"perf-" + tabResetKey}
            onLogout={() => setTab("home")}
            onRegistrarIglesia={() => setRegistrarAbierto(true)}
            onAbrirPanelSuper={puedePanelSuper ? () => setPanelSuperAbierto(true) : null}
            onAbrirPanelPastor={(puedePanelPastor && !isSuper) ? () => setPanelPastorAbierto(true) : null}
          />
        )}

        <BottomNav tab={tab} setTab={handleTab} extraTab={extraTabNav} />

        {/* Banner "Instala CultoRD" — sólo en la pantalla principal y sólo
            cuando no hay overlays de onboarding abiertos (invitación /
            selector de perfil). El propio componente decide si mostrarse
            según estado de instalación y dismiss reciente. */}
        {InstalarBanner && !codigoInvitacion && !selectorVisible && <InstalarBanner />}

        {overlayOSM}
        {overlayInvitacion}
        {overlaySelector}
        {overlayAvisoPerfil}
      </AppFrame>
    );
  }

  ReactDOM.createRoot(document.getElementById("root")).render(
    <ThemeProvider>
      <AuthProvider>
        <DataProvider>
          <App />
        </DataProvider>
      </AuthProvider>
    </ThemeProvider>
  );
})();
