// BoltLabs sections — Brief v2
const { useState, useEffect, useRef } = React;

function useInView(opts = {}) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const once = opts.once !== false; // default: once = true
    // Synchronous check: if already in viewport on mount, fire immediately
    const rect = ref.current.getBoundingClientRect();
    const vh = window.innerHeight || document.documentElement.clientHeight;
    if (rect.top < vh && rect.bottom > 0) {
      setInView(true);
      if (once) return;
    }
    const obs = new IntersectionObserver(([e]) => {
      if (once) {
        if (e.isIntersecting) {
          setInView(true);
          obs.disconnect();
        }
      } else {
        setInView(e.isIntersecting);
      }
    }, { threshold: opts.threshold ?? 0.15, rootMargin: opts.rootMargin ?? '0px 0px -8% 0px' });
    obs.observe(ref.current);
    // Safety fallback: ensure visible after 1.8s no matter what
    const t = setTimeout(() => setInView(true), 1800);
    return () => { obs.disconnect(); clearTimeout(t); };
  }, []);
  return [ref, inView];
}

// Scroll progress hook — returns 0..1 for an element's journey through viewport
function useScrollProgress() {
  const ref = useRef(null);
  const [progress, setProgress] = useState(0);
  useEffect(() => {
    if (!ref.current) return;
    let raf;
    const update = () => {
      if (!ref.current) return;
      const r = ref.current.getBoundingClientRect();
      const vh = window.innerHeight;
      // 0 when top hits bottom of viewport, 1 when bottom leaves top
      const total = vh + r.height;
      const passed = vh - r.top;
      const p = Math.max(0, Math.min(1, passed / total));
      setProgress(p);
    };
    const onScroll = () => {
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(update);
    };
    update();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
      cancelAnimationFrame(raf);
    };
  }, []);
  return [ref, progress];
}

function CountUp({ to, duration = 1400, suffix = '', prefix = '', decimals = 0, trigger }) {
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (!trigger) {
      setVal(0);
      return;
    }
    let raf, start;
    const step = (t) => {
      if (!start) start = t;
      const p = Math.min(1, (t - start) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setVal(to * eased);
      if (p < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [trigger, to, duration]);
  return <>{prefix}{val.toFixed(decimals)}{suffix}</>;
}

// Trendy reveal — stagger, blur, scale, directional variants
// kind: 'fade-up' | 'fade-in' | 'blur-up' | 'scale-up' | 'slide-left' | 'slide-right' | 'mask-up' | 'word'
function Reveal({ children, delay = 0, y = 28, kind = 'fade-up', duration = 900, as: Tag = 'div', className, style }) {
  const [ref, inView] = useInView();
  const ease = 'cubic-bezier(.22,.61,.36,1)';

  const variants = {
    'fade-up': {
      hidden: { opacity: 0, transform: `translate3d(0, ${y}px, 0)`, filter: 'blur(0px)' },
      show: { opacity: 1, transform: 'translate3d(0,0,0)', filter: 'blur(0px)' }
    },
    'fade-in': {
      hidden: { opacity: 0, transform: 'translate3d(0,0,0)', filter: 'blur(0px)' },
      show: { opacity: 1, transform: 'translate3d(0,0,0)', filter: 'blur(0px)' }
    },
    'blur-up': {
      hidden: { opacity: 0, transform: `translate3d(0, ${y}px, 0)`, filter: 'blur(14px)' },
      show: { opacity: 1, transform: 'translate3d(0,0,0)', filter: 'blur(0px)' }
    },
    'scale-up': {
      hidden: { opacity: 0, transform: `translate3d(0, ${y * 0.5}px, 0) scale(0.94)`, filter: 'blur(8px)' },
      show: { opacity: 1, transform: 'translate3d(0,0,0) scale(1)', filter: 'blur(0px)' }
    },
    'slide-left': {
      hidden: { opacity: 0, transform: `translate3d(${y * 1.4}px, 0, 0)`, filter: 'blur(0px)' },
      show: { opacity: 1, transform: 'translate3d(0,0,0)', filter: 'blur(0px)' }
    },
    'slide-right': {
      hidden: { opacity: 0, transform: `translate3d(-${y * 1.4}px, 0, 0)`, filter: 'blur(0px)' },
      show: { opacity: 1, transform: 'translate3d(0,0,0)', filter: 'blur(0px)' }
    },
    'mask-up': {
      hidden: { opacity: 1, transform: `translate3d(0, ${y}px, 0)`, filter: 'blur(0px)', clipPath: 'inset(100% 0 0 0)' },
      show: { opacity: 1, transform: 'translate3d(0,0,0)', filter: 'blur(0px)', clipPath: 'inset(0% 0 0 0)' }
    }
  };

  const v = variants[kind] || variants['fade-up'];
  const state = inView ? v.show : v.hidden;

  return (
    <Tag ref={ref} className={className} style={{
      ...style,
      ...state,
      willChange: 'transform, opacity, filter',
      transition: `opacity ${duration}ms ${ease} ${delay}ms, transform ${duration}ms ${ease} ${delay}ms, filter ${duration}ms ${ease} ${delay}ms, clip-path ${duration}ms ${ease} ${delay}ms`
    }}>{children}</Tag>);

}

// Word-by-word reveal for big headlines — splits on spaces and <br>
function RevealWords({ children, delay = 0, stagger = 60, kind = 'blur-up', duration = 800, className, style }) {
  // Walk children and split text nodes into spans
  const parts = [];
  let counter = 0;
  const walk = (node) => {
    if (typeof node === 'string') {
      const tokens = node.split(/(\s+)/);
      tokens.forEach((tok) => {
        if (!tok) return;
        if (/^\s+$/.test(tok)) {
          parts.push(<span key={`s${counter++}`}>{tok}</span>);
        } else {
          parts.push({ __word: true, key: counter++, text: tok });
        }
      });
    } else if (Array.isArray(node)) {
      node.forEach(walk);
    } else if (node && node.type === 'br') {
      parts.push(<br key={`br${counter++}`} />);
    } else if (node && node.props && node.props.children) {
      // Wrap inline element (em, span etc) — treat as a single word unit
      parts.push({ __word: true, key: counter++, el: node });
    } else if (node) {
      parts.push(node);
    }
  };
  walk(children);

  let wordIdx = 0;
  return (
    <span className={className} style={{ display: 'inline', ...style }}>
      {parts.map((p, i) => {
        if (p && p.__word) {
          const myDelay = delay + wordIdx * stagger;
          wordIdx++;
          return (
            <Reveal key={p.key ?? i} as="span" kind={kind} delay={myDelay} duration={duration} y={20}
              style={{ display: 'inline-block', willChange: 'transform, opacity, filter' }}>
              {p.text ?? p.el}
            </Reveal>);

        }
        return p;
      })}
    </span>);

}

// ===== Scroll Progress Bar =====
function ScrollProgressBar() {
  const [p, setP] = useState(0);
  useEffect(() => {
    const update = () => {
      const scrollTop = window.scrollY;
      const max = document.documentElement.scrollHeight - window.innerHeight;
      setP(max > 0 ? scrollTop / max : 0);
    };
    update();
    window.addEventListener('scroll', update, { passive: true });
    window.addEventListener('resize', update);
    return () => {
      window.removeEventListener('scroll', update);
      window.removeEventListener('resize', update);
    };
  }, []);
  return (
    <div style={{
      position: 'fixed', top: 0, left: 0, right: 0,
      height: '2px', zIndex: 200, pointerEvents: 'none',
      background: 'transparent'
    }}>
      <div style={{
        height: '100%',
        width: `${p * 100}%`,
        background: 'linear-gradient(90deg, #1982fe, #111)',
        transition: 'width 80ms linear',
        transformOrigin: 'left'
      }}></div>
    </div>);

}

// ===== NAV =====
function Nav() {
  const [scrolled, setScrolled] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 20);
    window.addEventListener('scroll', onScroll);
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  // Close menu on resize to desktop
  useEffect(() => {
    const onResize = () => { if (window.innerWidth > 900) setMenuOpen(false); };
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);
  // Prevent body scroll when menu open
  useEffect(() => {
    document.body.style.overflow = menuOpen ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [menuOpen]);

  return (
    <React.Fragment>
      <nav className="nav" style={{
        background: scrolled || menuOpen ? 'rgba(250,250,250,0.95)' : 'transparent',
        backdropFilter: scrolled || menuOpen ? 'saturate(180%) blur(16px)' : 'none',
        borderBottom: scrolled ? '1px solid rgba(0,0,0,0.06)' : '1px solid transparent'
      }}>
        <div className="nav-inner">
          <a href="index.html" className="logo">
            <img src={window.__resources?.logoImg || "assets/boltlabs-logo.png"} alt="BoltLabs" className="logo-img" style={{ maxWidth: "145px", width: "auto" }} />
          </a>
          <div className="nav-links">
            <a href="index.html">{t('nav.boltreview')}</a>
            <a href="brands.html">{t('nav.brands')}</a>
            <a href="about.html">{t('nav.about')}</a>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
            <button onClick={() => window.toggleLang()} className="nav-lang-toggle" style={{
              background: 'none', border: '1px solid rgba(0,0,0,0.15)', borderRadius: '6px',
              padding: '4px 10px', fontSize: '13px', fontWeight: 600, cursor: 'pointer',
              color: '#333', letterSpacing: '0.02em'
            }}>{t('lang.toggle')}</button>
            <a href="index.html#cta" className="nav-cta">
              {t('nav.cta')}
            </a>
          </div>
          <button className="nav-hamburger" onClick={() => setMenuOpen(!menuOpen)} aria-label={t('nav.menu')}>
            <span className={`nav-hamburger-line ${menuOpen ? 'open' : ''}`}></span>
            <span className={`nav-hamburger-line ${menuOpen ? 'open' : ''}`}></span>
            <span className={`nav-hamburger-line ${menuOpen ? 'open' : ''}`}></span>
          </button>
        </div>
      </nav>
      {menuOpen && <div className="nav-mobile-overlay" onClick={() => setMenuOpen(false)}></div>}
      <div className={`nav-mobile-menu ${menuOpen ? 'nav-mobile-menu--open' : ''}`}>
        <a href="index.html" onClick={() => setMenuOpen(false)}>{t('nav.boltreview')}</a>
        <a href="brands.html" onClick={() => setMenuOpen(false)}>{t('nav.brands')}</a>
        <a href="about.html" onClick={() => setMenuOpen(false)}>{t('nav.about')}</a>
        <button onClick={() => { window.toggleLang(); setMenuOpen(false); }} style={{
          background: 'none', border: '1px solid rgba(0,0,0,0.15)', borderRadius: '6px',
          padding: '8px 16px', fontSize: '15px', fontWeight: 600, cursor: 'pointer',
          color: '#333', textAlign: 'center', margin: '8px 0'
        }}>{t('lang.toggle')}</button>
        <a href="index.html#cta" className="nav-mobile-cta" onClick={() => setMenuOpen(false)}>{t('nav.cta')}</a>
      </div>
    </React.Fragment>);

}

// ===== 1. HERO =====
function Hero() {
  const [ref, inView] = useInView({ threshold: 0.1 });
  // Parallax: dashboard mock subtly drifts up as user scrolls
  const [scrollY, setScrollY] = useState(0);
  useEffect(() => {
    const onScroll = () => setScrollY(window.scrollY);
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  const mockParallax = Math.min(80, scrollY * 0.18);
  const mockOpacity = Math.max(0.2, 1 - scrollY / 900);

  return (
    <section className="hero" data-screen-label="01 Hero" ref={ref}>
      <div className="hero-inner">
        <Reveal delay={0} kind="fade-up" y={16}>
          <div className="hero-eyebrow">
            <span className="dot"></span>
            {t('hero.eyebrow')}
          </div>
        </Reveal>
        <h1 className="hero-h1 hero-h1--gradient" style={{ lineHeight: "1", margin: "0px 0px 25.3203px", fontWeight: "700" }}>
          <RevealWords delay={120} stagger={70} kind="blur-up" duration={900}>
            {t('hero.h1.line1')}
          </RevealWords>
          <br />
          <RevealWords delay={520} stagger={70} kind="blur-up" duration={900}>
            <span className="hero-accent" style={{ fontWeight: "700" }}>{t('hero.h1.accent')}</span>{' '}{t('hero.h1.line2.rest')}
          </RevealWords>
        </h1>
        <Reveal delay={1080} kind="blur-up" y={16} duration={800}>
          <p className="hero-lede" style={{ fontFamily: "\"Apple SD Gothic Neo\"", fontSize: "18px", color: "rgb(0, 0, 0)" }}>
            {t('hero.lede.line1')}<br />
            {t('hero.lede.line2')}
          </p>
        </Reveal>
        <Reveal delay={1240} kind="fade-up" y={14}>
          <div className="hero-cta">
            <a href="#cta" className="btn-primary">
              {t('hero.btn.start')}
            </a>
            <a href="#feature" className="btn-ghost">
              <span>{t('hero.btn.how')}</span>
              <span className="arrow">{'\u2193'}</span>
            </a>
          </div>
        </Reveal>

        <Reveal delay={1380} kind="scale-up" y={32} duration={1100}>
          <div className="hero-mock" style={{
            transform: `translate3d(0, ${-mockParallax}px, 0)`,
            opacity: mockOpacity,
            transition: 'opacity 200ms linear'
          }}>
            <HeroDashboardMock />
          </div>
        </Reveal>

        <Reveal delay={1640} kind="fade-up" y={14}>
          <div className="hero-stats">
            <div className="hs-item">
              <div className="hs-val" style={{ fontWeight: "500" }}><CountUp to={3.2} decimals={1} trigger={inView} />{'\u00d7'}</div>
              <div className="hs-lbl" style={{ fontSize: "16px" }}>{t('hero.stat.cvr')}</div>
            </div>
            <div className="hs-divider"></div>
            <div className="hs-item">
              <div className="hs-val" style={{ fontWeight: "500" }}>+<CountUp to={56} trigger={inView} />%</div>
              <div className="hs-lbl" style={{ fontSize: "16px" }}>{t('hero.stat.sales')}</div>
            </div>
            <div className="hs-divider"></div>
            <div className="hs-item">
              <div className="hs-val" style={{ fontWeight: "500" }}>{t('hero.stat.free')}</div>
              <div className="hs-lbl" style={{ fontSize: "16px" }}>{t('hero.stat.price')}</div>
            </div>
          </div>
        </Reveal>
      </div>
    </section>);

}

function HeroDashboardMock() {
  return (
    <div className="hero-dash hero-dash--image">
      <img src={window.__resources?.heroDashboard || "assets/hero-dashboard.png"} alt={t('hero.dashboard.alt')} />
    </div>);

}

function HDRow({ on, name, cvr }) {
  return (
    <div className="hd-row">
      <span className={'hd-toggle' + (on ? ' on' : '')}><span></span></span>
      <span className="hd-row-name">{name}</span>
      <span className="hd-row-cvr">{cvr}</span>
    </div>);

}

// ===== 1.5 PARTNERS =====
function Partners() {
  const partners = [
    { name: t('partner.1'), logo: 'assets/logo-startup-agency.png' },
    { name: t('partner.2'), logo: 'assets/seoul-innovation-center.png' },
    { name: t('partner.3'), logo: 'assets/logo-kakao-mobility.png' },
    { name: t('partner.4'), logo: 'assets/logo-wellcare-station.png' },
    { name: t('partner.5'), logo: 'assets/logo-km-park.png' },
    { name: t('partner.6'), logo: 'assets/logo-olivazumo.png' },
    { name: t('partner.7'), logo: 'assets/logo-geonganghagae.png' },
    { name: t('partner.8'), logo: 'assets/logo-artmont.png' },
    { name: 'OKO101', logo: 'assets/logo-oko101.png' }];

  const items = [...partners, ...partners];
  return (
    <section className="partners-band" id="partners" data-screen-label="01b Partners">
      {/* Marquee Band */}
      <div className="pb-marquee-wrap">
        <div className="pb-marquee-head">
          <div className="pb-marquee-eyebrow">{t('partners.eyebrow')}</div>
          <div className="pb-marquee-meta"></div>
        </div>
        <div className="pb-marquee-fade">
          <div className="pb-marquee-track">
            {items.map((p, i) =>
              <div key={i} className="pb-marquee-item">
                <div className="pb-marquee-logo">
                  {p.logo ?
                    <img src={window.__resources?.[p.logo] || p.logo} alt={p.name} /> :
                    <div className="pb-logo-placeholder">LOGO</div>
                  }
                </div>
                <span className="pb-marquee-name">{p.name}</span>
              </div>
            )}
          </div>
        </div>
      </div>
    </section>);

}

// ===== 2. FEATURE =====
function Feature() {
  const features = [
    {
      n: '01',
      title: t('feature.1.title'),
      desc: t('feature.1.desc'),
      visual: <FeatureVisualMatch />
    },
    {
      n: '02',
      title: t('feature.2.title'),
      desc: t('feature.2.desc'),
      visual: <FeatureVisualSort />
    },
    {
      n: '03',
      title: t('feature.3.title'),
      desc: t('feature.3.desc'),
      visual: <FeatureVisualChart />
    }];

  return (
    <section className="feature" id="feature" data-screen-label="02 Feature">
      <div className="section-inner">
        <Reveal kind="fade-up">
          <div className="section-eyebrow" style={{ fontFamily: "\"Apple SD Gothic Neo\"", fontWeight: "700", fontSize: "18px" }}>{t('feature.eyebrow')}</div>
        </Reveal>
        <h2 className="section-h2" style={{ fontWeight: "500", color: "rgb(25, 130, 254)" }}>
          <RevealWords delay={120} stagger={60} kind="blur-up">
            <span style={{ color: "rgb(0, 0, 0)" }}>{t('feature.h2.line1')}</span>
          </RevealWords>
          <br />
          <RevealWords delay={420} stagger={60} kind="blur-up">
            {t('feature.h2.line2')}
          </RevealWords>
        </h2>
        <Reveal delay={780} kind="fade-up">
          <p className="section-lede">{t('feature.lede.line1')}<br />{t('feature.lede.line2')}</p>
        </Reveal>
        <div className="feature-grid">
          {features.map((f, i) =>
            <Reveal key={i} delay={i * 140} kind="scale-up" y={36} duration={1000}>
              <div className="feature-card">
                <div className="feature-visual">{f.visual}</div>
                <div className="feature-num">{f.n}</div>
                <h3 className="feature-title">{f.title}</h3>
                <p className="feature-desc">{f.desc}</p>
              </div>
            </Reveal>
          )}
        </div>
      </div>
    </section>);

}

function FeatureVisualMatch() {
  return (
    <div className="fv" style={{ padding: 0, background: '#fff' }}>
      <img src="assets/feature-match-cropped.png" alt={t('feature.match.alt')} style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block' }} />
    </div>);
}

function FeatureVisualSort() {
  return (
    <div className="fv fv-sort-v2">
      <div className="fv-sort-col">
        <div className="fv-sort-header fv-sort-header--a">{t('feature.sort.safety.header')}</div>
        <div className="fv-sort-item fv-sort-item--on"><span className="fv-sort-rank">1</span>{t('feature.sort.safety.review')}</div>
        <div className="fv-sort-item fv-sort-item--on"><span className="fv-sort-rank">2</span>{t('feature.sort.safety.review')}</div>
        <div className="fv-sort-item fv-sort-item--off"><span className="fv-sort-rank">3</span>{t('feature.sort.deodor.review')}</div>
      </div>
      <div className="fv-sort-col">
        <div className="fv-sort-header fv-sort-header--b">{t('feature.sort.deodor.header')}</div>
        <div className="fv-sort-item fv-sort-item--on"><span className="fv-sort-rank">1</span>{t('feature.sort.deodor.review')}</div>
        <div className="fv-sort-item fv-sort-item--on"><span className="fv-sort-rank">2</span>{t('feature.sort.deodor.review')}</div>
        <div className="fv-sort-item fv-sort-item--off"><span className="fv-sort-rank">3</span>{t('feature.sort.safety.review')}</div>
      </div>
    </div>);
}

function FeatureVisualChart() {
  return (
    <div className="fv fv-chart-v2">
      <div className="fv-chart-bars-h">
        <div className="fv-chart-group-h">
          <div className="fv-chart-label">{t('feature.chart.appealA')}</div>
          <div className="fv-chart-bar-wrap">
            <div className="fv-chart-bar fv-chart-bar--before" style={{ width: '36%' }}><span>3.7%</span></div>
            <div className="fv-chart-bar fv-chart-bar--after" style={{ width: '86%' }}><span>8.6%</span></div>
          </div>
        </div>
        <div className="fv-chart-group-h">
          <div className="fv-chart-label">{t('feature.chart.appealB')}</div>
          <div className="fv-chart-bar-wrap">
            <div className="fv-chart-bar fv-chart-bar--before" style={{ width: '32%' }}><span>3.1%</span></div>
            <div className="fv-chart-bar fv-chart-bar--after" style={{ width: '100%' }}><span>10.3%</span></div>
          </div>
        </div>
      </div>
      <div className="fv-chart-legend">
        <span><span className="fv-chart-dot fv-chart-dot--before"></span>{t('feature.chart.before')}</span>
        <span><span className="fv-chart-dot fv-chart-dot--after"></span>{t('feature.chart.after')}</span>
      </div>
    </div>);
}

window.useInView = useInView;
window.useScrollProgress = useScrollProgress;
window.CountUp = CountUp;
window.Reveal = Reveal;
window.RevealWords = RevealWords;
window.ScrollProgressBar = ScrollProgressBar;
window.Nav = Nav;
window.Hero = Hero;
window.Partners = Partners;
window.Feature = Feature;
