// Valdebebas Life — piezas compartidas
const { useState, useEffect, useRef, useMemo } = React;

function useStored(key, init) {
  if (window.VBStore && VBStore.shared(key)) return VBStore.use(key); // estado compartido en Supabase
  const [v, setV] = useState(() => {
    try { const s = localStorage.getItem(key); return s ? JSON.parse(s) : (typeof init === "function" ? init() : init); }
    catch (e) { return typeof init === "function" ? init() : init; }
  });
  useEffect(() => { try { localStorage.setItem(key, JSON.stringify(v)); } catch (e) {} }, [key, v]);
  return [v, setV];
}

function Ic({ n, fill, style, className = "" }) {
  return <span className={"ms " + (fill ? "fill " : "") + className} style={style} aria-hidden="true">{n}</span>;
}

function ago(ts) {
  const d = (Date.now() - ts) / 1000;
  if (d < 3600) return "hace " + Math.max(1, Math.round(d / 60)) + " min";
  if (d < 86400) return "hace " + Math.round(d / 3600) + " h";
  const days = Math.round(d / 86400);
  if (days === 1) return "ayer";
  if (days < 30) return "hace " + days + " días";
  return new Date(ts).toLocaleDateString("es-ES", { day: "numeric", month: "short" });
}
function fdate(ts) { return new Date(ts).toLocaleDateString("es-ES", { day: "numeric", month: "long", year: "numeric" }); }
function initials(name) { return (name || "?").split(" ").filter(Boolean).slice(0, 2).map(w => w[0]).join("").toUpperCase(); }

function Modal({ open, onClose, title, sub, children, footer, wide }) {
  useEffect(() => {
    if (!open) return;
    const k = e => e.key === "Escape" && onClose();
    window.addEventListener("keydown", k);
    document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", k); document.body.style.overflow = ""; };
  }, [open]);
  if (!open) return null;
  return (
    <div className="mb" onMouseDown={onClose}>
      <div className={"md" + (wide ? " wide" : "")} role="dialog" aria-modal="true" onMouseDown={e => e.stopPropagation()}>
        <button className="md-x" onClick={onClose} aria-label="Cerrar"><Ic n="close" /></button>
        <div className="md-h"><h3>{title}</h3>{sub && <p>{sub}</p>}</div>
        <div className="md-b">{children}</div>
        {footer && <div className="md-f">{footer}</div>}
      </div>
    </div>
  );
}

function Brand({ onClick }) {
  return (
    <button className="brand" onClick={onClick} aria-label="Valdebebas Life, inicio">
      <img className="brand-logo" src="brand/mark.png" alt="" width="48" height="30" />
      <span><span className="brand-name">Valdebebas <b>Life</b></span><span className="brand-sub">Vive Valdebebas</span></span>
    </button>
  );
}

const VB_NAV = [
  { id: "home", label: "Inicio", icon: "home" },
  { id: "servicios", label: "Servicios", icon: "handyman" },
  { id: "mejor", label: "Locales", icon: "storefront" },
  { id: "tablon", label: "Tablón Vecinal", short: "Tablón", icon: "forum" },
  { id: "comunidad", label: "Conoce vecinos", short: "Vecinos", icon: "diversity_3" },
  { id: "contacto", label: "Contacto", icon: "mail" },
];

const isOn = (n, page) => (n.match || [n.id]).includes(page);

function Header({ page, go, user, onLogin, onRegister, onLogout, onBaro, onDelete, onInvite }) {
  const [open, setOpen] = useState(false);
  const ref = useRef();
  useEffect(() => {
    const h = e => ref.current && !ref.current.contains(e.target) && setOpen(false);
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, []);
  return (
    <header className="hdr">
      <div className="stripe"><i></i><i></i><i></i></div>
      <div className="wrap hdr-in">
        <Brand onClick={() => go("home")} />
        <nav className="nav" aria-label="Principal">
          {VB_NAV.map(n => <button key={n.id} className={isOn(n, page) ? "on" : ""} onClick={() => go(n.id)}>{n.label}</button>)}
        </nav>
        <div className="hdr-actions">
          {!user && <><button className="btn sm ghost hdr-login" onClick={onLogin}><Ic n="login" /><span>Entrar</span></button><button className="btn sm hdr-reg" onClick={onRegister}><Ic n="person_add" /><span className="l">Crear cuenta</span><span className="s">Únete</span></button></>}
          {user && (
            <div style={{ position: "relative" }} ref={ref}>
              <button className="user-chip" onClick={() => setOpen(o => !o)}>
                <span className={"avatar" + (user.role === "admin" ? " admin" : "")}>{initials(user.name)}</span>
                <span className="nm">{user.name.split(" ")[0]}</span><Ic n="expand_more" />
              </button>
              {open && (
                <div className="menu">
                  <div className="menu-h"><b>{user.name}</b><small>{user.email}</small>
                    <div style={{ marginTop: 8 }}>{user.role === "admin" ? <span className="badge admin"><Ic n="shield_person" />Administrador</span> : <span className="badge"><Ic n="verified" fill />Vecino</span>}</div>
                  </div>
                  {user.role === "admin" && <button id="menu-admin-panel" onClick={() => { setOpen(false); go("admin"); }}><Ic n="dashboard" />Panel de administración</button>}
                  {user.role !== "admin" && <button onClick={() => { setOpen(false); onBaro(); }}><Ic n="monitoring" />Mi barómetro</button>}
                  {user.role !== "admin" && <button onClick={() => { setOpen(false); onInvite(); }}><Ic n="person_add" />Invitar a vecinos</button>}
                  <button onClick={() => { setOpen(false); go("tablon"); }}><Ic n="forum" />Mis anuncios en el tablón</button>
                  <button onClick={() => { setOpen(false); onLogout(); }}><Ic n="logout" />Cerrar sesión</button>
                  {user.role !== "admin" && <button className="menu-danger" onClick={() => { setOpen(false); onDelete(); }}><Ic n="person_remove" />Borrar mi cuenta</button>}
                </div>
              )}
            </div>
          )}
        </div>
      </div>
    </header>
  );
}

function MobileNav({ page, go }) {
  return (
    <nav className="mnav" aria-label="Navegación móvil">
      {VB_NAV.map(n => <button key={n.id} className={isOn(n, page) ? "on" : ""} onClick={() => go(n.id)}><Ic n={n.icon} fill={isOn(n, page)} />{n.short || n.label}</button>)}
    </nav>
  );
}

const VB_LEGAL = {
  legal: { t: "Aviso legal", b: "Titular: Asociación Española TWC\nNIF: G93978617\nDomicilio social: Avda. Francisco Javier Sáenz de Oíza, 72, 28055 Madrid\nInscrita en el Registro Nacional de Asociaciones (Ministerio del Interior), Sección 1ª, Número Nacional 633896, con fecha 18/08/2026.\nContacto: valdebebaslife@gmail.com\n\nValdebebas Life es una plataforma vecinal independiente impulsada por la Asociación Española TWC. No está vinculada a la Asociación de Vecinos de Valdebebas, a la Junta de Compensación de Valdebebas, a la Entidad Urbanística de Conservación ni al Ayuntamiento de Madrid.\n\nValdebebas Life es una plataforma informativa de recomendación vecinal. La Asociación Española TWC no actúa como intermediaria ni asume ninguna responsabilidad sobre la contratación, calidad, ejecución, tarifas o resultados de los servicios prestados por los profesionales y comercios incluidos en el directorio. La relación es siempre directa entre el vecino y el profesional o comercio.\n\nLos contenidos publicados por vecinos (tablón, propuestas, recomendaciones) son responsabilidad de sus autores. Valdebebas Life puede retirar cualquier contenido que incumpla las normas." },
  privacidad: { t: "Política de privacidad", b: "1. Responsable\nAsociación Española TWC (NIF G93978617). Contacto: valdebebaslife@gmail.com.\n\n2. Qué datos tratamos\nNombre (o nombre e inicial del apellido) y email de tu cuenta; lo que publiques voluntariamente (anuncios y sus fotos o PDF adjuntos, respuestas, propuestas, quedadas, votos y recomendaciones); tus respuestas al barómetro de bienestar; y los datos que nos envíes en los formularios de contacto, recomendación o podcast.\n\n3. Para qué\na) Gestionar tu cuenta y permitirte publicar, responder, proponer, apuntarte y votar.\nb) Responder a tus mensajes y solicitudes.\nc) Barómetro de bienestar: un cuestionario breve y voluntario al registrarte y cada 3 meses, para que veas tu evolución. Tus respuestas solo las ves tú.\nd) Solo si lo aceptas expresamente (opción voluntaria del barómetro, que puedes desactivar en «Mi barómetro»): elaborar estudios sobre bienestar y vida comunitaria y la memoria de actividades de la Asociación, siempre con datos anonimizados y agregados, de forma que nadie pueda ser identificado.\n\n4. Base legal\nTu consentimiento (art. 6.1.a RGPD). Puedes retirarlo en cualquier momento escribiendo a valdebebaslife@gmail.com o borrando tu cuenta desde el menú de usuario, sin que afecte a lo tratado antes.\n\n5. Edad mínima\nEl registro está reservado a mayores de 18 años.\n\n6. Cuánto tiempo guardamos los datos\nLos datos de tu cuenta, mientras esté activa. Las cuentas sin actividad durante 2 años se eliminan. Los anuncios del tablón y las quedadas desaparecen al caducar. Los mensajes recibidos por formulario se conservan como máximo 1 año. Los datos anonimizados no permiten identificarte y pueden conservarse con fines estadísticos.\n\n7. Quién más trata tus datos (encargados del tratamiento)\nIONOS (alojamiento web, servidores en la Unión Europea); FormSubmit (envío de formularios por email, con sede en EE. UU.); y Supabase (base de datos y cuentas, servidores en Frankfurt, UE). No vendemos ni cedemos tus datos a terceros.\n\n8. Transferencias fuera de la UE\nEl uso de FormSubmit implica que los datos de los formularios pueden tratarse en EE. UU., bajo las garantías previstas en el RGPD (cláusulas contractuales tipo o Marco de Privacidad de Datos UE-EE. UU.).\n\n9. Tus derechos\nAcceso, rectificación, supresión, oposición, limitación y portabilidad, escribiendo a valdebebaslife@gmail.com. Si consideras que no hemos atendido bien tu solicitud, puedes reclamar ante la Agencia Española de Protección de Datos (aepd.es)." },
  cookies: { t: "Política de cookies", b: "Valdebebas Life no usa cookies de publicidad ni de analítica y no te rastrea entre webs.\n\nSolo usamos el almacenamiento local de tu navegador (localStorage), que es técnicamente necesario para que la web funcione: mantener tu sesión, recordar a qué círculos te has unido, tus votos y tus preferencias (por ejemplo, haber cerrado el aviso para instalar la app). Estos datos se quedan en tu dispositivo y puedes borrarlos desde los ajustes de tu navegador. Al ser técnicamente necesarios, no requieren consentimiento.\n\nLas tipografías e iconos están alojados en nuestro propio servidor, así que no se envía información a terceros al cargarlos.\n\nSi en el futuro incorporamos cookies de analítica o publicidad, te pediremos permiso antes de activarlas." },
  condiciones: { t: "Condiciones de uso", b: "1. Objeto\nValdebebas Life es una plataforma informativa de recomendación vecinal de la Asociación Española TWC (NIF G93978617). Consultarla es libre y gratuito; registrarse es necesario para publicar, proponer, apuntarse y votar.\n\n2. Registro\nPara crear una cuenta debes ser mayor de 18 años y vivir o trabajar en Valdebebas. Te comprometes a dar datos veraces y a no compartir tu cuenta.\n\n3. Qué puedes publicar\nAnuncios, respuestas, propuestas, quedadas y recomendaciones relacionadas con la vida del barrio, de forma respetuosa y veraz.\n\n4. Qué no está permitido\nContenido ofensivo, discriminatorio o ilegal; spam o publicidad encubierta; datos personales de terceros sin su permiso; suplantar a otra persona; y anuncios de empleo o servicios que incumplan la ley.\n\n5. Responsabilidad\nCada usuario es responsable de lo que publica. La Asociación no actúa como intermediaria ni asume responsabilidad sobre la contratación, calidad, ejecución, tarifas o resultados de los servicios de los profesionales y comercios del directorio, ni sobre las quedadas organizadas entre vecinos.\n\n6. Moderación\nPodemos retirar contenidos que incumplan estas condiciones o las normas del tablón y suspender o cerrar cuentas que las incumplan de forma reiterada.\n\n7. Ley aplicable\nEstas condiciones se rigen por la ley española. Para cualquier controversia, los juzgados y tribunales de Madrid, salvo que la ley reconozca al usuario el derecho a acudir a los de su domicilio." },
  normas: { t: "Normas del tablón", b: "1. Un anuncio por necesidad; nada de spam.\n2. Respeto siempre. Se eliminan mensajes ofensivos.\n3. No publiques datos personales de terceros, ni fotos de personas o documentos sin su permiso.\n4. Si algo no cumple las normas, repórtalo y lo revisamos." },
  como: { t: "Cómo funcionan las recomendaciones", b: "Cualquier profesional o local puede aparecer: lo propone un vecino o nos escribe el propio negocio, y revisamos cada caso antes de añadirlo. Aparecer es gratis.\n\nUna vez dentro, el orden lo deciden solo los vecinos: en Servicios, por número de recomendaciones; en Locales, por votos (uno por vecino y categoría)." },
};

function Footer({ go, openLegal }) {
  return (
    <footer className="ftr">
      <div className="wrap">
        <div className="ftr-in">
          <div>
            <Brand onClick={() => go("home")} />
            <p className="ftr-note">Guía independiente de servicios y comunidad de Valdebebas (Hortaleza, Madrid). Impulsada por la <b>Asociación Española TWC</b> · NIF G93978617.</p>
            <p className="ftr-note" style={{ marginTop: 8 }}>Plataforma informativa de recomendación vecinal: no intermediamos ni respondemos de la contratación, calidad, tarifas o resultados de los servicios del directorio.</p>
            <p className="ftr-note" style={{ marginTop: 8 }}>No es un canal oficial de la Asociación de Vecinos de Valdebebas, la Junta de Compensación ni el Ayuntamiento de Madrid.</p>
          </div>
          <div><h4>Explorar</h4><ul>{[["servicios", "Servicios"], ["mejor", "Locales del barrio"], ["tablon", "Tablón Vecinal"], ["comunidad", "Conoce vecinos"], ["contacto", "Contacto"]].map(([id, l]) => <li key={id}><button className="lnk" onClick={() => go(id)}>{l}</button></li>)}</ul></div>
          <div><h4>Comunidad</h4><ul>
            <li><button className="lnk" onClick={() => openLegal("como")}>Cómo funcionan las recomendaciones</button></li>
            <li><button className="lnk" onClick={() => openLegal("normas")}>Normas del tablón</button></li>
            <li><button className="lnk" onClick={() => go("contacto")}>¿Tienes un negocio? Aparece en la web</button></li>
            <li><button className="lnk" onClick={() => go("contacto")}>Enviar una sugerencia</button></li>
            <li><a href="https://www.instagram.com/valdebebaslife/" target="_blank" rel="noopener">Instagram @ValdebebasLife</a></li>
            <li><a href="mailto:valdebebaslife@gmail.com">valdebebaslife@gmail.com</a></li>
          </ul></div>
        </div>
        <div className="ftr-b"><span>© 2026 Valdebebas Life · Asociación Española TWC</span>
          <span style={{ display: "flex", gap: "8px 16px", flexWrap: "wrap" }}><button className="lnk" onClick={() => openLegal("legal")}>Aviso legal</button><button className="lnk" onClick={() => openLegal("privacidad")}>Política de privacidad</button><button className="lnk" onClick={() => openLegal("cookies")}>Cookies</button><button className="lnk" onClick={() => openLegal("condiciones")}>Condiciones de uso</button></span>
        </div>
      </div>
    </footer>
  );
}

function vbInviteCode(name, email) {
  const base = (name || "VECINO").split(" ")[0].normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-zA-Z]/g, "").toUpperCase().slice(0, 10) || "VECINO";
  let h = 0; for (const ch of email) h = (h * 31 + ch.charCodeAt(0)) % 1000;
  return "VALDE-" + base + String(h).padStart(3, "0");
}

function InviteModal({ open, onClose, user, users, flash }) {
  if (!open || !user) return null;
  const code = user.code || vbInviteCode(user.name, user.email);
  const link = location.origin + location.pathname + "?invita=" + code;
  const n = users.filter(u => u.invitedBy === user.email).length;
  const msg = "Me he unido a Valdebebas Life, la web del barrio para encontrar profesionales de confianza, planes y vecinos. Únete con mi código " + code + ": " + link;
  const copy = () => { try { navigator.clipboard.writeText(link); flash("Enlace copiado"); } catch (e) {} };
  return (
    <Modal open onClose={onClose} title="Invita a tus vecinos" sub="Cuantos más seamos, más planes salen. Comparte tu enlace en tus grupos del barrio."
      footer={<button className="btn" onClick={onClose}>Listo</button>}>
      <div className="invite-code" id="invite-code"><small>Tu código personal</small><b>{code}</b></div>
      <div className="invite-btns">
        <button id="invite-copy-btn" className="btn ghost" onClick={copy}><Ic n="link" />Copiar enlace</button>
        <a id="invite-whatsapp-btn" className="btn ghost" href={"https://wa.me/?text=" + encodeURIComponent(msg)} target="_blank" rel="noopener"><Ic n="chat" />WhatsApp</a>
        <a id="invite-telegram-btn" className="btn ghost" href={"https://t.me/share/url?url=" + encodeURIComponent(link) + "&text=" + encodeURIComponent(msg)} target="_blank" rel="noopener"><Ic n="send" />Telegram</a>
      </div>
      <p className="baro-note">{n ? "Has traído a " + n + (n === 1 ? " vecino" : " vecinos") + ". ¡Gracias por hacer barrio!" : "Sin rankings ni competiciones: cada invitación es un vecino más acompañado."}</p>
    </Modal>
  );
}

function Toast({ msg }) {
  if (!msg) return null;
  return <div className="toast"><Ic n="check_circle" fill />{msg}</div>;
}

Object.assign(window, { InviteModal, vbInviteCode, useStored, Ic, ago, fdate, initials, Modal, Brand, Header, MobileNav, Footer, Toast, VB_LEGAL, VB_NAV });
