/* PluginModes.jsx — Tour and Listen overlays on top of PluginShell.
   - Tour: scrim + spotlight + explainer card for each element.
   - Listen: faders locked, only preset/bypass/AB interactive. */

const { useState: _pm_us, useEffect: _pm_ue, useRef: _pm_ur, useMemo: _pm_um } = React;

// ─── TOUR STEPS ──────────────────────────────────────────────────────
// Each step targets a DOM selector inside the plugin shell (relative).
// text: body copy; title: short label; action: hint of what to try.
// watchKeys: fader keys in pluginState to monitor; the step completes when any
// of them change from the snapshot taken at step entry. Steps without watchKeys
// are purely informational and can be advanced manually.
const TOUR_STEPS = [
  {
    sel: '.mv-header',
    title: 'Header',
    body: 'Top strip of the plugin. Current preset name, nudge arrows between presets, Save / Delete, and the global Bypass — everything you reach before touching a fader.',
    action: 'Click the arrows or the preset name.',
  },
  {
    sel: '.mv-zone:nth-child(1)',
    title: 'Zone 1 — Start Here',
    body: 'Voice type (Off / Male / Female), input meter with rotary input gain, and POWER — the master drive that gives the whole chain its character.',
    action: 'Drag the POWER fader. Alt / Opt + click to reset.',
    watchKeys: ['power'],
  },
  {
    sel: '.mv-zone:nth-child(2)',
    title: 'Zone 2 — Creative',
    body: 'The five creative effects: FOCUS cuts the mud and pushes presence; FAT adds body; DOUBLER widens; REVERB creates depth; DELAY puts space between words.',
    action: 'Drag any fader. Alt / Opt + click to reset.',
    watchKeys: ['focus', 'fat', 'doubler', 'reverb', 'delay'],
  },
  {
    sel: '.mv-zone:nth-child(3)',
    title: 'Zone 3 — Clean Up',
    body: 'CLARITY adds air without the harshness; DE-ESS tames the sibilants. They work together: the more air you push, the more the de-esser earns its keep.',
    action: 'Drag Clarity or De-Ess. Alt / Opt + click to reset.',
    watchKeys: ['clarity', 'deess'],
  },
  {
    sel: '.mv-zone:nth-child(4)',
    title: 'Zone 4 — End Here',
    body: 'Output meter and final rotary gain. This is where you check you\u2019re not clipping on the way out of the plugin.',
    action: 'Drag the output fader. Alt / Opt + click to reset.',
    watchKeys: ['output'],
  },
  {
    sel: '.mv-auto-toggle',
    title: 'Auto Gain',
    body: 'The AUTO pill keeps your processed level matched to the dry signal, so EQ and compression moves are heard as shape, not as level. Saves you from second-guessing every fader.',
    action: 'Click AUTO to toggle.',
    watchKeys: ['autoGain'],
  },
  {
    sel: '.mv-zone:nth-child(2) .mv-control-icon--top',
    title: 'Bypass per effect',
    body: 'Every effect icon is a button. Tap it once to bypass that single FX, tap again to bring it back. Lets you A/B one element of the chain without unraveling the preset.',
    action: 'Click any effect icon.',
  },
  {
    sel: '.mv-zone:nth-child(2) .mv-zone-head',
    title: 'Bypass a whole zone',
    body: 'Tap a zone label — 1 Start Here, 2 Creative, or 3 Clean Up — to bypass everything inside it in one click. Tap again to bring the whole group back. Fastest way to A/B "with vs without the creative chain."',
    action: 'Click 2 Creative.',
  },
  {
    sel: '.mv-preset-big',
    title: 'Preset Selector',
    body: '58 factory presets across 7 genre categories with mood-tag filtering, favorites, and recent. Each loads a complete configuration you can refine from there.',
    action: 'Click to open the preset browser.',
  },
];

// ─── Hook: measure & track selector rect ─────────────────────────────
const useSelectorRect = (rootRef, sel, enabled) => {
  const [rect, setRect] = _pm_us(null);
  _pm_ue(() => {
    if (!enabled) { setRect(null); return; }
    const tick = () => {
      if (!rootRef.current || !sel) return;
      const root = rootRef.current;
      const target = root.querySelector(sel);
      const rr = root.getBoundingClientRect();
      if (!target) { setRect(null); return; }
      const tr = target.getBoundingClientRect();
      setRect({
        x: tr.left - rr.left,
        y: tr.top - rr.top,
        w: tr.width,
        h: tr.height,
      });
    };
    tick();
    const id = setInterval(tick, 120);
    window.addEventListener('resize', tick);
    return () => { clearInterval(id); window.removeEventListener('resize', tick); };
  }, [rootRef, sel, enabled]);
  return rect;
};

// ─── Mode toggle buttons (above the plugin) ──────────────────────────
const ModeButtons = ({ mode, setMode }) => (
  <div style={{
    display: 'flex', gap: 10,
    padding: 6,
    background: 'rgba(10,10,20,0.85)',
    border: '1px solid rgba(167,165,255,0.22)',
    borderRadius: 100, backdropFilter: 'blur(10px)',
  }}>
    {[
      { id: 'free',   label: 'Usar livremente',  color: 'rgba(255,255,255,.9)' },
      { id: 'tour',   label: 'Entenda o plugin', color: '#f5c518' },
      { id: 'listen', label: 'Escutar presets',  color: '#ff7ca8' },
    ].map(m => (
      <button key={m.id}
              onClick={() => setMode(m.id)}
              style={{
                padding: '10px 20px', borderRadius: 100, border: 'none',
                fontSize: 12, fontWeight: 700, letterSpacing: '.06em',
                cursor: 'pointer', fontFamily: 'var(--font-main)',
                background: mode === m.id ? m.color : 'transparent',
                color: mode === m.id ? '#0a0820' : m.color,
                boxShadow: mode === m.id ? `0 2px 14px ${m.color}55` : 'none',
                transition: 'all .15s',
              }}>
        {m.label}
      </button>
    ))}
  </div>
);

// ─── Tour overlay: scrim + cut-out + "?" markers + explainer card ────
const TOUR_ACCENT = '#a7a5ff';
const TourOverlay = ({ rootRef, pluginState, onClose }) => {
  const [stepIdx, setStepIdx] = _pm_us(0);
  const [actionDone, setActionDone] = _pm_us(false);
  const [snapshot, setSnapshot] = _pm_us(null);
  const step = TOUR_STEPS[stepIdx];
  const rect = useSelectorRect(rootRef, step.sel, true);

  // Take a snapshot of watched keys whenever the step changes.
  _pm_ue(() => {
    setActionDone(false);
    if (step.watchKeys && pluginState) {
      const snap = {};
      step.watchKeys.forEach(k => { snap[k] = pluginState[k]; });
      setSnapshot(snap);
    } else {
      setSnapshot(null);
    }
  }, [stepIdx]);

  // Detect if user has acted (changed any watched fader from snapshot).
  _pm_ue(() => {
    if (!snapshot || !pluginState || actionDone) return;
    const changed = Object.keys(snapshot).some(k =>
      Math.abs((pluginState[k] ?? 0) - (snapshot[k] ?? 0)) > 0.001);
    if (changed) setActionDone(true);
  }, [pluginState, snapshot, actionDone]);

  const waiting = !!(step.watchKeys && !actionDone);

  const [rootSize, setRootSize] = _pm_us({ w: 1000, h: 660 });
  _pm_ue(() => {
    if (!rootRef.current) return;
    const el = rootRef.current;
    const upd = () => setRootSize({ w: el.offsetWidth, h: el.offsetHeight });
    upd();
    const ro = new ResizeObserver(upd);
    ro.observe(el);
    return () => ro.disconnect();
  }, [rootRef]);

  if (!rect) return null;

  const pad = 4;
  // Clamp highlight rect so its stroke stays inside the plugin canvas.
  const hx = Math.max(pad, rect.x - pad);
  const hy = Math.max(pad, rect.y - pad);
  const hw = Math.min(rootSize.w - hx - pad, rect.w + pad * 2);
  const hh = Math.min(rootSize.h - hy - pad, rect.h + pad * 2);
  const cx = hx + hw / 2;
  const cy = hy + hh / 2;

  // "?" marker: nudged inside so it never clips on the plugin edge.
  const qSize = 32;
  const qX = Math.min(rootSize.w - qSize - 4, Math.max(4, rect.x + rect.w - qSize / 2));
  const qY = Math.min(rootSize.h - qSize - 4, Math.max(4, rect.y - qSize / 2));

  // Card position: right of rect if space, otherwise left; clamp to root.
  const cardW = 320;
  let cardX = rect.x + rect.w + 16;
  if (cardX + cardW > rootSize.w - 8) cardX = rect.x - cardW - 16;
  if (cardX < 8) cardX = 8;
  let cardY = Math.max(8, cy - 60);
  const cardH = 260;
  if (cardY + cardH > rootSize.h - 8) cardY = rootSize.h - cardH - 8;

  // Four backdrop-blur strips around the highlight (aperture-blur effect).
  // They cover everything OUTSIDE the highlight rect — no corner gaps.
  const stripStyle = {
    position: 'absolute', pointerEvents: 'auto',
    background: 'rgba(3,3,10,.78)',
    backdropFilter: 'blur(6px) saturate(80%)',
    WebkitBackdropFilter: 'blur(6px) saturate(80%)',
  };

  const goNext = () => {
    if (stepIdx === TOUR_STEPS.length - 1) onClose();
    else setStepIdx(stepIdx + 1);
  };
  const goPrev = () => setStepIdx((stepIdx - 1 + TOUR_STEPS.length) % TOUR_STEPS.length);

  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 50, pointerEvents: 'none',
      borderRadius: 10, overflow: 'hidden',
    }}>
      {/* Aperture blur scrim — four strips around the spotlight rect */}
      <div style={{ ...stripStyle, left: 0, right: 0, top: 0, height: hy }} onClick={goNext}/>
      <div style={{ ...stripStyle, left: 0, right: 0, top: hy + hh, bottom: 0 }} onClick={goNext}/>
      <div style={{ ...stripStyle, left: 0, width: hx, top: hy, height: hh }} onClick={goNext}/>
      <div style={{ ...stripStyle, left: hx + hw, right: 0, top: hy, height: hh }} onClick={goNext}/>

      {/* Highlight stroke — drawn as a div with INSET box-shadow so it never
          spills outside the plugin edge even when the target hugs the border. */}
      <div style={{
        position: 'absolute',
        left: hx, top: hy, width: hw, height: hh,
        borderRadius: 8,
        boxShadow: `inset 0 0 0 2px ${TOUR_ACCENT}, inset 0 0 18px rgba(167,165,255,.35), 0 0 0 1px rgba(167,165,255,.2)`,
        pointerEvents: 'none',
      }}/>

      {/* "?" marker — clamped inside the plugin bounds */}
      <div style={{
        position: 'absolute',
        left: qX, top: qY,
        width: qSize, height: qSize, borderRadius: '50%',
        background: TOUR_ACCENT, color: '#0a0820',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontSize: 18, fontWeight: 900,
        boxShadow: `0 0 0 3px rgba(167,165,255,.25), 0 0 24px rgba(167,165,255,.85)`,
        pointerEvents: 'none',
        animation: 'mv-pulse 1.8s ease-in-out infinite',
        zIndex: 2,
      }}>?</div>

      {/* Explainer card */}
      <div style={{
        position: 'absolute', left: cardX, top: cardY, width: cardW,
        background: 'linear-gradient(180deg, rgba(16,14,30,.96), rgba(10,8,20,.96))',
        border: `1px solid ${TOUR_ACCENT}72`,
        borderRadius: 12, padding: '18px 20px',
        pointerEvents: 'auto',
        boxShadow: `0 20px 60px rgba(0,0,0,.6), 0 0 0 1px rgba(167,165,255,.15)`,
        color: '#fff', fontFamily: 'var(--font-main)',
        zIndex: 3,
      }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
          <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '.2em', color: TOUR_ACCENT }}>
            STEP {stepIdx + 1} / {TOUR_STEPS.length}
          </div>
          <button onClick={onClose}
                  style={{ background: 'transparent', border: 'none', color: 'rgba(255,255,255,.5)', cursor: 'pointer', fontSize: 16, padding: 0, lineHeight: 1 }}>
            ✕
          </button>
        </div>
        <div style={{ fontSize: 18, fontWeight: 800, marginBottom: 10, letterSpacing: '-.01em' }}>{step.title}</div>
        <div style={{ fontSize: 13, lineHeight: 1.55, color: 'rgba(255,255,255,.82)', marginBottom: 14 }}>
          {step.body}
        </div>
        <div style={{
          fontSize: 11, fontWeight: 700, color: actionDone ? '#7dd3fc' : TOUR_ACCENT,
          marginBottom: 14, padding: '8px 10px',
          background: actionDone ? 'rgba(125,211,252,.08)' : 'rgba(167,165,255,.08)',
          borderRadius: 6,
          border: `1px solid ${actionDone ? 'rgba(125,211,252,.3)' : 'rgba(167,165,255,.25)'}`,
          display: 'flex', alignItems: 'center', gap: 8,
        }}>
          <span>{actionDone ? '✓' : '→'}</span>
          <span>{actionDone ? 'Nice — action detected.' : step.action}</span>
        </div>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'space-between', alignItems: 'center' }}>
          <button onClick={goPrev}
                  style={{ background: 'transparent', border: '1px solid rgba(255,255,255,.2)', color: 'rgba(255,255,255,.8)', padding: '7px 14px', borderRadius: 6, fontSize: 11, fontWeight: 700, cursor: 'pointer', letterSpacing: '.06em' }}>
            ← Prev
          </button>
          <div style={{ display: 'flex', gap: 4 }}>
            {TOUR_STEPS.map((_, i) => (
              <div key={i} onClick={() => setStepIdx(i)}
                   style={{ width: 6, height: 6, borderRadius: 3,
                            background: i === stepIdx ? TOUR_ACCENT : 'rgba(255,255,255,.25)',
                            cursor: 'pointer' }}/>
            ))}
          </div>
          {waiting ? (
            <button onClick={goNext}
                    title="Try the action above — or skip"
                    style={{ background: 'transparent', border: `1px solid ${TOUR_ACCENT}55`, color: `${TOUR_ACCENT}cc`, padding: '7px 14px', borderRadius: 6, fontSize: 11, fontWeight: 700, cursor: 'pointer', letterSpacing: '.06em' }}>
              Skip →
            </button>
          ) : (
            <button onClick={goNext}
                    style={{ background: TOUR_ACCENT, border: 'none', color: '#0a0820', padding: '7px 14px', borderRadius: 6, fontSize: 11, fontWeight: 800, cursor: 'pointer', letterSpacing: '.06em', boxShadow: `0 0 14px ${TOUR_ACCENT}55` }}>
              {stepIdx === TOUR_STEPS.length - 1 ? 'Finish' : 'Next →'}
            </button>
          )}
        </div>
      </div>
    </div>
  );
};

// ─── Listen-mode top bar: transport + AB + progress + preset chips ──
const ListenBar = ({ engine, activePresetId, onChoosePreset }) => {
  const isPlaying = engine.isPlaying;
  const isWet = engine.isWet;
  const buf = engine.buffers[engine.currentId];
  const dur = buf ? buf.duration : 0;
  const pos = engine.position;
  const pct = dur ? (pos / dur) * 100 : 0;
  const active = MV_PRESETS.find(p => p.id === activePresetId) || MV_PRESETS[0];
  const isReal = engine.hasRealWet(engine.currentId || activePresetId);
  const statusColor = isReal ? '#7dd3fc' : (isWet ? active.color : '#fbbf24');
  const statusLabel = isReal ? 'REAL STEMS' : (isWet ? 'PROCESSED' : 'RAW');

  const bars = _pm_um(() => Array.from({ length: 120 }, (_, i) =>
    0.25 + 0.75 * Math.abs(Math.sin(i * 0.7) * Math.cos(i * 0.22))), []);

  const seek = (e) => {
    const r = e.currentTarget.getBoundingClientRect();
    const p = (e.clientX - r.left) / r.width;
    if (dur) engine.seek(p * dur);
  };

  return (
    <div style={{
      width: 1000, padding: '14px 18px',
      background: 'rgba(10,10,20,0.92)',
      border: '1px solid rgba(167,165,255,0.28)',
      borderRadius: 14, backdropFilter: 'blur(10px)',
      boxShadow: '0 20px 60px -10px rgba(0,0,0,.6), 0 0 40px -10px rgba(167,165,255,.25)',
      color: '#fff', fontFamily: 'var(--font-main)',
      display: 'flex', flexDirection: 'column', gap: 12,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
        {/* Play/Pause */}
        <button onClick={() => engine.togglePlay(activePresetId)}
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 8,
                  padding: '10px 18px', borderRadius: 100, border: 'none',
                  background: isPlaying ? active.color : '#a7a5ff',
                  color: '#0a0820', fontWeight: 800, fontSize: 12,
                  letterSpacing: '.06em', cursor: 'pointer',
                  boxShadow: `0 2px 18px ${isPlaying ? active.color : '#a7a5ff'}55`,
                }}>
          {isPlaying
            ? <><svg width="10" height="10" viewBox="0 0 10 10"><rect x="2" y="1" width="2.2" height="8" fill="currentColor"/><rect x="5.8" y="1" width="2.2" height="8" fill="currentColor"/></svg> Pause</>
            : <><svg width="10" height="10" viewBox="0 0 10 10"><path d="M2 1 L9 5 L2 9 Z" fill="currentColor"/></svg> Play {active.name}</>}
        </button>

        {/* A/B toggle */}
        <div style={{ display: 'flex', background: 'rgba(255,255,255,.05)', border: '1px solid rgba(255,255,255,.1)', borderRadius: 100, padding: 3 }}>
          <button onClick={() => engine.setWet(false)}
                  style={{
                    padding: '7px 16px', borderRadius: 100, border: 'none',
                    background: !isWet ? '#fff' : 'transparent',
                    color: !isWet ? '#0a0820' : 'rgba(255,255,255,.6)',
                    fontSize: 11, fontWeight: 800, letterSpacing: '.08em', cursor: 'pointer',
                    fontFamily: 'var(--font-main)',
                  }}>
            A — Raw
          </button>
          <button onClick={() => engine.setWet(true)}
                  style={{
                    padding: '7px 16px', borderRadius: 100, border: 'none',
                    background: isWet ? active.color : 'transparent',
                    color: isWet ? '#0a0820' : 'rgba(255,255,255,.6)',
                    fontSize: 11, fontWeight: 800, letterSpacing: '.08em', cursor: 'pointer',
                    fontFamily: 'var(--font-main)',
                  }}>
            B — Magic Vocals
          </button>
        </div>

        {/* Scrubber */}
        <div onClick={seek}
             style={{
               flex: 1, minWidth: 160, height: 32,
               display: 'flex', alignItems: 'center', gap: 2,
               padding: '0 8px', cursor: 'pointer',
             }}>
          {bars.map((h, i) => {
            const lit = i / bars.length <= pct / 100;
            return <div key={i} style={{
              width: 2, borderRadius: 1,
              height: Math.max(4, h * 28),
              background: lit ? (isWet ? active.color : '#fbbf24') : 'rgba(167,165,255,.22)',
              boxShadow: lit ? `0 0 6px ${isWet ? active.color : '#fbbf24'}` : 'none',
              transition: 'background .1s',
            }}/>;
          })}
        </div>

        <div style={{
          fontSize: 10, fontWeight: 800, letterSpacing: '.18em',
          color: statusColor,
          minWidth: 90, textAlign: 'right',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'flex-end', gap: 6,
        }}>
          {isReal && <span style={{ width: 6, height: 6, borderRadius: 3, background: '#7dd3fc', boxShadow: '0 0 8px #7dd3fc' }}/>}
          {statusLabel}
        </div>
      </div>

      {/* Preset chips */}
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, justifyContent: 'center' }}>
        {MV_PRESETS.map(p => (
          <button key={p.id}
                  onClick={() => onChoosePreset(p)}
                  style={{
                    height: 30, padding: '0 14px',
                    borderRadius: 100,
                    border: `1px solid ${activePresetId === p.id ? p.color : 'rgba(255,255,255,.1)'}`,
                    background: activePresetId === p.id ? `${p.color}22` : 'rgba(255,255,255,.03)',
                    color: activePresetId === p.id ? '#fff' : 'rgba(255,255,255,.6)',
                    fontSize: 11, fontWeight: 700, letterSpacing: '.06em',
                    cursor: 'pointer',
                    boxShadow: activePresetId === p.id ? `0 0 14px ${p.color}55` : 'none',
                    fontFamily: 'var(--font-main)',
                  }}>
            {p.name}
          </button>
        ))}
      </div>
    </div>
  );
};

// ─── Listen-mode lock overlay (prevents fader dragging) ─────────────
const ListenLockOverlay = () => (
  <div style={{
    position: 'absolute', inset: 0, zIndex: 25, pointerEvents: 'none',
    borderRadius: 10,
    background: 'linear-gradient(180deg, transparent 0%, rgba(255,124,168,.04) 100%)',
  }}>
    {/* Allow Bypass chip + preset selector + zone headers to be clicked.
        We block only the fader regions via per-zone overlays. */}
    <div style={{
      position: 'absolute', left: 0, right: 0, top: 82, bottom: 0,
      pointerEvents: 'auto',
      background: 'transparent',
    }}
    onPointerDown={(e) => {
      // Block fader interaction but keep pointer-events live
      // for preset/bypass chips in the header (which is above top:82).
      const target = e.target;
      const interactive = target.closest('.mv-preset-big, .mv-nudge, .mv-chip, .mv-voice-pill');
      if (!interactive) {
        e.stopPropagation();
        e.preventDefault();
      }
    }}/>
  </div>
);

Object.assign(window, { ModeButtons, TourOverlay, ListenBar, ListenLockOverlay });
