// Components for Óscar Sala portfolio site

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

// ---- helpers --------------------------------------------------------------

function useT(lang) {
  return useCallback((node) => {
    if (node == null) return "";
    if (typeof node === "string") return node;
    if (typeof node === "object" && node[lang]) return node[lang];
    if (typeof node === "object" && node.es) return node.es;
    return String(node);
  }, [lang]);
}

function useReveal() {
  const ref = useRef(null);
  const [visible, setVisible] = useState(false);
  useEffect(() => {
    if (!ref.current || visible) return;
    const obs = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => { if (e.isIntersecting) { setVisible(true); obs.disconnect(); } });
      },
      { threshold: 0.12, rootMargin: "0px 0px -8% 0px" }
    );
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, [visible]);
  return [ref, visible];
}

function Reveal({ children, delay = 0, as: Tag = "div", className = "", style = {}, ...rest }) {
  const [ref, visible] = useReveal();
  return (
    <Tag
      ref={ref}
      className={className + " reveal" + (visible ? " is-visible" : "")}
      style={{ transitionDelay: visible ? delay + "ms" : "0ms", ...style }}
      {...rest}
    >
      {children}
    </Tag>
  );
}

// ---- Top bar --------------------------------------------------------------

function TopBar({ lang, setLang, sectionInView }) {
  const t = useT(lang);
  const [open, setOpen] = useState(false);
  const [scrolled, setScrolled] = useState(false);

  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 24);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  const items = [
    ["bio", I18N.nav.bio],
    ["media", I18N.nav.media],
    ["awards", I18N.nav.awards],
    ["education", I18N.nav.education],
    ["teaching", I18N.nav.teaching],
    ["contact", I18N.nav.contact],
  ];

  const goTo = (id) => {
    setOpen(false);
    const el = document.getElementById(id);
    if (el) window.scrollTo({ top: el.offsetTop - 8, behavior: "smooth" });
  };

  return (
    <header className={"topbar" + (scrolled ? " is-scrolled" : "") + (open ? " is-open" : "")}>
      <div className="topbar__inner">
        <button className="topbar__brand" onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}>
          <span className="topbar__brand-mark" aria-hidden="true">
            <img src="assets/sax-logo-96.png" alt="" width="28" height="28" />
          </span>
          <span className="topbar__brand-name">Óscar Sala</span>
        </button>

        <nav className="topbar__nav">
          {items.map(([id, label]) => (
            <button
              key={id}
              className={"topbar__link" + (sectionInView === id ? " is-active" : "")}
              onClick={() => goTo(id)}
            >
              {t(label)}
            </button>
          ))}
        </nav>

        <div className="topbar__lang">
          {["es", "val", "en"].map((code) => (
            <button
              key={code}
              className={"lang-pill" + (lang === code ? " is-active" : "")}
              onClick={() => setLang(code)}
              aria-label={code}
            >
              {code.toUpperCase()}
            </button>
          ))}
        </div>

        <button
          className="topbar__menu-btn"
          aria-label="menu"
          onClick={() => setOpen((o) => !o)}
        >
          <span /><span /><span />
        </button>
      </div>

      {open && (
        <div className="topbar__sheet">
          {items.map(([id, label]) => (
            <button key={id} className="topbar__sheet-link" onClick={() => goTo(id)}>
              {t(label)}
            </button>
          ))}
          <div className="topbar__sheet-lang">
            {["es", "val", "en"].map((code) => (
              <button
                key={code}
                className={"lang-pill" + (lang === code ? " is-active" : "")}
                onClick={() => setLang(code)}
              >
                {code.toUpperCase()}
              </button>
            ))}
          </div>
        </div>
      )}
    </header>
  );
}

// ---- Hero -----------------------------------------------------------------

function Hero({ lang, heroLayout }) {
  const t = useT(lang);
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    const img = new Image();
    img.onload = () => setLoaded(true);
    img.src = "assets/oscar-portrait.jpg";
  }, []);

  return (
    <section className={"hero hero--" + heroLayout} id="top">
      <div className="hero__grid">
        <div className="hero__text">
          <div className={"hero__eyebrow" + (loaded ? " is-loaded" : "")}>
            <span className="hero__line" />
            <span>{t(I18N.hero.role)}</span>
          </div>
          <h1 className={"hero__title" + (loaded ? " is-loaded" : "")}>
            <span className="hero__title-line">Óscar</span>
            <span className="hero__title-line hero__title-line--it">Sala</span>
            <span className="hero__title-line">Esteve</span>
          </h1>
          <p className={"hero__sub" + (loaded ? " is-loaded" : "")}>
            {t(I18N.hero.sub)}
          </p>
          <div className={"hero__meta" + (loaded ? " is-loaded" : "")}>
            <span>{t(I18N.hero.location)}</span>
            <span className="hero__meta-dot">·</span>
            <span>Saxophone — Alto · Soprano</span>
          </div>
        </div>

        <div className={"hero__photo-wrap" + (loaded ? " is-loaded" : "")}>
          <div className="hero__photo-frame">
            <img
              src="assets/oscar-portrait.jpg"
              alt="Óscar Sala Esteve, retrato con saxofón"
              className="hero__photo"
            />
            <div className="hero__photo-tag">
              <span>01</span>
              <span>Portrait</span>
              <span>2025</span>
            </div>
          </div>
        </div>
      </div>

      <button
        className="hero__scroll"
        onClick={() => {
          const el = document.getElementById("bio");
          if (el) window.scrollTo({ top: el.offsetTop - 8, behavior: "smooth" });
        }}
      >
        <span>{t(I18N.hero.scroll)}</span>
        <span className="hero__scroll-arrow">↓</span>
      </button>
    </section>
  );
}

// ---- Bio ------------------------------------------------------------------

function Bio({ lang }) {
  const t = useT(lang);
  const paras = I18N.bio.paragraphs[lang] || I18N.bio.paragraphs.es;

  return (
    <section className="section section--bio" id="bio">
      <div className="section__inner section__inner--bio">
        <Reveal className="section__label">
          <span className="section__num">01</span>
          <span className="section__name">{t(I18N.bio.label)}</span>
        </Reveal>
        <Reveal className="bio__pull" delay={120}>
          {t(I18N.bio.pull)}
        </Reveal>
        <div className="bio__body">
          {paras.map((p, i) => (
            <Reveal key={i} as="p" className="bio__para" delay={200 + i * 80}>
              {p}
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

// ---- Media (videos) -------------------------------------------------------

function Media({ lang }) {
  const t = useT(lang);
  const [open, setOpen] = useState(null);

  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") setOpen(null); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = open ? "hidden" : "";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [open]);

  return (
    <section className="section section--media" id="media">
      <div className="section__inner">
        <Reveal className="section__label">
          <span className="section__num">02</span>
          <span className="section__name">{t(I18N.media.label)}</span>
        </Reveal>
        <Reveal className="section__sub" delay={100}>{t(I18N.media.sub)}</Reveal>

        <div className="media__grid">
          {SITE.videos.map((v, i) => (
            <Reveal key={v.id} className="video-card" delay={150 + i * 100}>
              <button
                className="video-card__btn"
                onClick={() => setOpen(v.id)}
                aria-label={t(I18N.media.play) + " — " + t(v.title)}
              >
                <div className="video-card__thumb-wrap">
                  <img
                    className="video-card__thumb"
                    src={`https://i.ytimg.com/vi/${v.id}/maxresdefault.jpg`}
                    onError={(e) => { e.target.src = `https://i.ytimg.com/vi/${v.id}/hqdefault.jpg`; }}
                    alt=""
                  />
                  <div className="video-card__overlay" />
                  <div className="video-card__play">
                    <svg viewBox="0 0 64 64" width="56" height="56" aria-hidden="true">
                      <circle cx="32" cy="32" r="31" fill="none" stroke="currentColor" strokeWidth="1" />
                      <path d="M26 22 L44 32 L26 42 Z" fill="currentColor" />
                    </svg>
                  </div>
                  <div className="video-card__corner">0{i + 1}</div>
                </div>
                <div className="video-card__meta">
                  <div className="video-card__title">{t(v.title)}</div>
                  <div className="video-card__caption">{t(v.caption)}</div>
                </div>
              </button>
            </Reveal>
          ))}
        </div>
      </div>

      {open && (
        <div className="lightbox" onClick={() => setOpen(null)}>
          <button className="lightbox__close" aria-label="close" onClick={() => setOpen(null)}>×</button>
          <div className="lightbox__frame" onClick={(e) => e.stopPropagation()}>
            <iframe
              src={`https://www.youtube.com/embed/${open}?autoplay=1&rel=0`}
              title="video"
              frameBorder="0"
              allow="autoplay; encrypted-media; fullscreen"
              allowFullScreen
            />
          </div>
        </div>
      )}
    </section>
  );
}

// ---- Awards ---------------------------------------------------------------

function Awards({ lang }) {
  const t = useT(lang);
  return (
    <section className="section section--awards" id="awards">
      <div className="section__inner">
        <Reveal className="section__label">
          <span className="section__num">03</span>
          <span className="section__name">{t(I18N.awards.label)}</span>
        </Reveal>
        <Reveal className="section__sub" delay={100}>{t(I18N.awards.sub)}</Reveal>

        <ol className="awards">
          {SITE.awards.map((a, i) => (
            <Reveal key={i} as="li" className="award" delay={120 + i * 60}>
              <span className="award__year">{a.year}</span>
              <div className="award__main">
                <span className="award__placement">{t(a.placement)}</span>
                <span className="award__title">{t(a.title)}</span>
              </div>
              <span className="award__where">{t(a.where)}</span>
            </Reveal>
          ))}
        </ol>
      </div>
    </section>
  );
}

// ---- Education ------------------------------------------------------------

function Education({ lang }) {
  const t = useT(lang);
  return (
    <section className="section section--education" id="education">
      <div className="section__inner">
        <Reveal className="section__label">
          <span className="section__num">04</span>
          <span className="section__name">{t(I18N.education.label)}</span>
        </Reveal>
        <Reveal className="section__sub" delay={100}>{t(I18N.education.sub)}</Reveal>

        <div className="edu">
          {SITE.education.map((e, i) => (
            <Reveal key={i} className="edu__row" delay={120 + i * 70}>
              <div className="edu__degree">{t(e.degree)}</div>
              <div className="edu__where">{e.where}</div>
              {e.with && <div className="edu__with">{t(e.with)}</div>}
            </Reveal>
          ))}
        </div>

        <Reveal className="masterclasses" delay={300}>
          <div className="masterclasses__label">{t(I18N.education.masterclassesLabel)}</div>
          <div className="masterclasses__list">
            {SITE.masterclasses.map((m, i) => (
              <span key={m} className="masterclasses__item">
                {m}
                {i < SITE.masterclasses.length - 1 && <span className="masterclasses__sep"> · </span>}
              </span>
            ))}
          </div>
        </Reveal>
      </div>
    </section>
  );
}

// ---- Teaching -------------------------------------------------------------

function Teaching({ lang }) {
  const t = useT(lang);
  const creds = I18N.teaching.creds[lang] || I18N.teaching.creds.es;
  return (
    <section className="section section--teaching" id="teaching">
      <div className="section__inner section__inner--teaching">
        <Reveal className="section__label">
          <span className="section__num">05</span>
          <span className="section__name">{t(I18N.teaching.label)}</span>
        </Reveal>
        <Reveal className="teaching__title" delay={120} as="h3">
          {t(I18N.teaching.title)}
        </Reveal>
        <Reveal className="teaching__body" delay={200} as="p">
          {t(I18N.teaching.body)}
        </Reveal>
        <Reveal className="teaching__creds" delay={280}>
          {creds.map((c, i) => (
            <span key={i} className="teaching__cred">
              <span className="teaching__cred-dot" />
              {c}
            </span>
          ))}
        </Reveal>
        <Reveal className="teaching__cta-wrap" delay={360}>
          <a className="cta" href={`mailto:${SITE.contact.email}`}>
            <span>{t(I18N.teaching.cta)}</span>
            <span className="cta__arrow">→</span>
          </a>
        </Reveal>
      </div>
    </section>
  );
}

// ---- Contact + Footer -----------------------------------------------------

function Contact({ lang }) {
  const t = useT(lang);
  return (
    <section className="section section--contact" id="contact">
      <div className="section__inner section__inner--contact">
        <Reveal className="section__label section__label--light">
          <span className="section__num">06</span>
          <span className="section__name">{t(I18N.contact.label)}</span>
        </Reveal>
        <Reveal className="contact__title" delay={120} as="h3">
          {t(I18N.contact.title)}
        </Reveal>

        <div className="contact__grid">
          <Reveal className="contact__col" delay={200}>
            <div className="contact__col-label">{t(I18N.contact.booking)}</div>
            <a className="contact__col-value" href={`mailto:${SITE.contact.booking}`}>
              {SITE.contact.booking}
            </a>
          </Reveal>
          <Reveal className="contact__col" delay={260}>
            <div className="contact__col-label">{t(I18N.contact.general)}</div>
            <a className="contact__col-value" href={`mailto:${SITE.contact.email}`}>
              {SITE.contact.email}
            </a>
          </Reveal>
          <Reveal className="contact__col" delay={320}>
            <div className="contact__col-label">{t(I18N.contact.follow)}</div>
            <a className="contact__col-value" href={`https://instagram.com/${SITE.contact.instagram.replace("@", "")}`} target="_blank" rel="noopener">
              Instagram · {SITE.contact.instagram}
            </a>
            <a className="contact__col-value" href={`https://youtube.com/${SITE.contact.youtube}`} target="_blank" rel="noopener">
              YouTube · {SITE.contact.youtube}
            </a>
          </Reveal>
        </div>

        <Reveal className="contact__big" delay={380}>
          <a href={`mailto:${SITE.contact.booking}`} className="contact__big-link">
            {SITE.contact.booking}
            <span className="contact__big-arrow">↗</span>
          </a>
        </Reveal>
      </div>

      <footer className="footer">
        <div className="footer__inner">
          <div className="footer__col">
            <div className="footer__brand">Óscar Sala Esteve</div>
            <div className="footer__sub">{t(I18N.hero.role)} · {t(I18N.hero.location)}</div>
          </div>
          <div className="footer__col footer__col--right">
            <div>oscarsala.com</div>
            <div>© {new Date().getFullYear()} · {t(I18N.footer.rights)}</div>
          </div>
        </div>
      </footer>
    </section>
  );
}

// ---- Section in-view tracker ---------------------------------------------

function useSectionInView(ids) {
  const [active, setActive] = useState(ids[0]);
  useEffect(() => {
    const handlers = [];
    const obs = new IntersectionObserver(
      (entries) => {
        // Pick the entry closest to top that is intersecting
        const visible = entries
          .filter((e) => e.isIntersecting)
          .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top);
        if (visible[0]) setActive(visible[0].target.id);
      },
      { rootMargin: "-30% 0px -55% 0px", threshold: 0.01 }
    );
    ids.forEach((id) => {
      const el = document.getElementById(id);
      if (el) { obs.observe(el); handlers.push(el); }
    });
    return () => obs.disconnect();
  }, [ids.join(",")]);
  return active;
}

Object.assign(window, {
  TopBar, Hero, Bio, Media, Awards, Education, Teaching, Contact,
  useSectionInView, useT, Reveal,
});
