// App.jsx — estructura de navegación
const { useState, useEffect } = React;
const { UtilityBar, Masthead, Nav, BreakingTicker } = window.CS_Header;
const { Footer } = window.CS_Common;
const HomeView = window.CS_Home;
const ArticleView = window.CS_Article;
const { CategoryView, AuthorView, SearchView } = window.CS_Pages;

// Valores por defecto de ajustes — must be valid JSON between markers
const TWEAKS_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accentColor": "#E85D24",
  "primaryColor": "#1538A8",
  "showBreaking": true,
  "tickerSpeed": 65,
  "density": "Equilibrada",
  "headlineFont": "Source Serif 4",
  "darkUtilityBar": true
}/*EDITMODE-END*/;

function SearchOverlay({ onClose, onNav }) {
  const [q, setQ] = useState('');
  const articles = window.CS_DATA.articles;
  const results = q.trim()
    ? articles.filter(a => a.title.toLowerCase().includes(q.toLowerCase())).slice(0, 6)
    : articles.slice(0, 5);

  return (
    <div className="cs-search-overlay" onClick={onClose}>
      <div className="cs-search-overlay-inner" onClick={e => e.stopPropagation()}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12, borderBottom: '2px solid var(--ink)', paddingBottom: 8 }}>
          <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/>
          </svg>
          <input
            autoFocus
            value={q}
            onChange={e => setQ(e.target.value)}
            placeholder="Buscar artículos, autores, secciones..."
            style={{
              flex: 1, border: 0, outline: 'none', fontFamily: 'var(--serif)',
              fontSize: 24, fontWeight: 600, background: 'transparent', padding: '8px 0'
            }}
          />
          <button onClick={onClose} style={{
            background: 'var(--bg-alt)', border: '1px solid var(--line)', padding: '6px 10px',
            borderRadius: 4, fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.08em', textTransform: 'uppercase'
          }}>esc</button>
        </div>
        <div style={{
          fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.12em', textTransform: 'uppercase',
          color: 'var(--mute)', margin: '18px 0 8px'
        }}>
          {q ? `${results.length} resultados rápidos` : 'Sugerencias'}
        </div>
        {results.map(a => (
          <div
            key={a.id}
            onClick={() => { onNav({ view: 'article', id: a.id }); onClose(); }}
            style={{ display: 'flex', gap: 12, padding: '10px 0', borderBottom: '1px solid var(--line)', cursor: 'pointer', alignItems: 'center' }}
          >
            <span style={{ width: 6, height: 6, borderRadius: 999, background: window.CS_DATA.sections.find(s => s.slug === a.section)?.color }}></span>
            <div style={{ flex: 1 }}>
              <div style={{ fontFamily: 'var(--serif)', fontSize: 16, fontWeight: 600, lineHeight: 1.2 }}>{a.title}</div>
              <div style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--mute)', marginTop: 4, letterSpacing: '0.04em' }}>
                {a.kicker} · {a.readMin} min
              </div>
            </div>
            <span style={{ color: 'var(--mute)' }}>→</span>
          </div>
        ))}
        <div style={{
          marginTop: 18, display: 'flex', gap: 18, justifyContent: 'space-between',
          fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--mute)', letterSpacing: '0.06em'
        }}>
          <span>▾▴ Navegar · ↵ Abrir · ESC Cerrar</span>
          <span
            style={{ cursor: 'pointer', color: 'var(--brand-blue)', fontWeight: 600 }}
            onClick={() => { onNav({ view: 'search', q }); onClose(); }}
          >
            Ver todos los resultados →
          </span>
        </div>
      </div>
    </div>
  );
}

function TweaksUI({ tweaks, setTweak }) {
  if (!window.TweaksPanel) return null;
  const { TweaksPanel, TweakSection, TweakColor, TweakToggle, TweakRadio, TweakSlider } = window;
  return (
    <TweaksPanel title="Ajustes · Conexión Semanal">
      <TweakSection title="Identidad">
        <TweakColor
          label="Azul de marca"
          value={tweaks.primaryColor}
          onChange={v => setTweak('primaryColor', v)}
          options={['#1538A8', '#0C2479', '#0B6BCB', '#1E3A8A']}
        />
        <TweakColor
          label="Naranja de acento"
          value={tweaks.accentColor}
          onChange={v => setTweak('accentColor', v)}
          options={['#E85D24', '#D9480F', '#F59E0B', '#9C2A2A']}
        />
      </TweakSection>
      <TweakSection title="Portada">
        <TweakRadio
          label="Densidad de la home"
          value={tweaks.density}
          onChange={v => setTweak('density', v)}
          options={['Densa', 'Equilibrada', 'Aireada']}
        />
        <TweakToggle
          label="Barra superior oscura"
          value={tweaks.darkUtilityBar}
          onChange={v => setTweak('darkUtilityBar', v)}
        />
      </TweakSection>
      <TweakSection title="Última hora">
        <TweakToggle
          label="Mostrar ticker"
          value={tweaks.showBreaking}
          onChange={v => setTweak('showBreaking', v)}
        />
        <TweakSlider
          label="Velocidad del ticker (seg)"
          value={tweaks.tickerSpeed}
          onChange={v => setTweak('tickerSpeed', v)}
          min={30} max={120} step={5}
        />
      </TweakSection>
    </TweaksPanel>
  );
}

function resetPageScroll() {
  document.body.classList.remove('is-scrolled');
  window.scrollTo(0, 0);
}

function App() {
  const [route, setRoute] = useState({ view: 'home' });
  const [searchOpen, setSearchOpen] = useState(false);
  const [contentVersion, setContentVersion] = useState(0);
  const [saved, setSaved] = useState(() => {
    try { return JSON.parse(localStorage.getItem('cs_saved') || '["a1","a5"]'); }
    catch { return ['a1', 'a5']; }
  });
  const [tweaks, setTweaks] = window.useTweaks(TWEAKS_DEFAULTS);

  useEffect(() => {
    if ('scrollRestoration' in window.history) {
      window.history.scrollRestoration = 'manual';
    }

    const resetAfterBrowserRestore = () => {
      resetPageScroll();
      requestAnimationFrame(resetPageScroll);
      setTimeout(resetPageScroll, 120);
    };

    resetAfterBrowserRestore();
    window.addEventListener('pageshow', resetAfterBrowserRestore);
    window.addEventListener('load', resetAfterBrowserRestore);

    return () => {
      window.removeEventListener('pageshow', resetAfterBrowserRestore);
      window.removeEventListener('load', resetAfterBrowserRestore);
    };
  }, []);

  useEffect(() => {
    let mounted = true;
    const onDataChanged = () => {
      if (mounted) setContentVersion(v => v + 1);
    };

    window.addEventListener('cs:data-changed', onDataChanged);

    if (window.CS_Backend?.isConfigured?.()) {
      window.CS_Backend.loadPublicContent().catch(error => {
        console.warn('No se pudo cargar contenido desde Supabase:', error);
      });
    }

    return () => {
      mounted = false;
      window.removeEventListener('cs:data-changed', onDataChanged);
    };
  }, []);

  // Restore last route from localStorage
  useEffect(() => {
    try {
      const r = JSON.parse(localStorage.getItem('cs_route') || '{}');
      if (r.view) setRoute(r);
    } catch {}
  }, []);
  useEffect(() => {
    localStorage.setItem('cs_route', JSON.stringify(route));
    resetPageScroll();
    requestAnimationFrame(resetPageScroll);
    setTimeout(resetPageScroll, 120);
  }, [route]);
  useEffect(() => {
    localStorage.setItem('cs_saved', JSON.stringify(saved));
  }, [saved]);

  // Apply tweaks via CSS variables on :root
  useEffect(() => {
    const root = document.documentElement;
    root.style.setProperty('--brand-blue', tweaks.primaryColor);
    root.style.setProperty('--c-politica', tweaks.primaryColor);
    root.style.setProperty('--c-la-semanal', tweaks.primaryColor);
    root.style.setProperty('--brand-orange', tweaks.accentColor);
  }, [tweaks.primaryColor, tweaks.accentColor]);

  // ESC closes search
  useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'Escape') setSearchOpen(false);
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
        e.preventDefault();
        setSearchOpen(true);
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  // Sticky chrome — add is-scrolled to body when user scrolls past 80px
  useEffect(() => {
    let raf = 0;
    const onScroll = () => {
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(() => {
        document.body.classList.toggle('is-scrolled', window.scrollY > 80);
      });
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  // Reveal on scroll — confirm transition timeline is alive before arming.
  // If timeline is paused (some preview iframes), content stays visible without animation.
  useEffect(() => {
    let cancelled = false;
    let safety;
    let io;

    requestAnimationFrame(() => {
      if (cancelled) return;
      // Detect if animations actually advance in this environment.
      const timelineAlive = typeof document.timeline !== 'undefined'
        ? (document.timeline.currentTime || 0) > 0
        : true;

      if (!timelineAlive) return; // skip arming — keep content visible

      const targets = document.querySelectorAll('.cs-reveal:not(.cs-reveal-armed)');
      if (targets.length === 0) return;

      // Arm transitions
      targets.forEach(t => t.classList.add('cs-reveal-armed'));

      // Reveal items already in viewport on next frame
      requestAnimationFrame(() => {
        const vh = window.innerHeight || document.documentElement.clientHeight;
        document.querySelectorAll('.cs-reveal-armed:not(.is-in)').forEach(t => {
          const r = t.getBoundingClientRect();
          if (r.top < vh - 40) t.classList.add('is-in');
        });
      });

      // Observer for items below the fold
      if ('IntersectionObserver' in window) {
        io = new IntersectionObserver((entries) => {
          entries.forEach(entry => {
            if (entry.isIntersecting) {
              entry.target.classList.add('is-in');
              io.unobserve(entry.target);
            }
          });
        }, { rootMargin: '0px 0px -60px 0px', threshold: 0.05 });
        document.querySelectorAll('.cs-reveal-armed:not(.is-in)').forEach(t => io.observe(t));
      }

      // Safety fallback
      safety = setTimeout(() => {
        document.querySelectorAll('.cs-reveal-armed:not(.is-in)').forEach(t => t.classList.add('is-in'));
      }, 1500);
    });

    return () => {
      cancelled = true;
      clearTimeout(safety);
      if (io) io.disconnect();
    };
  }, [route]);

  function nav(next) {
    // Use View Transitions API where supported for crossfade between views
    if (document.startViewTransition) {
      document.startViewTransition(() => {
        setRoute(next);
      });
    } else {
      setRoute(next);
    }
  }

  function toggleSave(id) {
    setSaved(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]);
  }

  // Apply ticker speed live
  useEffect(() => {
    const el = document.querySelector('.cs-breaking-stream');
    if (el) el.style.animationDuration = `${tweaks.tickerSpeed}s`;
  }, [tweaks.tickerSpeed, route]);

  // Density CSS class
  useEffect(() => {
    document.body.classList.toggle('density-compact', tweaks.density === 'Densa');
    document.body.classList.toggle('density-airy', tweaks.density === 'Aireada');
  }, [tweaks.density]);

  // Utility bar style
  useEffect(() => {
    document.body.classList.toggle('utility-light', !tweaks.darkUtilityBar);
  }, [tweaks.darkUtilityBar]);

  let pageLabel = 'Portada';
  let content;
  if (route.view === 'home') {
    pageLabel = 'Portada';
    content = <HomeView onNav={nav} saved={saved} />;
  } else if (route.view === 'article') {
    pageLabel = `Artículo — ${route.id}`;
    content = <ArticleView id={route.id} onNav={nav} saved={saved} toggleSave={toggleSave} />;
  } else if (route.view === 'category') {
    pageLabel = `Categoría — ${route.slug}`;
    content = <CategoryView slug={route.slug} onNav={nav} />;
  } else if (route.view === 'author') {
    pageLabel = `Autor — ${route.slug}`;
    content = <AuthorView slug={route.slug} onNav={nav} />;
  } else if (route.view === 'search') {
    pageLabel = 'Búsqueda';
    content = <SearchView q={route.q || ''} onNav={nav} />;
  }

  return (
    <div data-screen-label={pageLabel}>
      <UtilityBar />
      <Masthead savedCount={saved.length} onNav={nav} onSearch={() => setSearchOpen(true)} />
      <Nav current={route} onNav={nav} />
      {tweaks.showBreaking && <BreakingTicker />}
      <main>{content}</main>
      <Footer onNav={nav} />
      {searchOpen && <SearchOverlay onClose={() => setSearchOpen(false)} onNav={nav} />}
      <TweaksUI tweaks={tweaks} setTweak={setTweak} />
    </div>
  );

  function setTweak(k, v) {
    if (typeof k === 'string') setTweaks({ [k]: v });
    else setTweaks(k);
  }
}

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