/* global React, CrownMark */
const { useState, useEffect, useRef, useCallback } = React;

// =============================================================================
// SUPABASE CLIENT
// =============================================================================

const SUPABASE_URL = "https://okdickifdjxqbezxbkhd.supabase.co";
const SUPABASE_KEY = "sb_publishable_qGLmJK_HkbI77zkaELoqwQ_ja0F-XgQ";

const supa = (window.supabase && window.supabase.createClient)
  ? window.supabase.createClient(SUPABASE_URL, SUPABASE_KEY, {
      auth: { persistSession: true, autoRefreshToken: true, storageKey: "rdc-auth" }
    })
  : null;

if (!supa) {
  console.warn("Supabase client no se pudo inicializar. Revisar que supabase-js esté cargado.");
}

// =============================================================================
// STORE — Supabase-backed reactive hook
// =============================================================================

const STORE_KEYS = { blog: "blog", videos: "videos", fotos: "fotos" };

// Schema mappers (DB usa snake_case; el código usa camelCase para videos.youtube_id)
const MAPPERS = {
  blog: { fromDb: r => r, toDb: r => r },
  videos: {
    fromDb: r => ({ ...r, youtubeId: r.youtube_id }),
    toDb: r => { const { youtubeId, ...rest } = r; return { ...rest, youtube_id: youtubeId }; },
  },
  fotos: { fromDb: r => r, toDb: r => r },
};

const ORDER_BY = { blog: "date", videos: "created_at", fotos: "created_at" };

// Defaults — usados como semilla inicial y mientras Supabase responde
const DEFAULT_BLOG = [
  { title: "Vuelve el torneo 3x3 a La Pintana", excerpt: "Después de dos años, volvemos a la cancha donde todo empezó.", body: "Inscripciones abiertas hasta el 30 de junio.", cover: "assets/court-mockup.jpeg", featured: true, date: "2026-05-15", category: "Torneos" },
  { title: "Drop 02 — Camo Pack disponible", excerpt: "La estampa más icónica del street chileno.", body: "Edición limitada de 200 unidades.", cover: "assets/shorts-camo.jpeg", featured: true, date: "2026-05-08", category: "Merch" },
  { title: "Clínica gratuita en Cerro Navia", excerpt: "Joaco 'Sniper' Núñez dicta una clínica para sub-15.", body: "Cupo limitado a 30 participantes.", cover: "assets/squad-sunset.jpeg", featured: false, date: "2026-04-28", category: "Comunidad" },
];
const DEFAULT_VIDEOS = [
  { youtubeId: "dQw4w9WgXcQ", thumb: "assets/court-mockup.jpeg", title: "Mixtape Verano 2024", duration: "5:21", size: "wide" },
  { youtubeId: "dQw4w9WgXcQ", thumb: "assets/squad-sunset.jpeg", title: "Torneo La Pintana", duration: "3:42", size: "" },
];
const DEFAULT_FOTOS = [
  { src: "assets/court-mockup.jpeg", title: "La Cancha", subtitle: "Mockup oficial", size: "wide" },
  { src: "assets/squad-sunset.jpeg", title: "El Equipo", subtitle: "Documental", size: "" },
  { src: "assets/king-painting.jpeg", title: "El Rey", subtitle: "Editorial", size: "" },
  { src: "assets/king-blue-shorts.jpeg", title: "Crossover", subtitle: "Ilustración", size: "" },
  { src: "assets/orange-stance.jpeg", title: "Defensa", subtitle: "Movimiento", size: "" },
];

const _initialData = {};

const useStore = (table, defaults) => {
  const [data, setData] = useState(() => _initialData[table] || defaults);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  const refresh = useCallback(async () => {
    if (!supa) { setLoading(false); return; }
    const { data: rows, error } = await supa
      .from(table)
      .select("*")
      .order(ORDER_BY[table], { ascending: false });
    if (error) { setError(error.message); setLoading(false); return; }
    const mapped = rows.map(MAPPERS[table].fromDb);
    _initialData[table] = mapped; // cache for next mount
    setData(mapped);
    setLoading(false);
  }, [table]);

  useEffect(() => {
    refresh();
    if (!supa) return;
    // Cross-instance refresh: cuando una instancia escribe, todas se enteran.
    const onLocalChange = (e) => {
      if (e.detail && e.detail.table === table) refresh();
    };
    window.addEventListener("rdc:supabase-change", onLocalChange);
    // Realtime via Supabase (si está habilitado en el proyecto).
    const channelName = `rt-${table}-${Math.random().toString(36).slice(2, 8)}`;
    const ch = supa.channel(channelName);
    ch.on("postgres_changes", { event: "*", schema: "public", table }, () => refresh());
    ch.subscribe();
    return () => {
      window.removeEventListener("rdc:supabase-change", onLocalChange);
      supa.removeChannel(ch);
    };
  }, [table, refresh]);

  const notify = () => window.dispatchEvent(new CustomEvent("rdc:supabase-change", { detail: { table } }));

  const add = useCallback(async (item) => {
    if (!supa) return null;
    const { id, created_at, ...rest } = item;
    const { data: row, error } = await supa.from(table).insert(MAPPERS[table].toDb(rest)).select().single();
    if (error) { alert("Error al crear: " + error.message); return null; }
    notify();
    return MAPPERS[table].fromDb(row);
  }, [table]);

  const update = useCallback(async (id, patch) => {
    if (!supa) return null;
    const payload = MAPPERS[table].toDb(patch);
    delete payload.id; delete payload.created_at;
    const { data: row, error } = await supa.from(table).update(payload).eq("id", id).select().single();
    if (error) { alert("Error al actualizar: " + error.message); return null; }
    notify();
    return MAPPERS[table].fromDb(row);
  }, [table]);

  const remove = useCallback(async (id) => {
    if (!supa) return;
    const { error } = await supa.from(table).delete().eq("id", id);
    if (error) alert("Error al eliminar: " + error.message);
    else notify();
  }, [table]);

  return [data, { add, update, remove, refresh, loading, error }];
};

// =============================================================================
// IMAGE UPLOAD — Supabase Storage
// =============================================================================

async function uploadImage(file) {
  if (!supa) { alert("Supabase no inicializado."); return null; }
  if (!file) return null;
  if (file.size > 5 * 1024 * 1024) { alert("La imagen supera 5MB."); return null; }
  const ext = (file.name.split(".").pop() || "jpg").toLowerCase();
  const path = `uploads/${Date.now()}-${Math.random().toString(36).slice(2, 8)}.${ext}`;
  const { error } = await supa.storage.from("media").upload(path, file, {
    cacheControl: "31536000",
    upsert: false,
    contentType: file.type || `image/${ext}`,
  });
  if (error) { alert("Error subiendo: " + error.message); return null; }
  const { data } = supa.storage.from("media").getPublicUrl(path);
  return data.publicUrl;
}

// =============================================================================
// PUBLIC — Novedades section
// =============================================================================

const formatDate = (iso) => {
  if (!iso) return "";
  const d = new Date(iso);
  if (isNaN(d.getTime())) return iso;
  const months = ["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"];
  return `${d.getDate()} ${months[d.getMonth()]} ${d.getFullYear()}`;
};

const Novedades = ({ onOpenPost }) => {
  const [posts] = useStore(STORE_KEYS.blog, DEFAULT_BLOG);
  const featured = posts.filter(p => p.featured).slice(0, 2);
  if (featured.length === 0) return null;

  return (
    <section id="novedades" data-screen-label="Novedades" className="relative py-16 md:py-24 bg-[#0A0807] overflow-hidden">
      <div className="max-w-[1440px] mx-auto px-6 md:px-10">
        <div className="flex flex-col md:flex-row md:items-end justify-between gap-6 mb-10">
          <div>
            <div className="text-[#FF6D0D] uppercase tracking-[0.3em] text-xs mb-4" style={{ fontFamily: "Inter, sans-serif" }}>
              ·  Novedades
            </div>
            <h2 style={{ fontFamily: "'Anton', sans-serif", fontSize: "clamp(40px, 6vw, 88px)", lineHeight: 0.92 }} className="text-white">
              LO ÚLTIMO<br /><span className="text-[#FF6D0D]">EN LA CALLE.</span>
            </h2>
          </div>
          <a href="#blog" className="text-white hover:text-[#FF6D0D] text-sm uppercase tracking-[0.2em] font-semibold flex items-center gap-2" style={{ fontFamily: "Inter, sans-serif" }}>
            Ver todas
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </a>
        </div>

        <div className="grid md:grid-cols-2 gap-4 md:gap-6">
          {featured.map((p, i) => (
            <article
              key={p.id || i}
              onClick={() => onOpenPost && onOpenPost(p)}
              className="group relative overflow-hidden bg-black border border-white/10 hover:border-[#FF6D0D]/60 transition-all cursor-pointer"
              style={{ animation: `fadeUp 0.6s ${i * 0.1}s both` }}>
              <div className="relative aspect-[16/10] overflow-hidden bg-black">
                <img src={p.cover} alt={p.title} className="absolute inset-0 w-full h-full object-contain transition-transform duration-700 group-hover:scale-105" />
                <div className="absolute inset-0 bg-gradient-to-t from-black/70 via-transparent to-transparent pointer-events-none" />
                <div className="absolute top-4 left-4 bg-[#FF6D0D] text-black text-[10px] uppercase tracking-[0.2em] font-bold px-3 py-1.5" style={{ fontFamily: "'Anton', sans-serif", letterSpacing: "0.18em" }}>
                  {p.category}
                </div>
              </div>
              <div className="p-6 md:p-8">
                <div className="flex items-center gap-3 text-white/40 text-[10px] uppercase tracking-[0.25em] mb-3" style={{ fontFamily: "Inter, sans-serif" }}>
                  <span>{formatDate(p.date)}</span>
                  <span className="w-1 h-1 rounded-full bg-[#FF6D0D]" />
                  <span>{Math.max(1, Math.ceil((p.body || "").length / 800))} min lectura</span>
                </div>
                <h3 className="text-white text-2xl md:text-3xl group-hover:text-[#FF6D0D] transition-colors" style={{ fontFamily: "'Anton', sans-serif", lineHeight: 1.05 }}>
                  {p.title}
                </h3>
                <p className="mt-4 text-white/65 text-base leading-relaxed" style={{ fontFamily: "Inter, sans-serif" }}>
                  {p.excerpt}
                </p>
                <div className="mt-6 inline-flex items-center gap-2 text-[#FF6D0D] text-xs uppercase tracking-[0.2em] font-semibold" style={{ fontFamily: "Inter, sans-serif" }}>
                  Leer nota
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
                </div>
              </div>
            </article>
          ))}
        </div>
      </div>
    </section>
  );
};

const BlogReader = ({ post, onClose }) => {
  if (!post) return null;
  return (
    <div onClick={onClose} className="fixed inset-0 z-[200] bg-black/90 backdrop-blur-md flex items-start justify-center p-4 overflow-y-auto" style={{ animation: "fadeIn 0.25s" }}>
      <article onClick={e => e.stopPropagation()} className="relative bg-[#0A0807] border border-white/10 w-full max-w-3xl my-8" style={{ animation: "pop 0.4s cubic-bezier(.34,1.56,.64,1)" }}>
        <button onClick={onClose} className="absolute top-4 right-4 z-10 w-10 h-10 bg-black/70 backdrop-blur-sm text-white flex items-center justify-center hover:bg-[#FF6D0D] hover:text-black transition-colors" aria-label="Cerrar">
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M6 6l12 12M18 6L6 18"/></svg>
        </button>
        <div className="relative aspect-[16/9] overflow-hidden bg-black">
          <img src={post.cover} alt={post.title} className="absolute inset-0 w-full h-full object-contain" />
          <div className="absolute inset-0 bg-gradient-to-t from-[#0A0807] via-transparent to-transparent pointer-events-none" />
        </div>
        <div className="p-8 md:p-12">
          <div className="flex items-center gap-3 mb-4">
            <span className="bg-[#FF6D0D] text-black text-[10px] uppercase tracking-[0.2em] font-bold px-3 py-1" style={{ fontFamily: "'Anton', sans-serif" }}>{post.category}</span>
            <span className="text-white/40 text-xs uppercase tracking-[0.25em]" style={{ fontFamily: "Inter, sans-serif" }}>{formatDate(post.date)}</span>
          </div>
          <h1 className="text-white mb-6" style={{ fontFamily: "'Anton', sans-serif", fontSize: "clamp(32px, 5vw, 56px)", lineHeight: 1 }}>
            {post.title}
          </h1>
          <p className="text-white/80 text-lg leading-relaxed mb-6" style={{ fontFamily: "Inter, sans-serif" }}>
            {post.excerpt}
          </p>
          <div className="text-white/75 text-base leading-relaxed whitespace-pre-wrap" style={{ fontFamily: "Inter, sans-serif" }}>
            {post.body}
          </div>
        </div>
      </article>
    </div>
  );
};

// =============================================================================
// ADMIN — Login (Supabase Auth) + Panel
// =============================================================================

const AdminGate = () => {
  const [open, setOpen] = useState(false);
  const [session, setSession] = useState(null);
  const [sessionReady, setSessionReady] = useState(false);

  useEffect(() => {
    if (!supa) { setSessionReady(true); return; }
    supa.auth.getSession().then(({ data }) => { setSession(data.session); setSessionReady(true); });
    const { data: sub } = supa.auth.onAuthStateChange((_e, s) => setSession(s));
    return () => sub.subscription.unsubscribe();
  }, []);

  useEffect(() => {
    const check = () => { if (window.location.hash === "#admin") setOpen(true); };
    check();
    window.addEventListener("hashchange", check);
    const onTrigger = () => setOpen(true);
    window.addEventListener("rdc:open-admin", onTrigger);
    return () => {
      window.removeEventListener("hashchange", check);
      window.removeEventListener("rdc:open-admin", onTrigger);
    };
  }, []);

  const close = () => {
    setOpen(false);
    if (window.location.hash === "#admin") {
      history.replaceState(null, "", window.location.pathname + window.location.search);
    }
  };

  if (!open) return null;
  if (!sessionReady) return null;
  if (!session) return <AdminLogin onClose={close} />;
  return <AdminPanel onClose={close} onLogout={async () => { await supa.auth.signOut(); }} />;
};

const AdminLogin = ({ onClose }) => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [err, setErr] = useState("");
  const [busy, setBusy] = useState(false);

  const submit = async (e) => {
    e.preventDefault();
    if (!supa) { setErr("Supabase no está conectado."); return; }
    setBusy(true); setErr("");
    const { error } = await supa.auth.signInWithPassword({ email: email.trim(), password });
    setBusy(false);
    if (error) { setErr(error.message); return; }
    // session listener triggers re-render
  };

  return (
    <div className="fixed inset-0 z-[300] bg-black/95 backdrop-blur-md flex items-center justify-center p-4" style={{ animation: "fadeIn 0.25s" }}>
      <form onSubmit={submit} className="relative bg-[#0A0807] border border-white/10 w-full max-w-md p-8 md:p-10" style={{ animation: "pop 0.4s cubic-bezier(.34,1.56,.64,1)" }}>
        <button type="button" onClick={onClose} className="absolute top-4 right-4 text-white/50 hover:text-white p-2" aria-label="Cerrar">
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M6 6l12 12M18 6L6 18"/></svg>
        </button>
        <div className="flex justify-center mb-4"><CrownMark size={56} /></div>
        <h2 className="text-white text-center" style={{ fontFamily: "'Anton', sans-serif", fontSize: 36, lineHeight: 1 }}>
          PANEL <span className="text-[#FF6D0D]">ADMIN</span>
        </h2>
        <p className="text-white/50 text-sm text-center mt-2" style={{ fontFamily: "Inter, sans-serif" }}>
          Acceso para el equipo de Reyes.
        </p>
        <div className="mt-8 space-y-5">
          <div>
            <label className="block text-white/60 text-[10px] uppercase tracking-[0.25em] mb-2" style={{ fontFamily: "Inter, sans-serif" }}>Email</label>
            <input
              autoFocus type="email" required
              value={email} onChange={e => { setEmail(e.target.value); setErr(""); }}
              className="w-full bg-transparent border-b-2 border-white/20 focus:border-[#FF6D0D] outline-none py-3 text-white text-base"
              style={{ fontFamily: "Inter, sans-serif" }} />
          </div>
          <div>
            <label className="block text-white/60 text-[10px] uppercase tracking-[0.25em] mb-2" style={{ fontFamily: "Inter, sans-serif" }}>Contraseña</label>
            <input
              type="password" required
              value={password} onChange={e => { setPassword(e.target.value); setErr(""); }}
              className="w-full bg-transparent border-b-2 border-white/20 focus:border-[#FF6D0D] outline-none py-3 text-white text-base"
              style={{ fontFamily: "Inter, sans-serif" }} />
          </div>
          {err && <div className="text-red-400 text-xs" style={{ fontFamily: "Inter, sans-serif" }}>{err}</div>}
        </div>
        <button type="submit" disabled={busy} className="mt-8 w-full bg-[#FF6D0D] hover:bg-[#ff8530] disabled:opacity-50 text-black font-bold py-4 uppercase tracking-[0.2em] transition-all" style={{ fontFamily: "'Anton', sans-serif" }}>
          {busy ? "Entrando..." : "Entrar al reino"}
        </button>
      </form>
    </div>
  );
};

const AdminPanel = ({ onClose, onLogout }) => {
  const [tab, setTab] = useState("blog");
  const [blog, blogOps] = useStore(STORE_KEYS.blog, []);
  const [videos, videosOps] = useStore(STORE_KEYS.videos, []);
  const [fotos, fotosOps] = useStore(STORE_KEYS.fotos, []);

  const tabs = [
    { k: "blog", label: "Novedades", count: blog.length, badge: blog.filter(p => p.featured).length + " destacadas" },
    { k: "videos", label: "Videos", count: videos.length },
    { k: "fotos", label: "Galería", count: fotos.length },
  ];

  const totalRows = blog.length + videos.length + fotos.length;
  const allLoading = blogOps.loading && videosOps.loading && fotosOps.loading;
  const showSeed = !allLoading && totalRows === 0;

  const seed = async () => {
    if (!confirm("¿Insertar contenido de ejemplo? Solo recomendado si la base está vacía.")) return;
    for (const p of DEFAULT_BLOG) await blogOps.add(p);
    for (const v of DEFAULT_VIDEOS) await videosOps.add(v);
    for (const f of DEFAULT_FOTOS) await fotosOps.add(f);
  };

  return (
    <div className="fixed inset-0 z-[300] bg-[#020100] flex flex-col" style={{ animation: "fadeIn 0.25s" }}>
      <header className="flex items-center justify-between px-6 md:px-10 py-4 border-b border-white/10 bg-black/40 backdrop-blur-sm">
        <div className="flex items-center gap-4">
          <CrownMark size={28} />
          <div>
            <div className="text-white text-sm uppercase tracking-[0.2em] font-bold" style={{ fontFamily: "'Anton', sans-serif", letterSpacing: "0.18em" }}>Panel Admin</div>
            <div className="text-white/40 text-[10px] uppercase tracking-[0.25em]" style={{ fontFamily: "Inter, sans-serif" }}>Reyes de la Calle · Supabase</div>
          </div>
        </div>
        <div className="flex items-center gap-3">
          {showSeed && (
            <button onClick={seed} className="text-[#FF6D0D] border border-[#FF6D0D] hover:bg-[#FF6D0D] hover:text-black text-xs uppercase tracking-[0.2em] px-3 py-1.5 transition-colors" style={{ fontFamily: "Inter, sans-serif" }}>
              Sembrar ejemplo
            </button>
          )}
          <button onClick={onClose} className="text-white/70 hover:text-white text-xs uppercase tracking-[0.2em] flex items-center gap-2" style={{ fontFamily: "Inter, sans-serif" }}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M15 12H3M9 6l-6 6 6 6"/></svg>
            Ver sitio
          </button>
          <button onClick={onLogout} className="text-white/70 hover:text-[#FF6D0D] text-xs uppercase tracking-[0.2em] border border-white/20 hover:border-[#FF6D0D] px-3 py-1.5" style={{ fontFamily: "Inter, sans-serif" }}>
            Cerrar sesión
          </button>
        </div>
      </header>

      <nav className="px-6 md:px-10 flex border-b border-white/10 bg-black/20 overflow-x-auto">
        {tabs.map(t => (
          <button
            key={t.k}
            onClick={() => setTab(t.k)}
            className={
              "shrink-0 px-5 py-4 text-xs uppercase tracking-[0.2em] font-semibold border-b-2 transition-all flex items-center gap-2 " +
              (tab === t.k ? "border-[#FF6D0D] text-white" : "border-transparent text-white/50 hover:text-white")
            }
            style={{ fontFamily: "Inter, sans-serif" }}>
            {t.label}
            <span className="text-[10px] bg-white/10 text-white/60 px-2 py-0.5">{t.count}</span>
            {t.badge && <span className="text-[10px] text-[#FF6D0D]">· {t.badge}</span>}
          </button>
        ))}
      </nav>

      <div className="flex-1 overflow-y-auto">
        {tab === "blog" && <BlogAdmin items={blog} ops={blogOps} />}
        {tab === "videos" && <VideosAdmin items={videos} ops={videosOps} />}
        {tab === "fotos" && <FotosAdmin items={fotos} ops={fotosOps} />}
      </div>
    </div>
  );
};

// =============================================================================
// FORM HELPERS
// =============================================================================

const TextField = ({ label, value, onChange, type = "text", placeholder, required, hint }) => (
  <label className="block">
    <span className="block text-white/60 text-[10px] uppercase tracking-[0.25em] mb-1.5" style={{ fontFamily: "Inter, sans-serif" }}>
      {label} {required && <span className="text-[#FF6D0D]">*</span>}
    </span>
    <input type={type} value={value || ""} onChange={e => onChange(e.target.value)} placeholder={placeholder}
      className="w-full bg-black/40 border border-white/15 focus:border-[#FF6D0D] outline-none px-3 py-2 text-white text-sm"
      style={{ fontFamily: "Inter, sans-serif" }} />
    {hint && <span className="block text-white/30 text-[10px] mt-1" style={{ fontFamily: "Inter, sans-serif" }}>{hint}</span>}
  </label>
);

const TextArea = ({ label, value, onChange, rows = 4, placeholder, required }) => (
  <label className="block">
    <span className="block text-white/60 text-[10px] uppercase tracking-[0.25em] mb-1.5" style={{ fontFamily: "Inter, sans-serif" }}>
      {label} {required && <span className="text-[#FF6D0D]">*</span>}
    </span>
    <textarea value={value || ""} onChange={e => onChange(e.target.value)} placeholder={placeholder} rows={rows}
      className="w-full bg-black/40 border border-white/15 focus:border-[#FF6D0D] outline-none px-3 py-2 text-white text-sm resize-none"
      style={{ fontFamily: "Inter, sans-serif" }} />
  </label>
);

const Toggle = ({ label, value, onChange, description }) => (
  <label className="flex items-start gap-3 cursor-pointer group">
    <button type="button" onClick={() => onChange(!value)}
      className={"shrink-0 w-11 h-6 rounded-full transition-colors relative " + (value ? "bg-[#FF6D0D]" : "bg-white/15")}>
      <span className={"absolute top-0.5 w-5 h-5 bg-white rounded-full transition-transform " + (value ? "translate-x-5" : "translate-x-0.5")} />
    </button>
    <div>
      <div className="text-white text-sm font-semibold" style={{ fontFamily: "Inter, sans-serif" }}>{label}</div>
      {description && <div className="text-white/50 text-xs" style={{ fontFamily: "Inter, sans-serif" }}>{description}</div>}
    </div>
  </label>
);

const ImageField = ({ label, value, onChange, hint }) => {
  const fileRef = useRef(null);
  const [uploading, setUploading] = useState(false);
  const handleFile = async (file) => {
    if (!file) return;
    setUploading(true);
    const url = await uploadImage(file);
    if (url) onChange(url);
    setUploading(false);
  };
  return (
    <div>
      <span className="block text-white/60 text-[10px] uppercase tracking-[0.25em] mb-1.5" style={{ fontFamily: "Inter, sans-serif" }}>{label}</span>
      <div className="flex gap-3">
        <div className="w-24 h-24 shrink-0 bg-black/40 border border-white/15 flex items-center justify-center overflow-hidden">
          {value ? <img src={value} alt="" className="w-full h-full object-cover" /> : <span className="text-white/30 text-[10px] text-center px-2" style={{ fontFamily: "Inter, sans-serif" }}>Sin imagen</span>}
        </div>
        <div className="flex-1 space-y-2">
          <input type="text" value={value || ""} onChange={e => onChange(e.target.value)} placeholder="Pega URL o usa el botón →"
            className="w-full bg-black/40 border border-white/15 focus:border-[#FF6D0D] outline-none px-3 py-2 text-white text-sm"
            style={{ fontFamily: "Inter, sans-serif" }} />
          <div className="flex gap-2">
            <button type="button" disabled={uploading} onClick={() => fileRef.current && fileRef.current.click()}
              className="bg-white/10 hover:bg-white/20 disabled:opacity-50 text-white text-xs uppercase tracking-[0.18em] px-3 py-2 transition-colors"
              style={{ fontFamily: "Inter, sans-serif" }}>
              {uploading ? "Subiendo..." : "Subir archivo"}
            </button>
            {value && (
              <button type="button" onClick={() => onChange("")}
                className="text-white/50 hover:text-red-400 text-xs uppercase tracking-[0.18em] px-3 py-2 transition-colors"
                style={{ fontFamily: "Inter, sans-serif" }}>
                Quitar
              </button>
            )}
          </div>
          <input ref={fileRef} type="file" accept="image/*" className="hidden" onChange={e => handleFile(e.target.files[0])} />
          {hint && <span className="block text-white/30 text-[10px]" style={{ fontFamily: "Inter, sans-serif" }}>{hint}</span>}
        </div>
      </div>
    </div>
  );
};

const Card = ({ children, onEdit, onDelete, featured }) => (
  <div className={"relative bg-black/40 border " + (featured ? "border-[#FF6D0D]/40" : "border-white/10") + " hover:border-white/30 transition-all"}>
    {featured && (
      <div className="absolute top-3 left-3 bg-[#FF6D0D] text-black text-[9px] uppercase tracking-[0.2em] font-bold px-2 py-0.5 z-10" style={{ fontFamily: "'Anton', sans-serif" }}>
        Destacada
      </div>
    )}
    {children}
    <div className="flex border-t border-white/10">
      <button onClick={onEdit} className="flex-1 px-4 py-3 text-xs uppercase tracking-[0.18em] text-white/70 hover:text-[#FF6D0D] hover:bg-white/5 transition-colors flex items-center justify-center gap-2" style={{ fontFamily: "Inter, sans-serif" }}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7M18.5 2.5a2.121 2.121 0 113 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
        Editar
      </button>
      <button onClick={onDelete} className="flex-1 px-4 py-3 text-xs uppercase tracking-[0.18em] text-white/70 hover:text-red-400 hover:bg-red-500/10 transition-colors flex items-center justify-center gap-2 border-l border-white/10" style={{ fontFamily: "Inter, sans-serif" }}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2m3 0v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6h14z"/></svg>
        Eliminar
      </button>
    </div>
  </div>
);

const FormShell = ({ title, onCancel, onSave, saveLabel = "Guardar", canSave = true, busy = false, hint = "", children }) => (
  <div className="fixed inset-0 z-[400] bg-black/85 backdrop-blur-md flex items-center justify-center p-4 overflow-y-auto" style={{ animation: "fadeIn 0.2s" }}>
    <div className="relative bg-[#0A0807] border border-white/10 w-full max-w-2xl my-8" style={{ animation: "pop 0.3s cubic-bezier(.34,1.56,.64,1)" }}>
      <header className="flex items-center justify-between px-6 py-4 border-b border-white/10">
        <h3 className="text-white" style={{ fontFamily: "'Anton', sans-serif", fontSize: 22, letterSpacing: "0.02em" }}>{title}</h3>
        <button onClick={onCancel} className="text-white/50 hover:text-white" aria-label="Cerrar">
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M6 6l12 12M18 6L6 18"/></svg>
        </button>
      </header>
      <div className="p-6 space-y-5">{children}</div>
      <footer className="flex items-center justify-between gap-3 px-6 py-4 border-t border-white/10 bg-black/40">
        <div className="text-[#FF6D0D] text-xs" style={{ fontFamily: "Inter, sans-serif" }}>
          {!canSave && hint ? hint : ""}
        </div>
        <div className="flex items-center gap-3">
          <button onClick={onCancel} className="text-white/60 hover:text-white text-xs uppercase tracking-[0.2em] px-4 py-2" style={{ fontFamily: "Inter, sans-serif" }}>Cancelar</button>
          <button onClick={onSave} disabled={!canSave || busy}
            className={"px-5 py-2.5 text-xs uppercase tracking-[0.2em] font-bold transition-all " + (canSave && !busy ? "bg-[#FF6D0D] hover:bg-[#ff8530] text-black" : "bg-white/10 text-white/40 cursor-not-allowed")}
            style={{ fontFamily: "'Anton', sans-serif", letterSpacing: "0.18em" }}>
            {busy ? "Guardando..." : saveLabel}
          </button>
        </div>
      </footer>
    </div>
  </div>
);

const PageHeader = ({ title, subtitle, onNew, newLabel = "+ Nuevo" }) => (
  <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 mb-8">
    <div>
      <h2 className="text-white" style={{ fontFamily: "'Anton', sans-serif", fontSize: 36, lineHeight: 1 }}>{title}</h2>
      <p className="text-white/50 text-sm mt-1" style={{ fontFamily: "Inter, sans-serif" }}>{subtitle}</p>
    </div>
    <button onClick={onNew} className="bg-[#FF6D0D] hover:bg-[#ff8530] text-black font-bold px-5 py-3 uppercase tracking-[0.18em] text-xs transition-all" style={{ fontFamily: "'Anton', sans-serif", letterSpacing: "0.18em" }}>
      {newLabel}
    </button>
  </div>
);

const EmptyState = ({ message }) => (
  <div className="text-center py-20 text-white/40 text-sm border border-dashed border-white/10" style={{ fontFamily: "Inter, sans-serif" }}>
    {message}
  </div>
);

// =============================================================================
// BLOG ADMIN
// =============================================================================

const BlogAdmin = ({ items, ops }) => {
  const [editing, setEditing] = useState(null);
  const [busy, setBusy] = useState(false);

  const startNew = () => setEditing({
    title: "", excerpt: "", body: "", cover: "", featured: false,
    date: new Date().toISOString().slice(0, 10), category: "Comunidad", _new: true,
  });

  const save = async () => {
    const { _new, ...post } = editing;
    setBusy(true);
    try {
      if (_new) await ops.add(post);
      else await ops.update(editing.id, post);
      // Enforce máx 2 destacadas
      if (post.featured) await enforceMax2Featured(items, editing.id || "_new", ops);
      setEditing(null);
    } finally { setBusy(false); }
  };

  const remove = async (id) => {
    if (!confirm("¿Eliminar esta nota?")) return;
    await ops.remove(id);
  };

  const toggleFeatured = async (post) => {
    if (post.featured) {
      await ops.update(post.id, { featured: false });
    } else {
      await ops.update(post.id, { featured: true });
      await enforceMax2Featured(items, post.id, ops);
    }
  };

  const featuredCount = items.filter(i => i.featured).length;

  return (
    <div className="max-w-[1100px] mx-auto px-6 md:px-10 py-10">
      <PageHeader
        title="Novedades / Blog"
        subtitle={ops.loading ? "Cargando..." : `${items.length} notas · ${featuredCount}/2 destacadas en home`}
        onNew={startNew}
        newLabel="+ Nueva nota" />

      {items.length === 0 ? <EmptyState message='Aún no hay notas. Crea la primera con "+ Nueva nota".' /> : (
        <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
          {items.map(p => (
            <Card key={p.id} featured={p.featured} onEdit={() => setEditing(p)} onDelete={() => remove(p.id)}>
              <div className="relative aspect-[16/10] overflow-hidden bg-black">
                {p.cover ? <img src={p.cover} alt={p.title} className="absolute inset-0 w-full h-full object-cover" /> : <div className="flex items-center justify-center h-full text-white/20 text-xs">sin imagen</div>}
              </div>
              <div className="p-4">
                <div className="flex items-center justify-between gap-2 mb-2">
                  <span className="text-[10px] uppercase tracking-[0.2em] text-[#FF6D0D]" style={{ fontFamily: "Inter, sans-serif" }}>{p.category}</span>
                  <span className="text-[10px] uppercase tracking-[0.2em] text-white/40" style={{ fontFamily: "Inter, sans-serif" }}>{formatDate(p.date)}</span>
                </div>
                <h4 className="text-white text-base mb-2" style={{ fontFamily: "'Anton', sans-serif", lineHeight: 1.1 }}>{p.title || "(sin título)"}</h4>
                <p className="text-white/55 text-xs leading-relaxed mb-3 line-clamp-2" style={{ fontFamily: "Inter, sans-serif" }}>{p.excerpt}</p>
                <button onClick={() => toggleFeatured(p)} className={"text-[10px] uppercase tracking-[0.18em] font-semibold px-2 py-1 border transition-colors " + (p.featured ? "bg-[#FF6D0D]/10 border-[#FF6D0D]/50 text-[#FF6D0D]" : "border-white/15 text-white/50 hover:border-white/40")} style={{ fontFamily: "Inter, sans-serif" }}>
                  {p.featured ? "★ Destacada" : "☆ Marcar destacada"}
                </button>
              </div>
            </Card>
          ))}
        </div>
      )}

      {editing && (() => {
        const titleOk = !!(editing.title || "").trim();
        const missing = !titleOk ? "Falta el título" : "";
        return (
        <FormShell
          title={editing._new ? "Nueva nota" : "Editar nota"}
          onCancel={() => setEditing(null)}
          onSave={save}
          busy={busy}
          canSave={titleOk}
          hint={missing}>
          <TextField label="Título" value={editing.title} onChange={v => setEditing({ ...editing, title: v })} required />
          <div className="grid grid-cols-2 gap-4">
            <TextField label="Categoría" value={editing.category} onChange={v => setEditing({ ...editing, category: v })} placeholder="Torneos, Merch, Comunidad..." />
            <TextField label="Fecha" type="date" value={editing.date} onChange={v => setEditing({ ...editing, date: v })} />
          </div>
          <ImageField label="Imagen de portada" value={editing.cover} onChange={v => setEditing({ ...editing, cover: v })} hint="Sube un archivo (≤5MB) o pega URL. Se guarda en tu bucket de Supabase." />
          <TextArea label="Bajada (excerpt)" value={editing.excerpt} onChange={v => setEditing({ ...editing, excerpt: v })} rows={2} placeholder="Resumen corto que aparece en home..." />
          <TextArea label="Cuerpo de la nota" value={editing.body} onChange={v => setEditing({ ...editing, body: v })} rows={8} placeholder="Texto completo. Los saltos de línea se respetan." />
          <Toggle
            label="Destacar en home"
            value={editing.featured}
            onChange={v => setEditing({ ...editing, featured: v })}
            description="Las 2 notas destacadas más recientes aparecen en la sección Novedades." />
        </FormShell>
        );
      })()}
    </div>
  );
};

async function enforceMax2Featured(items, justUpdatedId, ops) {
  const featured = items.filter(p => p.featured && p.id !== justUpdatedId);
  // Si ya hay 2 o más además del que acabamos de marcar, demotear las más viejas
  if (featured.length >= 2) {
    const toDemote = [...featured].sort((a, b) => (a.date || "").localeCompare(b.date || "")).slice(0, featured.length - 1);
    for (const p of toDemote) await ops.update(p.id, { featured: false });
  }
}

// =============================================================================
// VIDEOS ADMIN
// =============================================================================

function extractYoutubeId(input) {
  if (!input) return "";
  const m = input.match(/(?:youtu\.be\/|v=|\/shorts\/|\/embed\/)([A-Za-z0-9_-]{11})/);
  return m ? m[1] : input.trim();
}

const VideosAdmin = ({ items, ops }) => {
  const [editing, setEditing] = useState(null);
  const [busy, setBusy] = useState(false);

  const startNew = () => setEditing({ youtubeId: "", thumb: "", title: "", duration: "", size: "", _new: true });

  const save = async () => {
    const { _new, ...v } = editing;
    if (!v.youtubeId) { alert("Necesitás un ID de YouTube válido."); return; }
    if (!v.thumb) v.thumb = `https://img.youtube.com/vi/${v.youtubeId}/maxresdefault.jpg`;
    setBusy(true);
    try {
      if (_new) await ops.add(v);
      else await ops.update(editing.id, v);
      setEditing(null);
    } finally { setBusy(false); }
  };

  const remove = async (id) => {
    if (!confirm("¿Eliminar este video?")) return;
    await ops.remove(id);
  };

  return (
    <div className="max-w-[1100px] mx-auto px-6 md:px-10 py-10">
      <PageHeader title="Videos" subtitle={ops.loading ? "Cargando..." : `${items.length} videos · Se abren en YouTube en pestaña nueva.`} onNew={startNew} newLabel="+ Nuevo video" />

      {items.length === 0 ? <EmptyState message="Aún no hay videos." /> : (
        <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
          {items.map(v => (
            <Card key={v.id} onEdit={() => setEditing(v)} onDelete={() => remove(v.id)}>
              <div className="relative aspect-video overflow-hidden bg-black">
                {v.thumb ? <img src={v.thumb} alt={v.title} className="absolute inset-0 w-full h-full object-cover" /> : <div className="flex items-center justify-center h-full text-white/20 text-xs">sin thumb</div>}
                <div className="absolute inset-0 flex items-center justify-center">
                  <div className="w-12 h-12 rounded-full bg-[#FF6D0D]/90 flex items-center justify-center">
                    <svg width="20" height="20" viewBox="0 0 24 24" fill="black"><path d="M8 5v14l11-7z"/></svg>
                  </div>
                </div>
                {v.duration && <div className="absolute bottom-2 right-2 bg-black/80 text-white text-[10px] font-mono px-1.5 py-0.5">{v.duration}</div>}
              </div>
              <div className="p-4">
                <h4 className="text-white text-sm mb-1" style={{ fontFamily: "'Anton', sans-serif", lineHeight: 1.1 }}>{v.title || "(sin título)"}</h4>
                <div className="text-white/40 text-[10px] uppercase tracking-[0.2em] font-mono">YT: {v.youtubeId || "—"}</div>
                {v.size === "wide" && <span className="inline-block mt-2 text-[10px] uppercase tracking-[0.2em] text-[#FF6D0D]" style={{ fontFamily: "Inter, sans-serif" }}>Tamaño 2×2</span>}
              </div>
            </Card>
          ))}
        </div>
      )}

      {editing && (
        <FormShell title={editing._new ? "Nuevo video" : "Editar video"} onCancel={() => setEditing(null)} onSave={save} busy={busy} canSave={!!(editing.title || "").trim() && !!(editing.youtubeId || "").trim()}>
          <TextField label="Título" value={editing.title} onChange={v => setEditing({ ...editing, title: v })} required />
          <TextField label="ID o URL de YouTube" value={editing.youtubeId} onChange={v => setEditing({ ...editing, youtubeId: extractYoutubeId(v) })} required hint="Pega la URL completa o solo el ID (11 caracteres)." />
          <div className="grid grid-cols-2 gap-4">
            <TextField label="Duración" value={editing.duration} onChange={v => setEditing({ ...editing, duration: v })} placeholder="3:42" />
            <div>
              <span className="block text-white/60 text-[10px] uppercase tracking-[0.25em] mb-1.5" style={{ fontFamily: "Inter, sans-serif" }}>Tamaño</span>
              <select value={editing.size || ""} onChange={e => setEditing({ ...editing, size: e.target.value })} className="w-full bg-black/40 border border-white/15 focus:border-[#FF6D0D] outline-none px-3 py-2 text-white text-sm" style={{ fontFamily: "Inter, sans-serif" }}>
                <option value="">Normal</option>
                <option value="wide">2×2 (destacado)</option>
              </select>
            </div>
          </div>
          <ImageField label="Thumbnail (opcional)" value={editing.thumb} onChange={v => setEditing({ ...editing, thumb: v })} hint="Si lo dejas vacío, usamos el thumb automático de YouTube." />
        </FormShell>
      )}
    </div>
  );
};

// =============================================================================
// FOTOS ADMIN
// =============================================================================

const FotosAdmin = ({ items, ops }) => {
  const [editing, setEditing] = useState(null);
  const [busy, setBusy] = useState(false);

  const startNew = () => setEditing({ src: "", title: "", subtitle: "", size: "", _new: true });

  const save = async () => {
    const { _new, ...f } = editing;
    if (!f.src) { alert("Necesitás una imagen."); return; }
    setBusy(true);
    try {
      if (_new) await ops.add(f);
      else await ops.update(editing.id, f);
      setEditing(null);
    } finally { setBusy(false); }
  };

  const remove = async (id) => {
    if (!confirm("¿Eliminar esta foto?")) return;
    await ops.remove(id);
  };

  return (
    <div className="max-w-[1100px] mx-auto px-6 md:px-10 py-10">
      <PageHeader title="Galería de Fotos" subtitle={ops.loading ? "Cargando..." : `${items.length} fotos en el archivo público.`} onNew={startNew} newLabel="+ Nueva foto" />

      {items.length === 0 ? <EmptyState message="Aún no hay fotos." /> : (
        <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
          {items.map(f => (
            <Card key={f.id} onEdit={() => setEditing(f)} onDelete={() => remove(f.id)}>
              <div className="relative aspect-square overflow-hidden bg-black">
                {f.src ? <img src={f.src} alt={f.title} className="absolute inset-0 w-full h-full object-cover" /> : <div className="flex items-center justify-center h-full text-white/20 text-xs">sin imagen</div>}
                {f.size === "wide" && <div className="absolute top-2 right-2 bg-black/70 text-white text-[10px] uppercase tracking-[0.2em] px-2 py-0.5">2×2</div>}
              </div>
              <div className="p-3">
                <h4 className="text-white text-sm" style={{ fontFamily: "'Anton', sans-serif", lineHeight: 1.1 }}>{f.title || "(sin título)"}</h4>
                <div className="text-[#FF6D0D] text-[10px] uppercase tracking-[0.2em]" style={{ fontFamily: "Inter, sans-serif" }}>{f.subtitle || "—"}</div>
              </div>
            </Card>
          ))}
        </div>
      )}

      {editing && (
        <FormShell title={editing._new ? "Nueva foto" : "Editar foto"} onCancel={() => setEditing(null)} onSave={save} busy={busy} canSave={!!editing.src && !!(editing.title || "").trim()}>
          <ImageField label="Imagen" value={editing.src} onChange={v => setEditing({ ...editing, src: v })} hint="Sube un archivo (≤5MB) o pega URL." />
          <TextField label="Título" value={editing.title} onChange={v => setEditing({ ...editing, title: v })} required />
          <TextField label="Subtítulo / Categoría" value={editing.subtitle} onChange={v => setEditing({ ...editing, subtitle: v })} placeholder="Editorial, Documental, Movimiento..." />
          <div>
            <span className="block text-white/60 text-[10px] uppercase tracking-[0.25em] mb-1.5" style={{ fontFamily: "Inter, sans-serif" }}>Tamaño en grilla</span>
            <select value={editing.size || ""} onChange={e => setEditing({ ...editing, size: e.target.value })} className="w-full bg-black/40 border border-white/15 focus:border-[#FF6D0D] outline-none px-3 py-2 text-white text-sm" style={{ fontFamily: "Inter, sans-serif" }}>
              <option value="">Normal (1×1)</option>
              <option value="wide">Destacado (2×2)</option>
            </select>
          </div>
        </FormShell>
      )}
    </div>
  );
};

Object.assign(window, {
  STORE_KEYS,
  DEFAULT_BLOG,
  DEFAULT_VIDEOS,
  DEFAULT_FOTOS,
  useStore,
  uploadImage,
  Novedades,
  BlogReader,
  AdminGate,
});
