/* global React, EsIcon, STRINGS */
const { useState, useEffect, useRef, useMemo } = React;

// ── YouTube channel handle/id ───────────────────────────
// We use the handle URL — the channel's RSS feed needs a channel ID.
// We'll attempt multiple strategies: noembed, RSS via CORS proxy.
const CHANNEL_HANDLE = "Esmandautech";
const CHANNEL_URL = `https://www.youtube.com/@${CHANNEL_HANDLE}`;
const CHANNEL_ID = "UCzm0XVnwnkm7ZfmGlFv515w";

// ── Reveal-on-scroll hook ───────────────────────────────
// We arm the reveal system AFTER first paint by adding `.reveal-ready` to <html>.
// In-viewport elements get `.in` immediately so the hero is never blank;
// off-screen elements wait for IntersectionObserver.
function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll('.reveal');
    // Mark already-visible elements as 'in' BEFORE arming the hidden state — so they never flash empty
    const inView = (el) => {
      const r = el.getBoundingClientRect();
      return r.top < window.innerHeight * 0.95 && r.bottom > 0;
    };
    els.forEach(el => { if (inView(el)) el.classList.add('in'); });
    // Now arm the system
    document.documentElement.classList.add('reveal-ready');
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } });
    }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
    els.forEach(el => { if (!el.classList.contains('in')) io.observe(el); });
    return () => io.disconnect();
  }, []);
}

// ── Floating tech icons backdrop ────────────────────────
function FloatIcons() {
  const items = useMemo(() => ([
    { I: EsIcon.Controller, top: '12%', left: '6%', size: 56, dur: 18, delay: 0 },
    { I: EsIcon.Smartphone, top: '20%', right: '8%', size: 44, dur: 22, delay: 2 },
    { I: EsIcon.Headphones, top: '60%', left: '4%', size: 60, dur: 20, delay: 4 },
    { I: EsIcon.Wifi, top: '70%', right: '10%', size: 48, dur: 24, delay: 1 },
    { I: EsIcon.Laptop, top: '38%', left: '52%', size: 52, dur: 26, delay: 3 },
    { I: EsIcon.Power, top: '85%', left: '40%', size: 40, dur: 19, delay: 5 },
  ]), []);
  return (
    <div className="float-icons" aria-hidden="true">
      {items.map((it, i) => {
        const { I, size, dur, delay, ...pos } = it;
        return (
          <div key={i} className="float-icon" style={{ ...pos, width: size, height: size, animationDuration: `${dur}s`, animationDelay: `${delay}s` }}>
            <I />
          </div>
        );
      })}
    </div>
  );
}

// ── Hero rings (chevron motif) ──────────────────────────
function HeroRings() {
  const rings = [];
  for (let i = 0; i < 8; i++) {
    const size = 240 + i * 110;
    rings.push(
      <circle key={i} cx="0" cy="0" r={size}
        opacity={0.08 + i * 0.025}
        strokeWidth={i === 3 ? 1.6 : 0.8}
        style={i === 3 ? { filter: 'drop-shadow(0 0 8px var(--accent))', opacity: 0.55 } : null}
      />
    );
  }
  return (
    <div className="hero-rings" aria-hidden="true">
      <svg viewBox="-600 -600 1200 1200">
        <g>{rings}</g>
      </svg>
    </div>
  );
}

// ── Nav ─────────────────────────────────────────────────
function Nav({ lang, setLang, t }) {
  return (
    <header className="nav">
      <a className="mark" href="#top">
        <img src="assets/es-icon-blue.png" alt="ES" />
        <span>Esmandau</span>
      </a>
      <nav className="links">
        <a href="#about">{t.nav.about}</a>
        <a href="#videos">{t.nav.videos}</a>
        <a href="#collab">{t.nav.collabs}</a>
        <a href="#contact">{t.nav.contact}</a>
      </nav>
      <div className="right">
        <div className="lang" role="group" aria-label="Language">
          <button className={lang === 'es' ? 'active' : ''} onClick={() => setLang('es')}>ES</button>
          <button className={lang === 'en' ? 'active' : ''} onClick={() => setLang('en')}>EN</button>
        </div>
      </div>
    </header>
  );
}

// ── Hero ────────────────────────────────────────────────
function Hero({ t, heroImage }) {
  return (
    <section className="hero" id="top">
      <div className="hero-bg">
        <div className="grid"></div>
        <div className="orb orb-1"></div>
        <div className="orb orb-2"></div>
      </div>
      <FloatIcons />
      <HeroRings />

      <div className="hero-text reveal">
        <h1 className="hero-title">
          {t.hero.title1}<br/>
          <span className="accent">{t.hero.title2}</span>
        </h1>
        <p className="lede">{t.hero.lede}</p>
        <div className="hero-actions">
          <a href="#contact" className="btn btn-primary">
            {t.hero.cta}
            <EsIcon.ArrowRight width="16" height="16" />
          </a>
          <a href={CHANNEL_URL} target="_blank" rel="noreferrer" className="btn btn-ghost">
            <EsIcon.YouTube width="18" height="18" />
            {t.hero.ctaSecondary}
          </a>
        </div>
      </div>

      <div className="portrait reveal" style={{ transitionDelay: '.15s' }}>
        <span className="corner tl"></span>
        <span className="corner tr"></span>
        <span className="corner bl"></span>
        <span className="corner br"></span>
        {heroImage ? (
          <img src={heroImage} alt="Hernán — Esmandau" />
        ) : (
          <div className="placeholder">
            <div>
              <div className="pl-icon"><EsIcon.Sparkle width="28" height="28" /></div>
              <div className="pl-label">[ portrait · drop image here ]</div>
            </div>
          </div>
        )}
        <div className="badge"><span className="dot"></span>{t.hero.live}</div>
      </div>
    </section>
  );
}

// ── About ───────────────────────────────────────────────
function About({ t }) {
  return (
    <section id="about">
      <div className="about-grid">
        <div className="reveal">
          <h2 className="section-title">
            {t.about.title1}<br/>
            <span className="accent">{t.about.titleAccent}</span>
          </h2>
          <p className="kicker">{t.about.copy}</p>
          <div className="about-feat">
            {t.about.feats.map((f, i) => (
              <div key={i} className="item">
                <div className="lbl">{f.lbl}</div>
                <div className="val">{f.val}</div>
              </div>
            ))}
          </div>
        </div>
        <div className="feature-card reveal" style={{ transitionDelay: '.1s' }}>
          <div className="ring"></div>
          <div className="yt-mark">
            <EsIcon.YouTube width="20" height="14" />
            {t.about.featureMark}
          </div>
          <div>
            <div className="big">100<span className="unit">K+</span></div>
            <div className="sub">{t.about.featureSub}</div>
          </div>
          <a href={CHANNEL_URL} target="_blank" rel="noreferrer" className="btn btn-ghost" style={{ alignSelf: 'flex-start', marginTop: 24 }}>
            <EsIcon.YouTube width="16" height="12" />
            @esmandautech
          </a>
        </div>
      </div>
    </section>
  );
}

// ── Videos slider with live YouTube fetch ───────────────
function Videos({ t, lang }) {
  const [videos, setVideos] = useState(null); // null = loading, [] = error
  const [index, setIndex] = useState(0);
  const trackRef = useRef(null);
  const [perView, setPerView] = useState(3);

  useEffect(() => {
    const update = () => {
      const w = window.innerWidth;
      if (w < 700) setPerView(1);
      else if (w < 1180) setPerView(2);
      else setPerView(3);
    };
    update();
    window.addEventListener('resize', update);
    return () => window.removeEventListener('resize', update);
  }, []);

  useEffect(() => {
    let cancelled = false;
    async function fetchVideos() {
      // file:// protocol breaks CORS proxy fetches; warn + show fallback immediately.
      if (location.protocol === 'file:') {
        console.warn('[Esmandau] Videos slider needs to be served over http(s); CORS proxies are blocked under file://. Use a local server or open via the design tab.');
        if (!cancelled) setVideos([]);
        return;
      }
      const rssUrl = `https://www.youtube.com/feeds/videos.xml?channel_id=${CHANNEL_ID}`;
      const proxies = [
        `https://api.allorigins.win/raw?url=${encodeURIComponent(rssUrl)}`,
        `https://corsproxy.io/?${encodeURIComponent(rssUrl)}`,
        `https://api.codetabs.com/v1/proxy/?quest=${encodeURIComponent(rssUrl)}`,
      ];
      for (const url of proxies) {
        try {
          const res = await fetch(url);
          if (!res.ok) continue;
          const text = await res.text();
          const doc = new DOMParser().parseFromString(text, 'text/xml');
          const entries = [...doc.getElementsByTagName('entry')].slice(0, 5);
          if (!entries.length) continue;
          const list = entries.map(e => {
            const id = e.getElementsByTagName('yt:videoId')[0]?.textContent || '';
            const title = e.getElementsByTagName('title')[0]?.textContent || '';
            const published = e.getElementsByTagName('published')[0]?.textContent || '';
            return {
              id, title, published,
              url: `https://www.youtube.com/watch?v=${id}`,
              thumb: `https://i.ytimg.com/vi/${id}/hqdefault.jpg`,
            };
          });
          if (!cancelled) setVideos(list);
          return;
        } catch (e) { console.warn('[Esmandau] proxy failed:', url, e); }
      }
      if (!cancelled) setVideos([]);
    }
    fetchVideos();
    return () => { cancelled = true; };
  }, []);

  const formatAgo = (iso) => {
    if (!iso) return '';
    const ago = STRINGS[lang].videos.ago;
    const diff = (Date.now() - new Date(iso).getTime()) / 1000;
    if (diff < 60) return ago.just;
    if (diff < 3600) return `${Math.floor(diff/60)} ${ago.min}`;
    if (diff < 86400) return `${Math.floor(diff/3600)} ${ago.hour}`;
    if (diff < 86400*7) return `${Math.floor(diff/86400)} ${ago.day}`;
    if (diff < 86400*30) return `${Math.floor(diff/86400/7)} ${ago.week}`;
    if (diff < 86400*365) return `${Math.floor(diff/86400/30)} ${ago.month}`;
    return `${Math.floor(diff/86400/365)} ${ago.year}`;
  };

  const cardWidth = 360 + 24; // card + gap
  const totalCards = videos ? videos.length + 1 : 0;
  // Measure the actual visible track width so the last step lands flush with the right edge.
  const [trackVisibleWidth, setTrackVisibleWidth] = useState(0);
  useEffect(() => {
    if (!trackRef.current) return;
    const wrap = trackRef.current.parentElement; // .track-wrap
    const measure = () => {
      const cs = getComputedStyle(wrap);
      const padL = parseFloat(cs.paddingLeft) || 0;
      const padR = parseFloat(cs.paddingRight) || 0;
      setTrackVisibleWidth(wrap.clientWidth - padL - padR);
    };
    measure();
    const ro = new ResizeObserver(measure);
    ro.observe(wrap);
    return () => ro.disconnect();
  }, []);
  // total content width: N cards * 360 + (N-1) * 24 gap
  const trackContentWidth = totalCards > 0 ? (totalCards * 360 + (totalCards - 1) * 24) : 0;
  const maxOffset = Math.max(0, trackContentWidth - trackVisibleWidth);
  // Index-based step still drives navigation, but we cap the actual translate to maxOffset.
  const stepIndexMax = Math.max(0, totalCards - perView);
  const safeIndex = Math.min(index, stepIndexMax);
  const desiredOffset = safeIndex * cardWidth;
  const offset = Math.min(desiredOffset, maxOffset);
  const transform = `translateX(-${offset}px)`;
  const atEnd = offset >= maxOffset - 1;

  const prev = () => setIndex(i => Math.max(0, i - 1));
  const next = () => setIndex(i => Math.min(stepIndexMax, i + 1));

  return (
    <section id="videos" className="videos full">
      <div className="inner">
        <div className="head reveal">
          <div>
            <h2 className="section-title">
              {t.videos.title1} <span className="accent">{t.videos.titleAccent}</span>
            </h2>
            <p className="kicker" style={{ marginTop: 16 }}>{t.videos.kicker}</p>
          </div>
          <div className="nav-btns">
            <button onClick={prev} disabled={!videos || index === 0} aria-label="Previous">
              <EsIcon.ArrowLeft width="18" height="18" />
            </button>
            <button onClick={next} disabled={!videos || atEnd} aria-label="Next">
              <EsIcon.ArrowRight width="18" height="18" />
            </button>
          </div>
        </div>

        <div className="track-wrap reveal" style={{ transitionDelay: '.1s' }}>
          <div className="track" ref={trackRef} style={{ transform }}>
            {videos === null && (
              [...Array(5)].map((_, i) => (
                <div key={i} className="video-card skeleton">
                  <div className="thumb"></div>
                  <div className="meta">
                    <div className="title">&nbsp;</div>
                    <div className="when">&nbsp;</div>
                  </div>
                </div>
              ))
            )}
            {videos && videos.length > 0 && videos.map(v => (
              <a key={v.id} href={v.url} target="_blank" rel="noreferrer" className="video-card">
                <div className="thumb">
                  <img src={v.thumb} alt={v.title} loading="lazy" />
                  <div className="play">
                    <div className="circle"><EsIcon.Play width="22" height="22" /></div>
                  </div>
                </div>
                <div className="meta">
                  <div className="title">{v.title}</div>
                  <div className="when"><span className="accent">●</span> {formatAgo(v.published)}</div>
                </div>
              </a>
            ))}
            {videos && videos.length > 0 && (
              <a href={CHANNEL_URL} target="_blank" rel="noreferrer" className="video-card cta-card">
                <div className="cta-inner">
                  <div className="cta-icon"><EsIcon.YouTube width="40" height="28" /></div>
                  <div className="cta-title">{t.videos.ctaTitle}</div>
                  <div className="cta-sub">{t.videos.ctaSub}</div>
                  <div className="cta-btn">
                    {t.videos.visitChannel}
                    <EsIcon.ArrowRight width="14" height="14" />
                  </div>
                </div>
              </a>
            )}
            {videos && videos.length === 0 && (
              <div className="videos-fallback">
                {t.videos.error}
                <a href={CHANNEL_URL} target="_blank" rel="noreferrer">{t.videos.visitChannel}</a>
              </div>
            )}
          </div>
        </div>
      </div>
    </section>
  );
}

// ── Collaborations ──────────────────────────────────────
function Collab({ t }) {
  const brands = [
    { name: 'Apple',    src: 'assets/brand-apple.png',    invert: true,  bigger: true },
    { name: 'Samsung',  src: 'assets/brand-samsung.png',  invert: false },
    { name: 'Motorola', src: 'assets/brand-motorola.png', invert: true },
    { name: 'Claro',    src: 'assets/brand-claro.png',    invert: false },
    { name: 'Anker',    src: 'assets/brand-anker.png',    invert: false },
    { name: 'abxylute', src: 'assets/brand-abxylute.png', invert: false },
    { name: 'AT&T',     src: 'assets/brand-att.png',      invert: false },
    { name: 'T-Mobile', src: 'assets/brand-tmobile.png',  invert: false, bigger: true },
  ];
  // Duplicate for seamless infinite scroll
  const looped = [...brands, ...brands];
  return (
    <section id="collab" className="collab">
      <div className="reveal" style={{ textAlign: 'center', maxWidth: 720, margin: '0 auto' }}>
        <h2 className="section-title">
          {t.collab.title1} <span className="accent">{t.collab.titleAccent}</span>
        </h2>
      </div>
      <div className="marquee reveal" style={{ transitionDelay: '.1s' }}>
        <div className="marquee-track">
          {looped.map((b, i) => (
            <img
              key={i}
              src={b.src}
              alt={b.name}
              className={`brand-logo ${b.invert ? 'invert' : ''} ${b.bigger ? 'bigger' : ''}`}
            />
          ))}
        </div>
      </div>
    </section>
  );
}

// ── Contact form ────────────────────────────────────────
function Contact({ t }) {
  const [form, setForm]       = useState({ name: '', email: '', message: '' });
  const [sent, setSent]       = useState(false);
  const [sending, setSending] = useState(false);
  const [error, setError]     = useState(false);

  const submit = async (e) => {
    e.preventDefault();
    setSending(true);
    setError(false);
    try {
      const body = new FormData();
      Object.entries(form).forEach(([k, v]) => body.append(k, v));
      const res = await fetch('/contact', { method: 'POST', body });
      if (!res.ok) throw new Error('Network error');
      setSent(true);
    } catch {
      setError(true);
    } finally {
      setSending(false);
    }
  };
  const u = (k) => (e) => setForm(f => ({ ...f, [k]: e.target.value }));

  return (
    <section id="contact" className="contact">
      <div className="reveal">
        <h2 className="section-title">
          {t.contact.title1} <span className="accent">{t.contact.titleAccent}</span>
        </h2>
        <p className="kicker">{t.contact.kicker}</p>
        <div className="contact-aside" style={{ marginTop: 40 }}>
          <div className="item">
            <div className="ico"><EsIcon.Mail width="20" height="20" /></div>
            <div>
              <div className="lbl">{t.contact.emailLabel}</div>
              <div className="val"><a href="mailto:hernan@esmandau.com">hernan@esmandau.com</a></div>
            </div>
          </div>
          <div className="item">
            <div className="ico"><EsIcon.YouTube width="22" height="16" /></div>
            <div>
              <div className="lbl">{t.contact.youtubeLabel}</div>
              <div className="val"><a href={CHANNEL_URL} target="_blank" rel="noreferrer">@esmandautech</a></div>
            </div>
          </div>
        </div>
      </div>
      <div className="form reveal" style={{ transitionDelay: '.1s' }}>
        {!sent ? (
          <form name="contact" onSubmit={submit}>
            <div className="field">
              <label>{t.contact.labels.name}</label>
              <input required type="text" name="name" placeholder={t.contact.placeholders.name} value={form.name} onChange={u('name')} />
            </div>
            <div className="field">
              <label>{t.contact.labels.email}</label>
              <input required type="email" name="email" placeholder={t.contact.placeholders.email} value={form.email} onChange={u('email')} />
            </div>
            <div className="field">
              <label>{t.contact.labels.message || 'Mensaje'}</label>
              <textarea required name="message" rows="4" placeholder={t.contact.placeholders.message || 'Cuéntanos sobre tu propuesta...'} value={form.message} onChange={u('message')} style={{ resize: 'vertical' }} />
            </div>
            {error && (
              <p style={{ color: '#ff5577', fontSize: 13, margin: '0 0 8px', letterSpacing: '.01em' }}>
                Something went wrong — please try again or email hernan@esmandau.com directly.
              </p>
            )}
            <button type="submit" className="btn btn-primary" disabled={sending}>
              <EsIcon.Send width="16" height="16" />
              {sending ? '...' : t.contact.submit}
            </button>
          </form>
        ) : (
          <div className="form-success">
            <div className="check"><EsIcon.Check width="28" height="28" /></div>
            <div style={{ fontSize: 22, fontWeight: 600, marginBottom: 10 }}>{t.contact.success}</div>
            <div style={{ color: 'var(--es-ink-dim)', fontSize: 15, lineHeight: 1.5 }}>{t.contact.successCopy}</div>
          </div>
        )}
      </div>
    </section>
  );
}

// ── Footer ──────────────────────────────────────────────
function Footer({ t }) {
  return (
    <footer>
      <div className="inner">
        <div className="brand">
          <img src="assets/es-icon-blue.png" alt="ES" />
          <span className="name">Esmandau</span>
        </div>
        <div className="socials">
          <a href={CHANNEL_URL} target="_blank" rel="noreferrer" aria-label="YouTube"><EsIcon.YouTube width="22" height="16" /></a>
          <a href="https://instagram.com/esmandau" target="_blank" rel="noreferrer" aria-label="Instagram"><EsIcon.Instagram width="20" height="20" /></a>
          <a href="https://threads.net/@esmandau" target="_blank" rel="noreferrer" aria-label="Threads"><EsIcon.Threads width="20" height="20" /></a>
          <a href="https://facebook.com/esmandau" target="_blank" rel="noreferrer" aria-label="Facebook"><EsIcon.Facebook width="20" height="20" /></a>
          <a href="mailto:hernan@esmandau.com" aria-label="Email"><EsIcon.Mail width="20" height="20" /></a>
        </div>
        <div className="copy">{t.footer.rights}</div>
      </div>
    </footer>
  );
}

// ── Tweaks panel ────────────────────────────────────────
function TweaksOverlay({ tweaks, setTweak }) {
  const { TweaksPanel, TweakSection, TweakSlider } = window;
  if (!TweaksPanel) return null;
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection title="Color">
        <TweakSlider label="Accent hue" value={tweaks.accentHue} min={210} max={260} step={1}
          onChange={(v) => setTweak('accentHue', v)} formatValue={(v) => `${v}°`} />
      </TweakSection>
      <TweakSection title="Background">
        <TweakSlider label="Darkness" value={tweaks.bgDarkness} min={0} max={1} step={0.05}
          onChange={(v) => setTweak('bgDarkness', v)} formatValue={(v) => v.toFixed(2)} />
      </TweakSection>
    </TweaksPanel>
  );
}

// ── App root ────────────────────────────────────────────
function App({ heroImage }) {
  const detectLang = () => {
    // Spanish is the default. Only honor a stored override if the user
    // explicitly switched to English in a previous visit.
    const stored = localStorage.getItem('es-lang');
    if (stored === 'en') return 'en';
    return 'es';
  };
  const [lang, setLang] = useState(detectLang);
  useEffect(() => { localStorage.setItem('es-lang', lang); document.documentElement.lang = lang; }, [lang]);
  const t = STRINGS[lang];

  // Tweaks
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "accentHue": 230, "bgDarkness": 1 }/*EDITMODE-END*/;
  const useTweaks = window.useTweaks;
  const [tweaks, setTweak] = useTweaks ? useTweaks(TWEAK_DEFAULTS) : [TWEAK_DEFAULTS, () => {}];

  useEffect(() => {
    document.documentElement.style.setProperty('--accent-hue', tweaks.accentHue);
    document.documentElement.style.setProperty('--bg-darkness', tweaks.bgDarkness);
  }, [tweaks.accentHue, tweaks.bgDarkness]);

  useReveal();

  return (
    <>
      <Nav lang={lang} setLang={setLang} t={t} />
      <main>
        <Hero t={t} heroImage={heroImage} />
        <About t={t} />
        <Videos t={t} lang={lang} />
        <Collab t={t} />
        <Contact t={t} />
      </main>
      <Footer t={t} />
      <TweaksOverlay tweaks={tweaks} setTweak={setTweak} />
    </>
  );
}

window.EsmandauApp = App;
