// wheel.jsx — drehbares Skill-Rad
// Großer Kreis am linken Bildrand, Nummern auf dem Kreisrand rotieren mit,
// Details (rechts) faden zum aktiven Skill.

const SKILLS = [
  {
    no: '01',
    name: 'Webdesign',
    kicker: 'interfaces that feel inevitable',
    body: 'Websites und Interfaces, die sich nicht nur gut ansehen, sondern sich richtig anfühlen. Von der ersten Wireframe-Skizze bis zum pixelgenauen Layout in der Browser-Engine.',
    deliverables: ['Landing Pages', 'Portfolio-Seiten', 'Interaktive One-Pager', 'Design-Systeme'],
    packages: [
      { name: 'One-Pager', price: '€ 890', lead: 'ab', meta: '5–7 Tage' },
      { name: 'Multi-Page', price: '€ 1.890', lead: 'ab', meta: '2–3 Wochen' },
      { name: 'Custom',    price: 'auf Anfrage', lead: '',  meta: 'Scope-Call' },
    ],
  },
  {
    no: '02',
    name: 'Programmierung',
    kicker: 'shipping code, not slideware',
    body: 'Saubere, wartbare Frontends. HTML, CSS, JavaScript, React — und das Wissen, wann man welches davon nicht braucht. Performance über Feature-Bloat.',
    deliverables: ['React / Next.js', 'Interaktive Prototypen', 'APIs & Integrationen', 'CMS-Anbindung'],
    packages: [
      { name: 'Component',  price: '€ 240', lead: 'ab', meta: 'pro Modul' },
      { name: 'Frontend',   price: '€ 2.400', lead: 'ab', meta: 'Full-Build' },
      { name: 'Retainer',   price: '€ 1.200', lead: '/Monat', meta: 'laufend' },
    ],
  },
  {
    no: '03',
    name: 'Videoschnitt',
    kicker: 'rhythm before everything',
    body: 'Schnitt, der atmet. Ob Social-Cut, Produkt-Film oder Longform-Doku — der Rhythmus entscheidet, ob jemand bleibt oder wegklickt.',
    deliverables: ['Social-Edits (9:16)', 'Produktvideos', 'YouTube-Content', 'Trailer & Teaser'],
    packages: [
      { name: 'Short-Cut',  price: '€ 180', lead: 'ab', meta: '< 60s' },
      { name: 'Standard',   price: '€ 540', lead: 'ab', meta: '1–3 min' },
      { name: 'Longform',   price: '€ 1.200', lead: 'ab', meta: '10+ min' },
    ],
  },
  {
    no: '04',
    name: 'Grafik Design',
    kicker: 'systems over artifacts',
    body: 'Identitäten, Editorial, Print. Grafik als System gedacht — damit jedes neue Artefakt in der gleichen Sprache spricht.',
    deliverables: ['Logo & Wortmarke', 'Brand-Systeme', 'Editorial Design', 'Social Templates'],
    packages: [
      { name: 'Logo',        price: '€ 640',  lead: 'ab', meta: 'inkl. 3 Varianten' },
      { name: 'Identity',    price: '€ 1.890', lead: 'ab', meta: 'Logo + Guidelines' },
      { name: 'Full Brand',  price: '€ 3.900', lead: 'ab', meta: 'Brand + Kollateral' },
    ],
  },
  {
    no: '05',
    name: 'Motion Graphics',
    kicker: 'moving pictures, moving people',
    body: 'Animationen, Titles, UI-Motion. Nicht Bewegung als Deko, sondern als Information — Timing ist die halbe Komposition.',
    deliverables: ['Logo-Animationen', 'UI-Motion', 'Explainer-Videos', 'Title-Sequenzen'],
    packages: [
      { name: 'Logo-Sting',  price: '€ 320',  lead: 'ab', meta: '3–5s' },
      { name: 'Explainer',   price: '€ 1.400', lead: 'ab', meta: '30–60s' },
      { name: 'Full Motion', price: '€ 2.900', lead: 'ab', meta: 'Campaign' },
    ],
  },
];

const N = SKILLS.length;
// Winkel pro Segment auf dem sichtbaren Kreis-Bogen. Das Rad steht
// links am Rand; nur ein Bogen ist sichtbar. Wir nutzen ±60° für 5 Items.
const STEP_DEG = 26; // Grad zwischen zwei Items

// Easing für sanftes Rad-Drehen
function easeOutCubic(t) { return 1 - Math.pow(1 - t, 3); }

function Wheel({ active, setActive, intensity, accent }) {
  const wrapRef = React.useRef(null);
  // rotation = Rad-Drehwinkel. Wenn active = 2, rotation = -2 * STEP_DEG
  // so dass Item #2 in der Mitte (bei 0°) steht.
  const targetRot = -active * STEP_DEG;
  const [rot, setRot] = React.useState(targetRot);
  const rafRef = React.useRef(null);
  const animRef = React.useRef(null);

  // Animiere rot → targetRot
  React.useEffect(() => {
    const startRot = rot;
    const delta = targetRot - startRot;
    if (Math.abs(delta) < 0.01) return;
    const dur = 620;
    const t0 = performance.now();
    cancelAnimationFrame(rafRef.current);
    const tick = (now) => {
      const p = Math.min(1, (now - t0) / dur);
      const e = easeOutCubic(p);
      setRot(startRot + delta * e);
      if (p < 1) rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, [targetRot]);

  // Scroll: akkumuliere Deltas, trigger active ±1 bei Schwelle
  React.useEffect(() => {
    const el = wrapRef.current;
    if (!el) return;
    let acc = 0;
    let cooldown = false;
    const onWheel = (e) => {
      // Nur innerhalb des Wheel-Containers reagieren, wenn Maus drin ist,
      // damit man die Seite normal scrollen kann, wenn außerhalb.
      e.preventDefault();
      if (cooldown) return;
      acc += e.deltaY;
      if (Math.abs(acc) > 60) {
        const dir = acc > 0 ? 1 : -1;
        setActive((a) => Math.max(0, Math.min(N - 1, a + dir)));
        acc = 0;
        cooldown = true;
        setTimeout(() => { cooldown = false; }, 380);
      }
    };
    el.addEventListener('wheel', onWheel, { passive: false });
    return () => el.removeEventListener('wheel', onWheel);
  }, [setActive]);

  // Drag (Pointer) — vertikale Bewegung rotiert das Rad
  React.useEffect(() => {
    const el = wrapRef.current;
    if (!el) return;
    let startY = 0;
    let startActive = 0;
    let dragging = false;
    const onDown = (e) => {
      if (e.target.closest('[data-no-drag]')) return;
      dragging = true;
      startY = e.clientY;
      startActive = active;
      el.setPointerCapture?.(e.pointerId);
      el.classList.add('is-dragging');
    };
    const onMove = (e) => {
      if (!dragging) return;
      const dy = e.clientY - startY;
      // 80px vertical drag ≈ 1 step
      const step = Math.round(dy / 80);
      const target = Math.max(0, Math.min(N - 1, startActive + step));
      if (target !== active) setActive(target);
    };
    const onUp = () => {
      dragging = false;
      el.classList.remove('is-dragging');
    };
    el.addEventListener('pointerdown', onDown);
    window.addEventListener('pointermove', onMove);
    window.addEventListener('pointerup', onUp);
    return () => {
      el.removeEventListener('pointerdown', onDown);
      window.removeEventListener('pointermove', onMove);
      window.removeEventListener('pointerup', onUp);
    };
  }, [active, setActive]);

  // Keyboard
  React.useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
        setActive((a) => Math.min(N - 1, a + 1));
      } else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
        setActive((a) => Math.max(0, a - 1));
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [setActive]);

  // Geometrie: Kreis-Mittelpunkt liegt links außerhalb des Viewports.
  // Container ist 2R × 2R (vmin) und wird so verschoben, dass sein LINKER
  // Rand bei cx liegt — das Zentrum landet bei cx + R.
  // Damit das Zentrum außerhalb des Viewports bleibt, muss cx + R < 0 sein.
  const R = 72;            // Radius in vmin
  const cx = -R - 18;      // linker Rand des 2R-Containers (vmin) → Zentrum bei -18vmin

  return (
    <div className="wheel" ref={wrapRef}>
      {/* Kreislinie (SVG) — rotiert nicht, Linie ist symmetrisch */}
      <svg className="wheel-ring" viewBox="-100 -100 200 200" preserveAspectRatio="xMidYMid meet"
           style={{
             left: `${cx}vmin`, top: '50%',
             width: `${R*2}vmin`, height: `${R*2}vmin`,
             transform: 'translateY(-50%)',
           }}>
        <circle cx="0" cy="0" r="100" fill="none"
                stroke="currentColor" strokeWidth="0.4" opacity="0.4" />
      </svg>

      {/* Rotierende Gruppe mit Nummern + Dots */}
      <div className="wheel-rotor" style={{
        left: `${cx}vmin`, top: '50%',
        width: `${R*2}vmin`, height: `${R*2}vmin`,
        transform: `translateY(-50%) rotate(${rot}deg)`,
      }}>
        {SKILLS.map((s, i) => {
          const a = i * STEP_DEG; // Winkel vom Zentrum (0 = rechts)
          const rad = a * Math.PI / 180;
          // Position auf dem Kreis (vmin-koord, rel. zu Rotor-Center)
          const x = Math.cos(rad) * R;
          const y = Math.sin(rad) * R;
          const isActive = i === active;
          return (
            <React.Fragment key={s.no}>
              {/* Dot */}
              <div className="wheel-dot" style={{
                left: `calc(50% + ${x}vmin)`,
                top:  `calc(50% + ${y}vmin)`,
                transform: 'translate(-50%, -50%)',
                opacity: isActive ? 1 : 0.55,
                scale: isActive ? 1.6 : 1,
              }} />
              {/* Nummer — nur gegenrotieren, damit sie immer aufrecht steht */}
              <button className={'wheel-num' + (isActive ? ' is-active' : '')}
                      data-no-drag
                      onClick={() => setActive(i)}
                      style={{
                        left: `calc(50% + ${x}vmin)`,
                        top:  `calc(50% + ${y}vmin)`,
                        transform: `translate(-50%, -50%) rotate(${-rot}deg)`,
                      }}>
                {s.no}
              </button>
            </React.Fragment>
          );
        })}
      </div>

      {/* Mittiges aktives Item */}
      <div className="wheel-center">
        <CenterPiece active={active} intensity={intensity} accent={accent} />
      </div>
    </div>
  );
}

// CenterPiece: die große Zahl + der Skill-Name mit Flip/Fade-Animation
function CenterPiece({ active, intensity, accent }) {
  const s = SKILLS[active];
  const [displayed, setDisplayed] = React.useState(s);
  const [phase, setPhase] = React.useState('in'); // 'in' | 'out'

  React.useEffect(() => {
    if (s === displayed) return;
    setPhase('out');
    const t = setTimeout(() => {
      setDisplayed(s);
      setPhase('in');
    }, 180);
    return () => clearTimeout(t);
  }, [active]);

  return (
    <div className={`center ${phase === 'out' ? 'is-out' : 'is-in'}`}
         data-intensity={intensity}>
      <div className="center-big" aria-hidden="true">
        <BigNumber n={displayed.no} />
      </div>
      <div className="center-meta">
        <div className="center-name">
          <span>{displayed.name}</span>
          <em style={{ background: accent }} />
        </div>
        <div className="center-kicker">{displayed.kicker}</div>
      </div>
    </div>
  );
}

// Große Zahl mit einzeln animierten Ziffern
function BigNumber({ n }) {
  return (
    <span className="big-num">
      {n.split('').map((ch, i) => (
        <span key={i} className="big-num-digit" style={{ animationDelay: `${i * 40}ms` }}>
          {ch}
        </span>
      ))}
    </span>
  );
}

Object.assign(window, { Wheel, SKILLS, N });
