// Anzeigenkette — main React app, scroll-driven
// Globals: window.AnzeigenkettenApp

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

/* ---------------- helpers ---------------- */
function useInView(opts = { threshold: 0.25 }) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) setInView(true);
    }, opts);
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return [ref, inView];
}

function useScrollY() {
  const [y, setY] = useState(0);
  useEffect(() => {
    let raf = 0;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        setY(window.scrollY);
        raf = 0;
      });
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return y;
}

function useCountUp(target, inView, duration = 1800, decimals = 0) {
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (!inView) return;
    const t0 = performance.now();
    let raf;
    const tick = (now) => {
      const t = Math.min(1, (now - t0) / duration);
      // ease out cubic
      const e = 1 - Math.pow(1 - t, 3);
      setVal(target * e);
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [inView, target, duration]);
  const formatted = useMemo(() => {
    if (decimals === 0) return Math.round(val).toLocaleString('de-DE');
    return val.toLocaleString('de-DE', { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
  }, [val, decimals]);
  return formatted;
}

/* ---------------- TOPBAR ---------------- */
function TopBar() {
  const y = useScrollY();
  return (
    <div className={'topbar' + (y > 60 ? ' scrolled' : '')}>
      <img src="assets/logo-dark.png" alt="Clementine Media" />
      <div className="meta"><b>Intern</b> · Demo · Anzeigenkette</div>
    </div>
  );
}

/* ---------------- HERO ---------------- */
function Hero() {
  const y = useScrollY();
  // celestial path during hero (uses a 5s autoloop on a sine)
  const [t, setT] = useState(0);
  useEffect(() => {
    let raf, t0 = performance.now();
    const tick = (now) => {
      setT(((now - t0) / 8000) % 1);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);
  // x: 5% → 95%, y: arc (sin)
  const x = 5 + t * 90;
  const arcY = 120 - Math.sin(t * Math.PI) * 70;  // top of arc near 50
  const isMoon = t > 0.6;
  const heroOpacity = Math.max(0, 1 - y / 600);

  return (
    <section className="hero">
      <div className="hero-skystrip" />
      <div
        className={'celestial' + (isMoon ? ' moon' : '')}
        style={{
          left: `${x}%`,
          top: `${arcY}px`,
          transform: 'translateX(-50%)'
        }}
      />
      <div className="stars on">
        {Array.from({ length: 22 }).map((_, i) => (
          <span key={i} className="star" style={{
            top: `${Math.random() * 180}px`,
            left: `${Math.random() * 100}%`,
            animationDelay: `${Math.random() * 3}s`,
            opacity: isMoon ? 1 : 0
          }} />
        ))}
      </div>

      <div className="hero-content" style={{ opacity: heroOpacity, transform: `translateY(${y * 0.2}px)` }}>
        <div className="hero-tag">
          <span className="dot" />
          Live-Beispiel · Stadt Ellwangen · Mai 2026
        </div>
        <h1>
          Eine Anzeige reicht nicht.<br />
          Eine <span className="accent">Kette</span> schon.
        </h1>
        <p className="sub">
          Wie Clementine Media über den Tag hinweg dieselben passenden Menschen erreicht — mit immer neuen Inhalten.
        </p>
      </div>

      <div className="scroll-cue" style={{ opacity: heroOpacity }}>
        Scroll, um den Tag eines passenden Kandidaten zu sehen
        <div className="arrow" />
      </div>
    </section>
  );
}

/* ---------------- SARAH ---------------- */
function SarahAvatar() {
  return (
    <svg viewBox="0 0 400 400">
      <defs>
        <linearGradient id="hairG" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stopColor="#a06236" />
          <stop offset="1" stopColor="#6e3e1d" />
        </linearGradient>
        <linearGradient id="bgG" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stopColor="#003a52" />
          <stop offset="1" stopColor="#001a26" />
        </linearGradient>
        <linearGradient id="orG" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stopColor="#f79520" />
          <stop offset="1" stopColor="#ef4137" />
        </linearGradient>
      </defs>
      <circle cx="200" cy="200" r="180" fill="url(#bgG)" />
      {/* concentric rings */}
      <circle cx="200" cy="200" r="170" fill="none" stroke="rgba(247,149,32,0.18)" strokeDasharray="2 6" />
      <circle cx="200" cy="200" r="150" fill="none" stroke="rgba(255,255,255,0.06)" />
      {/* shoulders */}
      <path d="M70 360 Q200 240 330 360 L330 400 L70 400 Z" fill="#0e3f54" />
      <path d="M70 360 Q200 240 330 360 L330 400 L70 400 Z" fill="none" stroke="rgba(255,255,255,0.08)" />
      {/* neck */}
      <rect x="180" y="220" width="40" height="40" fill="#e8c8a8" />
      {/* face */}
      <ellipse cx="200" cy="190" rx="58" ry="68" fill="#f0d4b3" />
      {/* hair */}
      <path d="M138 175 Q140 110 200 105 Q260 110 262 175 Q258 145 240 138 Q230 168 200 162 Q170 168 160 138 Q142 145 138 175 Z" fill="url(#hairG)" />
      <path d="M138 175 Q132 195 140 220 L150 200 Z" fill="url(#hairG)" />
      <path d="M262 175 Q268 195 260 220 L250 200 Z" fill="url(#hairG)" />
      {/* eyes */}
      <ellipse cx="180" cy="195" rx="4" ry="5" fill="#002a3c" />
      <ellipse cx="220" cy="195" rx="4" ry="5" fill="#002a3c" />
      {/* brows */}
      <path d="M170 182 Q180 178 192 182" stroke="#6e3e1d" strokeWidth="2" fill="none" strokeLinecap="round" />
      <path d="M208 182 Q220 178 230 182" stroke="#6e3e1d" strokeWidth="2" fill="none" strokeLinecap="round" />
      {/* mouth (subtle smile) */}
      <path d="M186 222 Q200 230 214 222" stroke="#a04020" strokeWidth="2.5" fill="none" strokeLinecap="round" />
      {/* accent dot top right */}
      <circle cx="305" cy="100" r="8" fill="url(#orG)" />
    </svg>
  );
}

function Sarah() {
  const [ref, inView] = useInView({ threshold: 0.3 });
  const bullets = [
    { num: '01', text: <><b>Verwaltungsfachwirtin, 34</b></> },
    { num: '02', text: <>Aktuell <b>Sachbearbeitung in einer Nachbargemeinde</b></> },
    { num: '03', text: <><b>AII-Abschluss</b> seit 18 Monaten</> },
    { num: '04', text: <>Wartet auf den nächsten <b>Karriereschritt</b></> },
    { num: '05', text: <>Wohnt im <b>30-km-Umkreis</b> der Stelle</> },
  ];
  return (
    <section className="sarah" ref={ref}>
      <div className="container">
        <div className="sarah-grid">
          <div className="sarah-avatar-wrap">
            <SarahAvatar />
          </div>
          <div className="sarah-text">
            <div className="eyebrow-mark">Profil · Passender Kandidat</div>
            <h2>Stellen Sie sich eine typische Bewerberin vor.</h2>
            <p className="sarah-lead">Wir folgen ihrem Tag — stellvertretend für die rund 14.000 passenden Profile, die diese Anzeigenkette in der Region erreicht.</p>
            <ul className="sarah-bullets">
              {bullets.map((b, i) => (
                <li
                  key={i}
                  className={inView ? 'in' : ''}
                  style={{ transitionDelay: `${i * 120}ms` }}
                >
                  <span className="bullet-num">{b.num}</span>
                  <span>{b.text}</span>
                </li>
              ))}
            </ul>
          </div>
        </div>
      </div>
    </section>
  );
}

window.TopBar = TopBar;
window.Hero = Hero;
window.Sarah = Sarah;
window.useInView = useInView;
window.useScrollY = useScrollY;
window.useCountUp = useCountUp;
