/* Buscador → window. Resultados dinámicos agrupados por sección.
   Props: { abierto, query, iglesias, iglesiasEnRango, onSelect, onClose }

   Reglas de búsqueda (acordadas con producto):
   - **Globales** (contra TODAS las iglesias activas, sin radio):
       · nombre de iglesia
       · nombre del pastor (creado_por_nombre)
       · nombre de actividad puntual (evento)
   - **Limitadas al alcance del user** (porque sería demasiada data):
       · horarios del programa — culto, oración, jóvenes, "hoy",
         "mañana", por día, etc.
   - **Nunca**: nombres de miembros ni de amigos.

   Render: secciones etiquetadas (Iglesias · Pastores · Actividades ·
   Programa). Cada fila es delgada y uniforme — nada de parecerse a
   la ficha de una iglesia. Tap abre el detalle de la iglesia asociada. */
(function () {
  const { useMemo, useState, useEffect } = React;

  function normalize(s) {
    return (s || "")
      .toString()
      .toLowerCase()
      .normalize("NFD")
      .replace(/[\u0300-\u036f]/g, "");
  }

  const DIAS_NORM    = ["domingo", "lunes", "martes", "miercoles", "jueves", "viernes", "sabado"];
  const DIAS_ABREV   = ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb"];
  const DIAS_NOMBRE  = ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"];
  const TIPOS_LABEL  = {
    culto: "Culto", jovenes: "Jóvenes", caballeros: "Caballeros",
    damas: "Damas", ninos: "Niños", oracion: "Oración",
    estudio: "Estudio", celula: "Célula", otro: "Otro",
  };
  const TIPOS_EMOJI  = {
    culto: "⛪", jovenes: "🧑‍🎤", caballeros: "🤝", damas: "💐",
    ninos: "🧒", oracion: "🙏", estudio: "📖", celula: "🏠", otro: "✨",
  };
  const TIPOS_ALIAS  = {
    culto: "culto", cultos: "culto", jovenes: "jovenes", joven: "jovenes",
    caballeros: "caballeros", caballero: "caballeros", hombres: "caballeros", hombre: "caballeros",
    damas: "damas", mujer: "damas", mujeres: "damas",
    ninos: "ninos", nino: "ninos", ninas: "ninos", nina: "ninos", infantil: "ninos",
    oracion: "oracion", oraciones: "oracion",
    estudio: "estudio", biblia: "estudio", biblico: "estudio",
    celula: "celula", celulas: "celula",
  };

  // Emoji por tipo de actividad puntual (alineado con actividades.js TIPOS).
  const EMOJI_ACTIVIDAD = {
    culto_unido: "🙌", retiro: "⛰️", vigilia: "🕯️", campana: "📣",
    conferencia: "🎤", ayuno: "🙏", bautismo: "💧", santa_cena: "🍷",
    otro: "✨",
  };

  function parseHHMM(s) {
    const [h, m] = String(s || "").split(":").map(Number);
    if (isNaN(h) || isNaN(m)) return null;
    return h * 60 + m;
  }
  function fmtHora12(hhmm) {
    const n = parseHHMM(hhmm);
    if (n == null) return "";
    const h = Math.floor(n / 60), m = n % 60;
    const period = h >= 12 ? "PM" : "AM";
    const hr = h % 12 || 12;
    return hr + ":" + String(m).padStart(2, "0") + " " + period;
  }
  function diaIdx(d) {
    if (typeof d === "number" && d >= 0 && d <= 6) return d;
    if (typeof d === "string") {
      const ix = DIAS_NOMBRE.indexOf(d);
      if (ix >= 0) return ix;
      const n = Number(d);
      if (!isNaN(n) && n >= 0 && n <= 6) return n;
    }
    return -1;
  }

  // Extrae día y tipo semántico de la query; el resto queda como texto
  // libre. "hoy"/"mañana" se resuelven contra la fecha actual.
  function parseQuery(qNorm) {
    const tokens = qNorm.split(/\s+/).filter(Boolean);
    const now = new Date();
    let dia = null;
    let tipo = null;
    const resto = [];
    tokens.forEach((t) => {
      if (t === "hoy")    { dia = now.getDay(); return; }
      if (t === "manana") { dia = (now.getDay() + 1) % 7; return; }
      const ix = DIAS_NORM.indexOf(t);
      if (ix >= 0) { dia = ix; return; }
      if (TIPOS_ALIAS[t]) { tipo = TIPOS_ALIAS[t]; return; }
      resto.push(t);
    });
    return { dia, tipo, texto: resto.join(" ") };
  }

  function minutosParaEmpezar(slot, now) {
    const d = diaIdx(slot.dia);
    const ini = parseHHMM(slot.hora_inicio);
    if (d < 0 || ini == null) return null;
    const nowDay = now.getDay();
    const nowMin = now.getHours() * 60 + now.getMinutes();
    let daysAhead = (d - nowDay + 7) % 7;
    let startAbs = daysAhead * 1440 + ini;
    const fin = parseHHMM(slot.hora_fin);
    const dur = (fin != null && fin > ini) ? (fin - ini) : 60;
    if (daysAhead === 0 && nowMin > startAbs + dur + 60) startAbs += 7 * 1440;
    return startAbs - nowMin;
  }

  function fmtFechaCorta(ms) {
    if (typeof ms !== "number") return "";
    const d = new Date(ms);
    const hoy = new Date();
    const manana = new Date(hoy.getTime() + 24 * 60 * 60 * 1000);
    const mismo = (a, b) =>
      a.getFullYear() === b.getFullYear() &&
      a.getMonth() === b.getMonth() &&
      a.getDate() === b.getDate();
    if (mismo(d, hoy))    return "Hoy";
    if (mismo(d, manana)) return "Mañana";
    return DIAS_ABREV[d.getDay()] + " " + d.getDate() + "/" + (d.getMonth() + 1);
  }

  function BadgeNoReclamada({ dark }) {
    return (
      <span style={{
        display: "inline-block",
        padding: "1px 6px",
        borderRadius: 6,
        fontSize: 9, fontWeight: 900,
        letterSpacing: 0.4,
        textTransform: "uppercase",
        background: dark ? "#78350F" : "#FEF3C7",
        color: dark ? "#FCD34D" : "#92400E",
        marginLeft: 6,
        verticalAlign: "middle",
        whiteSpace: "nowrap",
      }}>
        No reclamada
      </span>
    );
  }

  function Row({ emoji, imagen, titulo, subtitulo, onClick, dark, noReclamada }) {
    return (
      <button
        type="button"
        onClick={onClick}
        style={{
          display: "flex", alignItems: "center", gap: 12,
          width: "100%", textAlign: "left",
          padding: "10px 14px",
          borderRadius: 0,
          border: "none",
          background: "transparent",
          cursor: "pointer",
          fontFamily: "inherit",
        }}
        onMouseEnter={(e) => { e.currentTarget.style.background = dark ? "#1A1A1A" : "#F9FAFB"; }}
        onMouseLeave={(e) => { e.currentTarget.style.background = "transparent"; }}
      >
        <div style={{
          width: 36, height: 36, borderRadius: 10,
          background: dark ? "#262626" : "#F3F4F6",
          display: "flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0, overflow: "hidden",
          fontSize: 18,
        }}>
          {imagen ? (
            <img
              src={imagen}
              alt=""
              referrerPolicy="no-referrer"
              style={{ width: "100%", height: "100%", objectFit: "cover" }}
            />
          ) : (
            <span aria-hidden>{emoji || "·"}</span>
          )}
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            fontSize: 14, fontWeight: 800,
            color: dark ? "#F0F0F0" : "#111827",
            overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
          }}>
            <span>{titulo}</span>
            {noReclamada && <BadgeNoReclamada dark={dark} />}
          </div>
          {subtitulo && (
            <div style={{
              fontSize: 12, fontWeight: 600,
              marginTop: 1,
              color: dark ? "#9CA3AF" : "#6B7280",
              overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
            }}>
              {subtitulo}
            </div>
          )}
        </div>
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden
             style={{ flexShrink: 0, color: dark ? "#4B5563" : "#D1D5DB" }}>
          <path d="M9 6l6 6-6 6" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      </button>
    );
  }

  function Seccion({ titulo, count, dark, children }) {
    if (count === 0) return null;
    return (
      <div style={{ marginBottom: 10 }}>
        <div style={{
          padding: "10px 16px 6px",
          fontSize: 10, fontWeight: 900,
          letterSpacing: "0.15em", textTransform: "uppercase",
          color: dark ? "#9CA3AF" : "#6B7280",
          display: "flex", alignItems: "center", justifyContent: "space-between",
        }}>
          <span>{titulo}</span>
          <span style={{
            fontSize: 10, padding: "2px 8px", borderRadius: 999,
            background: dark ? "#1F2937" : "#F3F4F6",
            color: dark ? "#D1D5DB" : "#4B5563",
            letterSpacing: 0.3,
          }}>{count}</span>
        </div>
        <div>{children}</div>
      </div>
    );
  }

  function Buscador({ abierto, query, onSelect, onClose, onSetQuery, iglesias, iglesiasEnRango }) {
    const dark =
      typeof document !== "undefined" &&
      document.querySelector(".app-frame")?.classList.contains("dark");

    const qNorm = normalize((query || "").trim());
    const todas = Array.isArray(iglesias) ? iglesias : [];
    const enRango = Array.isArray(iglesiasEnRango) ? iglesiasEnRango : [];

    // Actividades puntuales cargadas bajo demanda cuando el buscador está
    // abierto. Las actividades viven en /iglesias/{id}/actividades y sólo
    // se pueden listar pasándolas por una suscripción que abre listeners
    // por iglesia. Para que la búsqueda de actividades sea GLOBAL, la
    // suscribimos aquí contra `todas`, no contra `enRango`.
    const [actividadesGlobales, setActividadesGlobales] = useState([]);
    useEffect(() => {
      if (!abierto) return;
      if (!todas.length) return;
      if (typeof window.suscribirActividadesDeIglesias !== "function") return;
      const unsub = window.suscribirActividadesDeIglesias(todas, function (arr) {
        setActividadesGlobales(Array.isArray(arr) ? arr : []);
      });
      return function () { if (typeof unsub === "function") unsub(); };
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [abierto, todas.length]);

    const parsed = useMemo(() => qNorm ? parseQuery(qNorm) : { dia: null, tipo: null, texto: "" }, [qNorm]);

    // Resultados iglesias (globales): match por nombre.
    const resIglesias = useMemo(() => {
      if (!parsed.texto) return [];
      const t = parsed.texto;
      return todas
        .filter((ig) => ig && normalize(ig.nombre).includes(t))
        .slice(0, 20);
    }, [todas, parsed.texto]);

    // Resultados pastores (globales): match por creado_por_nombre. Una
    // fila por iglesia (si un pastor tiene varias, aparecen separadas).
    const resPastores = useMemo(() => {
      if (!parsed.texto) return [];
      const t = parsed.texto;
      return todas
        .filter((ig) => {
          if (!ig) return false;
          const p = ig.creado_por_nombre || (ig.perfil && ig.perfil.creado_por_nombre) || "";
          if (!p) return false;
          // Excluir si el match ya viene por nombre de iglesia (evita doble fila).
          if (normalize(ig.nombre).includes(t)) return false;
          return normalize(p).includes(t);
        })
        .slice(0, 15);
    }, [todas, parsed.texto]);

    // Resultados actividades puntuales (globales): match por título/descripción.
    const resActividades = useMemo(() => {
      if (!parsed.texto) return [];
      const t = parsed.texto;
      const arr = actividadesGlobales
        .filter((a) => a && (normalize(a.titulo).includes(t) || normalize(a.descripcion || "").includes(t)))
        .sort((a, b) => (a.fecha_inicio || 0) - (b.fecha_inicio || 0));
      return arr.slice(0, 20);
    }, [actividadesGlobales, parsed.texto]);

    // Resultados programa (horarios): LIMITADOS al alcance del user.
    // Se activan si la query tiene filtro semántico (día o tipo) o si el
    // texto matchea algún título de slot dentro del rango.
    const resPrograma = useMemo(() => {
      const { dia, tipo, texto } = parsed;
      if (dia == null && tipo == null && !texto) return [];
      const now = new Date();
      const out = [];
      enRango.forEach((ig) => {
        const slots = (ig.horario || []).filter((s) => s && s.activo !== false);
        slots.forEach((s) => {
          if (dia != null && diaIdx(s.dia) !== dia) return;
          if (tipo != null && (s.tipo || "").toLowerCase() !== tipo) return;
          if (texto) {
            const ok = normalize(s.titulo || "").includes(texto)
                    || normalize(TIPOS_LABEL[s.tipo] || "").includes(texto);
            if (!ok) return;
          }
          const m = minutosParaEmpezar(s, now);
          out.push({ ig, slot: s, m });
        });
      });
      out.sort((a, b) => (a.m == null ? Infinity : a.m) - (b.m == null ? Infinity : b.m));
      return out.slice(0, 30);
    }, [enRango, parsed]);

    if (!abierto) return null;
    if (typeof document === "undefined") return null;

    const pick = (ig) => {
      if (onSelect) onSelect(ig);
      if (onClose) onClose();
    };

    const sugerencias = [
      { label: "Hoy",     q: "hoy" },
      { label: "Mañana",  q: "mañana" },
      { label: "Oración", q: "oración" },
      { label: "Jóvenes", q: "jóvenes" },
      { label: "Culto",   q: "culto" },
    ];

    const totalResultados =
      resIglesias.length + resPastores.length + resActividades.length + resPrograma.length;

    const content = (
      <div
        style={{
          position: "fixed",
          top: 64, left: "50%", bottom: 0,
          transform: "translateX(-50%)",
          width: "100%", maxWidth: 430,
          background: dark ? "#0F0F10" : "#FFFFFF",
          zIndex: 40,
          overflowY: "auto",
          WebkitOverflowScrolling: "touch",
          paddingBottom: "calc(72px + env(safe-area-inset-bottom, 0px))",
        }}
      >
        {/* Estado vacío / ayuda inicial */}
        {!qNorm && (
          <div style={{ padding: "28px 20px 16px", color: dark ? "#9CA3AF" : "#6B7280" }}>
            <div style={{ textAlign: "center", marginBottom: 18 }}>
              <div style={{ fontSize: 44, marginBottom: 10 }}>🔎</div>
              <div style={{ fontSize: 14, fontWeight: 800, color: dark ? "#F0F0F0" : "#111827" }}>
                Buscar en CultoRD
              </div>
              <div style={{ fontSize: 12, fontWeight: 500, marginTop: 4, lineHeight: 1.5 }}>
                Busca iglesias, pastores o actividades.<br/>
                Para el programa (culto, oración, jóvenes…) sólo se muestran las que están en tu alcance.
              </div>
            </div>
            <div style={{
              fontSize: 10, fontWeight: 900,
              letterSpacing: "0.15em", textTransform: "uppercase",
              color: dark ? "#9CA3AF" : "#6B7280",
              marginBottom: 8, padding: "0 2px",
            }}>
              Sugerencias
            </div>
            <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
              {sugerencias.map((c) => (
                <button
                  key={c.q}
                  type="button"
                  onClick={() => { if (typeof onSetQuery === "function") onSetQuery(c.q); }}
                  style={{
                    padding: "8px 14px",
                    borderRadius: 999,
                    border: "1px solid " + (dark ? "#2A2A2A" : "#E5E7EB"),
                    background: dark ? "#1A1A1A" : "#F9FAFB",
                    color: dark ? "#F0F0F0" : "#111827",
                    fontSize: 13, fontWeight: 700,
                    cursor: "pointer",
                    fontFamily: "inherit",
                  }}
                >
                  {c.label}
                </button>
              ))}
            </div>
          </div>
        )}

        {/* Empty state con query */}
        {qNorm && totalResultados === 0 && (
          <div style={{
            padding: "40px 24px", textAlign: "center",
            color: dark ? "#9CA3AF" : "#6B7280",
          }}>
            <div style={{ fontSize: 44, marginBottom: 10 }}>∅</div>
            <div style={{ fontSize: 14, fontWeight: 800 }}>Sin resultados</div>
            <div style={{ fontSize: 12, fontWeight: 500, marginTop: 4, lineHeight: 1.5 }}>
              Prueba con el nombre de una iglesia, de un pastor, o un día/tipo de culto.
            </div>
          </div>
        )}

        {/* Resultados agrupados */}
        {qNorm && totalResultados > 0 && (
          <div style={{ padding: "8px 0" }}>

            <Seccion titulo="Iglesias" count={resIglesias.length} dark={dark}>
              {resIglesias.map((ig) => (
                <Row
                  key={"ig_" + ig.id}
                  imagen={ig.imagen_url}
                  emoji="🏠"
                  titulo={ig.nombre}
                  subtitulo={ig.direccion_texto || (ig.categoria_fuente || "")}
                  noReclamada={ig.reclamada === false}
                  dark={dark}
                  onClick={() => pick(ig)}
                />
              ))}
            </Seccion>

            <Seccion titulo="Pastores" count={resPastores.length} dark={dark}>
              {resPastores.map((ig) => {
                const p = ig.creado_por_nombre || (ig.perfil && ig.perfil.creado_por_nombre) || "";
                return (
                  <Row
                    key={"pas_" + ig.id}
                    emoji="👤"
                    titulo={p}
                    subtitulo={"Pastor · " + (ig.nombre || "")}
                    dark={dark}
                    onClick={() => pick(ig)}
                  />
                );
              })}
            </Seccion>

            <Seccion titulo="Actividades" count={resActividades.length} dark={dark}>
              {resActividades.map((a) => {
                const meta = a.iglesia || {};
                const ig = todas.find((x) => x && x.id === meta.id) || null;
                const subtitulo = [
                  meta.nombre || (ig ? ig.nombre : ""),
                  fmtFechaCorta(a.fecha_inicio),
                  a.hora ? fmtHora12(a.hora) : "",
                ].filter(Boolean).join(" · ");
                return (
                  <Row
                    key={"act_" + (meta.id || "?") + "_" + a.id}
                    emoji={EMOJI_ACTIVIDAD[a.tipo] || "✨"}
                    imagen={a.imagen_url}
                    titulo={a.titulo}
                    subtitulo={subtitulo}
                    dark={dark}
                    onClick={() => ig ? pick(ig) : null}
                  />
                );
              })}
            </Seccion>

            <Seccion titulo="Programa (en tu alcance)" count={resPrograma.length} dark={dark}>
              {resPrograma.map(({ ig, slot, m }, i) => {
                const dI = diaIdx(slot.dia);
                const cuando = (dI >= 0 ? DIAS_ABREV[dI] : "") + " · " + fmtHora12(slot.hora_inicio);
                const hoy = (typeof m === "number" && m >= -60 && m <= 0) ? " · EN VIVO" : "";
                return (
                  <Row
                    key={"hor_" + ig.id + "_" + i}
                    emoji={TIPOS_EMOJI[slot.tipo] || "📅"}
                    titulo={slot.titulo || (TIPOS_LABEL[slot.tipo] || "Culto")}
                    subtitulo={(ig.nombre || "") + " · " + cuando + hoy}
                    dark={dark}
                    onClick={() => pick(ig)}
                  />
                );
              })}
            </Seccion>

          </div>
        )}
      </div>
    );

    return ReactDOM.createPortal(content, document.body);
  }

  window.Buscador = Buscador;
})();
