const { useState, useEffect, useRef, useMemo } = React;

// ——— Tweaks wiring ——————————————————————————————————————————
function useSiteTheme() {
  const defaults = window.TWEAK_DEFAULTS || {};
  const [tweaks, setTweak] = useTweaks(defaults);

  useEffect(() => {
    const r = document.documentElement;
    r.style.setProperty('--bg', tweaks.bgColor || '#EDE4D3');
    r.style.setProperty('--gold', tweaks.accentColor || '#8B6B3D');
    r.style.setProperty('--gold-deep', shadeColor(tweaks.accentColor || '#8B6B3D', -28));
    r.style.setProperty('--body', tweaks.bodyColor || '#2B1810');
    r.style.setProperty('--body-2', shadeColor(tweaks.bodyColor || '#2B1810', 12));
    r.style.setProperty('--serif', `'${tweaks.fontSerif || 'Cormorant Garamond'}', Georgia, serif`);
    const washEl = document.querySelector('.bg-wash-wrap');
    if (washEl) washEl.style.opacity = ((tweaks.bgOpacity || 100) / 100) * 0.06;
    document.querySelectorAll('.hero-title').forEach(el => {
      el.style.fontSize = `clamp(${Math.round(68 * (tweaks.heroSize / 100))}px, ${10 * (tweaks.heroSize / 100)}vw, ${Math.round(132 * (tweaks.heroSize / 100))}px)`;
    });
  }, [tweaks]);

  return { tweaks, setTweak };
}

function shadeColor(hex, pct) {
  try {
    let r = parseInt(hex.slice(1,3),16), g = parseInt(hex.slice(3,5),16), b = parseInt(hex.slice(5,7),16);
    r = Math.max(0, Math.min(255, r + pct)); g = Math.max(0, Math.min(255, g + pct)); b = Math.max(0, Math.min(255, b + pct));
    return `#${r.toString(16).padStart(2,'0')}${g.toString(16).padStart(2,'0')}${b.toString(16).padStart(2,'0')}`;
  } catch { return hex; }
}

const SERIF_OPTIONS = [
  'Cormorant Garamond',
  'Playfair Display',
  'EB Garamond',
  'Libre Baskerville',
];

function TweaksLayer() {
  const { tweaks, setTweak } = useSiteTheme();
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Fondo y colores">
        <TweakColor label="Color de fondo" id="bgColor" value={tweaks.bgColor} onChange={v => setTweak('bgColor', v)} />
        <TweakColor label="Color dorado / acento" id="accentColor" value={tweaks.accentColor} onChange={v => setTweak('accentColor', v)} />
        <TweakColor label="Color de texto" id="bodyColor" value={tweaks.bodyColor} onChange={v => setTweak('bodyColor', v)} />
        <TweakSlider label="Opacidad fondo (hojas)" id="bgOpacity" value={tweaks.bgOpacity} min={0} max={100} step={5} onChange={v => setTweak('bgOpacity', v)} />
      </TweakSection>
      <TweakSection label="Tipografía">
        <TweakSelect label="Fuente serif" id="fontSerif" value={tweaks.fontSerif}
          options={SERIF_OPTIONS} onChange={v => setTweak('fontSerif', v)} />
        <TweakSlider label="Tamaño título hero (%)" id="heroSize" value={tweaks.heroSize} min={60} max={130} step={5} onChange={v => setTweak('heroSize', v)} />
      </TweakSection>
    </TweaksPanel>
  );
}

// ——— Tiny hash-router ————————————————————————————————————————
function parseHash() {
  const h = (window.location.hash || '#/').replace(/^#/, '');
  const parts = h.split('/').filter(Boolean);
  if (parts.length === 0) return { name: 'home' };
  if (parts[0] === 'escritos' && parts.length === 1) return { name: 'escritos' };
  if (parts[0] === 'escritos' && parts[1]) return { name: 'poem', slug: parts[1] };
  if (parts[0] === 'sobre') return { name: 'about' };
  return { name: 'home' };
}
function navigate(path) {
  window.location.hash = path;
  window.scrollTo({ top: 0, behavior: 'instant' });
}
function useRoute() {
  const [route, setRoute] = useState(parseHash());
  useEffect(() => {
    const onHash = () => setRoute(parseHash());
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  return route;
}

// ——— Placeholder imagery (botanical color washes) ————————————
const IMG_PALETTES = {
  lavender: { a: '#B9A9CE', b: '#8B7AA8', c: '#F1E9DA', label: 'lavanda' },
  olive:    { a: '#B8C09A', b: '#7A8F66', c: '#F2EAD4', label: 'olivos' },
  fig:      { a: '#8A6A4E', b: '#5C3F2A', c: '#E8DBC5', label: 'higuera' },
  geraniums:{ a: '#C97560', b: '#9A4330', c: '#F5E5D4', label: 'geranios' },
  letters:  { a: '#D9C6A5', b: '#A3885E', c: '#F3E8D2', label: 'cartas' },
  citrus:   { a: '#D9A25E', b: '#A57235', c: '#F5E8CC', label: 'membrillo' },
  jasmine:  { a: '#E8DDCC', b: '#B9A98A', c: '#FBF5E8', label: 'jazmín' },
  almond:   { a: '#E6D1C8', b: '#B88C7A', c: '#F6EADF', label: 'almendro' },
  poppy:    { a: '#D96A58', b: '#A13A28', c: '#F3DCC7', label: 'amapolas' },
};
function PlaceholderImage({ variant = 'lavender', label = '' }) {
  const p = IMG_PALETTES[variant] || IMG_PALETTES.lavender;
  // Soft botanical pattern: gradient base + leaf ring + label
  return (
    <svg className="ph-img" viewBox="0 0 400 300" preserveAspectRatio="xMidYMid slice" xmlns="http://www.w3.org/2000/svg" aria-label={label || p.label}>
      <defs>
        <linearGradient id={`g-${variant}`} x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stopColor={p.c} />
          <stop offset="100%" stopColor={p.a} stopOpacity="0.75" />
        </linearGradient>
        <radialGradient id={`r-${variant}`} cx="70%" cy="35%" r="75%">
          <stop offset="0%" stopColor="#FFFDF5" stopOpacity="0.55" />
          <stop offset="100%" stopColor={p.b} stopOpacity="0" />
        </radialGradient>
      </defs>
      <rect width="400" height="300" fill={`url(#g-${variant})`} />
      <rect width="400" height="300" fill={`url(#r-${variant})`} />
      {/* subtle leaf sprigs */}
      <g opacity="0.45" stroke={p.b} strokeWidth="1" fill="none">
        <path d="M 40 250 Q 120 180 180 230" />
        <path d="M 360 60 Q 300 120 240 80" />
      </g>
      <g opacity="0.55" fill={p.b}>
        <ellipse cx="70" cy="230" rx="18" ry="6" transform="rotate(-30 70 230)" />
        <ellipse cx="110" cy="210" rx="20" ry="7" transform="rotate(-15 110 210)" />
        <ellipse cx="150" cy="220" rx="18" ry="6" transform="rotate(10 150 220)" />
        <ellipse cx="340" cy="80" rx="18" ry="6" transform="rotate(25 340 80)" />
        <ellipse cx="300" cy="100" rx="20" ry="7" transform="rotate(40 300 100)" />
      </g>
      <text x="20" y="285" fontFamily="ui-monospace, monospace" fontSize="10"
            fill={p.b} opacity="0.75" letterSpacing="2">
        {(label || p.label).toUpperCase()}
      </text>
    </svg>
  );
}

// ——— Common ————————————————————————————————————————————————
function Divider() {
  return (
    <div className="divider" aria-hidden="true"
      dangerouslySetInnerHTML={{ __html: window.Botanicals.divider() }} />
  );
}
function ScrollReveal({ children, delay = 0, className = '' }) {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            setTimeout(() => setShown(true), delay);
            io.disconnect();
          }
        });
      },
      { threshold: 0.15 }
    );
    io.observe(ref.current);
    return () => io.disconnect();
  }, [delay]);
  return (
    <div ref={ref} className={`reveal ${shown ? 'reveal-in' : ''} ${className}`}>
      {children}
    </div>
  );
}

// ——— Nav ————————————————————————————————————————————————————
function Nav({ route }) {
  const [scrolled, setScrolled] = useState(false);
  const [mobileOpen, setMobileOpen] = useState(false);
  useEffect(() => {
    const fn = () => setScrolled(window.scrollY > 40);
    window.addEventListener('scroll', fn, { passive: true });
    fn();
    return () => window.removeEventListener('scroll', fn);
  }, []);
  useEffect(() => { setMobileOpen(false); }, [route]);
  const links = [
    ['Inicio', '/', 'home'],
    ['Escritos', '/escritos', 'escritos'],
    ['Sobre mí', '/sobre', 'about'],
  ];
  const activeKey = route.name === 'poem' ? 'escritos' : route.name;
  return (
    <>
      <nav className={`nav ${scrolled ? 'nav-scrolled' : ''}`} aria-label="Principal">
        <div className="nav-inner">
          <a href="#/" className="nav-logo" onClick={(e) => { e.preventDefault(); navigate('/'); }}>
            <span className="nav-logo-mark">A</span>
            <span className="nav-logo-text">Auropoesía</span>
          </a>
          <ul className="nav-links">
            {links.map(([label, path, key]) => (
              <li key={key}>
                <button
                  className={`nav-link ${activeKey === key ? 'active' : ''}`}
                  onClick={() => navigate(path)}>
                  {label}
                </button>
              </li>
            ))}
          </ul>
          <button className="nav-burger" aria-label="Abrir menú"
            aria-expanded={mobileOpen}
            onClick={() => setMobileOpen(v => !v)}>
            {mobileOpen ? (
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round">
                <line x1="6" y1="6" x2="18" y2="18" />
                <line x1="18" y1="6" x2="6" y2="18" />
              </svg>
            ) : (
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
                <line x1="4" y1="8" x2="20" y2="8" />
                <line x1="4" y1="16" x2="20" y2="16" />
              </svg>
            )}
          </button>
        </div>
      </nav>
      <div className={`nav-mobile ${mobileOpen ? 'open' : ''}`}>
        {links.map(([label, path, key]) => (
          <button key={key}
            className={`nav-link ${activeKey === key ? 'active' : ''}`}
            onClick={() => navigate(path)}>
            {label}
          </button>
        ))}
      </div>
    </>
  );
}

// ——— Custom select ——————————————————————————————————————
function CustomSelect({ value, options, onChange, ariaLabel }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === 'Escape') setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    document.addEventListener('keydown', onKey);
    return () => {
      document.removeEventListener('mousedown', onDoc);
      document.removeEventListener('keydown', onKey);
    };
  }, [open]);
  const current = options.find(o => String(o.value) === String(value));
  return (
    <div className={`filter-select ${open ? 'open' : ''}`} ref={ref}>
      <button type="button" className="filter-select-btn"
        aria-haspopup="listbox" aria-expanded={open} aria-label={ariaLabel}
        onClick={() => setOpen(v => !v)}>
        {current ? current.label : ''}
      </button>
      <svg className="filter-select-chevron" width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
        <polyline points="3 5 7 9 11 5" />
      </svg>
      {open && (
        <ul className="filter-select-menu" role="listbox">
          {options.map(o => (
            <li key={String(o.value)} role="option" aria-selected={String(o.value) === String(value)}>
              <button type="button"
                className={`filter-select-option ${String(o.value) === String(value) ? 'selected' : ''}`}
                onClick={() => { onChange(o.value); setOpen(false); }}>
                {o.label}
              </button>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

// ——— Hero ———————————————————————————————————————————————————
function Hero() {
  return (
    <section id="hero" className="hero" data-screen-label="01 Hero">
      <div className="hero-motif-wrap" aria-hidden="true"
        dangerouslySetInnerHTML={{ __html: window.Botanicals.heroMotif() }} />
      <div className="hero-inner">
        <p className="hero-kicker">— un jardín de palabras —</p>
        <h1 className="hero-title">Auropoesía</h1>
        <p className="hero-sub">Poesía de Aurelia</p>
        <p className="hero-blurb">
          Versos escritos despacio, a la luz de la ventana,
          <br />entre geranios, cartas y tardes que no tienen prisa.
        </p>
        <button className="hero-cta" onClick={() => navigate('/escritos')}>
          Leer los escritos
        </button>
      </div>
    </section>
  );
}

// ——— Home: featured row ——————————————————————————————————————
function HomeFeatured() {
  const featured = window.POEMS.slice(0, 3);
  return (
    <section className="home-featured" aria-label="Escritos destacados">
      <Divider />
      <div className="home-featured-head">
        <p className="section-kicker">Escritos recientes</p>
        <h2 className="section-title">Tres del cuaderno<br/>de este año.</h2>
      </div>
      <div className="home-featured-grid">
        {featured.map((p, i) => (
          <PoemCard key={p.slug} poem={p} index={i} />
        ))}
      </div>
      <div className="home-featured-foot">
        <button className="hero-cta" onClick={() => navigate('/escritos')}>
          Ver todos los escritos
        </button>
      </div>
    </section>
  );
}

// ——— About ——————————————————————————————————————————————————
function About() {
  return (
    <section id="about" className="about" data-screen-label="02 Sobre mí">
      <Divider />
      <div className="about-inner">
        <ScrollReveal className="about-portrait-col">
          <div className="portrait">
            <div className="portrait-frame-wrap" aria-hidden="true"
              dangerouslySetInnerHTML={{ __html: window.Botanicals.portraitFrame(360) }} />
            <div className="portrait-photo" role="img" aria-label="Retrato de Aurelia">
              <div className="portrait-placeholder">
                <span className="portrait-mono">foto · Aurelia</span>
              </div>
            </div>
          </div>
        </ScrollReveal>
        <ScrollReveal className="about-text-col" delay={120}>
          <p className="section-kicker">Sobre mí</p>
          <h2 className="section-title">Un jardín, una libreta,<br/>setenta primaveras.</h2>
          <p className="about-p">
            Me llamo Aurelia. Nací en un pueblo de Cuenca donde los veranos olían a higo maduro
            y las ventanas se dejaban abiertas hasta muy tarde. Toda mi vida he escrito poemas —
            a lápiz, en libretas de hule, entre la lista de la compra y las recetas de mi madre.
          </p>
          <p className="about-p">
            Fui maestra durante cuarenta y dos años. Enseñé a leer a tres generaciones de niños,
            pero solo ahora — con las manos algo más lentas y el tiempo por fin mío — me atrevo
            a compartir lo que guardé siempre en el cajón de abajo.
          </p>
          <p className="about-p about-sig">
            Bienvenido a mi jardín.
            <span className="about-signature">— Aurelia</span>
          </p>
        </ScrollReveal>
      </div>
    </section>
  );
}

// ——— Poem card —————————————————————————————————————————————
function PoemCard({ poem, index = 0 }) {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            setTimeout(() => setShown(true), (index % 2) * 60);
            io.disconnect();
          }
        });
      },
      { threshold: 0.12 }
    );
    io.observe(ref.current);
    return () => io.disconnect();
  }, [index]);
  return (
    <article ref={ref} className={`poem-card reveal ${shown ? 'reveal-in' : ''}`}
      onClick={() => navigate('/escritos/' + poem.slug)}
      role="link" tabIndex={0}
      onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); navigate('/escritos/' + poem.slug); } }}
      aria-label={`Leer ${poem.title}`}>
      <div className="poem-card-image">
        <PlaceholderImage variant={poem.image} label={poem.image} />
      </div>
      <div className="poem-card-body">
        <span className="poem-card-year">{poem.year}</span>
        <h3 className="poem-card-title">{poem.title}</h3>
        <pre className="poem-card-excerpt">{poem.excerpt}</pre>
        <div className="poem-card-rule" aria-hidden="true"></div>
        <div className="poem-card-foot">
          <span className="poem-card-read">Leer el poema</span>
          <span className="poem-card-arrow" aria-hidden="true">→</span>
        </div>
      </div>
    </article>
  );
}

// ——— Escritos (index with search + year filter + pagination) ———
const PER_PAGE = 12;

function Escritos() {
  const [q, setQ] = useState('');
  const [year, setYear] = useState('all');
  const [page, setPage] = useState(1);

  const years = useMemo(() => {
    const s = new Set(window.POEMS.map(p => p.year));
    return [...s].sort((a, b) => b - a);
  }, []);

  const filtered = useMemo(() => {
    const needle = q.trim().toLowerCase();
    return window.POEMS.filter(p => {
      if (year !== 'all' && String(p.year) !== String(year)) return false;
      if (!needle) return true;
      const hay = [p.title, p.body, p.excerpt, ...(p.tags || [])].join(' ').toLowerCase();
      return hay.includes(needle);
    });
  }, [q, year]);

  useEffect(() => { setPage(1); }, [q, year]);

  const totalPages = Math.max(1, Math.ceil(filtered.length / PER_PAGE));
  const curPage = Math.min(page, totalPages);
  const pageItems = filtered.slice((curPage - 1) * PER_PAGE, curPage * PER_PAGE);

  return (
    <section className="escritos" data-screen-label="03 Escritos">
      <div className="escritos-head">
        <p className="section-kicker">Escritos</p>
        <h2 className="section-title">El cuaderno,<br/>ordenado con calma.</h2>
        <p className="escritos-intro">
          Poemas reunidos a lo largo de los años. Busca por palabra,
          filtra por año, o simplemente déjate llevar.
        </p>
      </div>

      {/* Filter bar */}
      <div className="filter-bar" role="search">
        <label className="filter-search">
          <svg className="filter-search-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" aria-hidden="true">
            <circle cx="11" cy="11" r="7" />
            <line x1="20" y1="20" x2="16.5" y2="16.5" />
          </svg>
          <input
            type="text"
            value={q}
            onChange={(e) => setQ(e.target.value)}
            placeholder="Buscar entre los escritos…"
            aria-label="Buscar entre los escritos"
          />
        </label>
        <CustomSelect
          value={year}
          onChange={setYear}
          ariaLabel="Filtrar por año"
          options={[
            { value: 'all', label: 'Todos los años' },
            ...years.map(y => ({ value: y, label: String(y) })),
          ]}
        />
      </div>

      {/* Grid */}
      {pageItems.length === 0 ? (
        <div className="empty">No hay escritos que coincidan con esa búsqueda.</div>
      ) : (
        <div className="poems-grid">
          {pageItems.map((p, i) => (
            <PoemCard key={p.slug} poem={p} index={i} />
          ))}
        </div>
      )}

      {/* Pagination */}
      {totalPages > 1 && (
        <Pagination page={curPage} totalPages={totalPages} onPage={setPage} />
      )}
    </section>
  );
}

function Pagination({ page, totalPages, onPage }) {
  // Build page tokens with ellipses: 1 ... p-1 p p+1 ... N
  const tokens = [];
  const push = (t) => tokens.push(t);
  const set = new Set();
  const add = (n) => { if (n >= 1 && n <= totalPages && !set.has(n)) { set.add(n); push(n); } };
  add(1);
  for (let i = page - 1; i <= page + 1; i++) add(i);
  add(totalPages);
  // sort and inject ellipses
  const sorted = [...set].sort((a, b) => a - b);
  const withDots = [];
  for (let i = 0; i < sorted.length; i++) {
    if (i > 0 && sorted[i] - sorted[i - 1] > 1) withDots.push('…');
    withDots.push(sorted[i]);
  }
  return (
    <nav className="pagination" aria-label="Paginación">
      <button className="edge" disabled={page === 1}
        onClick={() => onPage(page - 1)}>← Anterior</button>
      {withDots.map((t, i) =>
        t === '…'
          ? <span key={'e' + i} className="ellipsis">·</span>
          : <button key={t} className={t === page ? 'active' : ''}
              onClick={() => onPage(t)}>{t}</button>
      )}
      <button className="edge" disabled={page === totalPages}
        onClick={() => onPage(page + 1)}>Siguiente →</button>
    </nav>
  );
}

// ——— Poem page ——————————————————————————————————————————————
function PoemPage({ slug }) {
  const poem = window.POEMS.find(p => p.slug === slug);
  if (!poem) {
    return (
      <section className="poem-page" data-screen-label="Poema no encontrado">
        <div className="poem-page-inner">
          <p className="poem-page-year">404</p>
          <h1 className="poem-page-title">Este poema se extravió en el cajón.</h1>
          <button className="poem-page-back" onClick={() => navigate('/escritos')}>
            ← Volver a los escritos
          </button>
        </div>
      </section>
    );
  }
  return (
    <article className="poem-page" data-screen-label={`Poema · ${poem.title}`}>
      <div className="poem-page-hero" aria-hidden="true">
        <PlaceholderImage variant={poem.image} label={poem.image} />
      </div>
      <div className="poem-page-inner">
        <h1 className="poem-page-title">{poem.title}</h1>
        <p className="poem-page-year">{poem.year}</p>
        <pre className="poem-page-body">{poem.body}</pre>
        <p className="poem-page-sig">— Aurelia</p>
        <div className="poem-page-divider" aria-hidden="true"
          dangerouslySetInnerHTML={{ __html: window.Botanicals.divider() }} />
        <button className="poem-page-back" onClick={() => navigate('/escritos')}>
          ← Volver a los escritos
        </button>
      </div>
    </article>
  );
}

// ——— Footer —————————————————————————————————————————————————
function Footer() {
  const year = new Date().getFullYear();
  return (
    <footer className="footer" data-screen-label="Pie">
      <p className="footer-name">Auropoesía</p>
      <p className="footer-sub">Hecho con cariño para Aurelia.</p>
      <p className="footer-fine">© {year}</p>
    </footer>
  );
}

// ——— App ————————————————————————————————————————————————————
function App() {
  const route = useRoute();
  return (
    <>
      <div className="bg-wash-wrap" aria-hidden="true"
        dangerouslySetInnerHTML={{ __html: window.Botanicals.bgWash() }} />
      <Nav route={route} />
      <main>
        {route.name === 'home' && (
          <>
            <Hero />
            <HomeFeatured />
          </>
        )}
        {route.name === 'escritos' && <Escritos />}
        {route.name === 'poem' && <PoemPage slug={route.slug} />}
        {route.name === 'about' && (
          <div style={{ paddingTop: 80 }}>
            <About />
          </div>
        )}
      </main>
      <Footer />
      <TweaksLayer />
    </>
  );
}

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