import { useStore } from '@nanostores/react';
import { useEffect, useRef, useState } from 'react';
import cx from '@src/cx.mjs';
import { useT } from '@src/i18n.mjs';
import { $projects, $playing, $resetPending, parseMeta, fmt } from './panel/ProjectsTab.jsx';

// Barra de transporte estilo Spotify, FIJA debajo del editor de código:
//   · fila superior: controles CENTRADOS (anterior / play-pausa / siguiente)
//   · fila inferior: tiempo transcurrido · barra ARRASTRABLE (seek) · duración
// La barra permite saltar a un segundo concreto del loop (click o arrastre;
// el salto se aplica al soltar). Pausar recuerda la posición y reanudar
// continúa desde ahí (scheduler.setCycle). Arrastrar con el tema parado fija
// el punto desde el que arrancará el play.
export function TransportBar({ context }) {
  const projects = useStore($projects);
  const playingName = useStore($playing);
  const [, tick] = useState(0);
  const t = useT();
  const [dragFrac, setDragFrac] = useState(null); // fracción bajo el dedo mientras se arrastra
  const pausedAtRef = useRef(null); // ciclo (dentro del loop) donde se pausó
  const barRef = useRef(null);

  // refresco de la barra (~8 fps)
  useEffect(() => {
    const id = setInterval(() => tick((t) => (t + 1) % 1e9), 120);
    return () => clearInterval(id);
  }, []);

  // al cambiar de tema se descarta la posición de pausa (era de otro loop)
  useEffect(() => {
    pausedAtRef.current = null;
  }, [playingName]);

  const editor = () => context.editorRef.current;
  const ed = editor();
  const sch = ed?.repl?.scheduler;
  const started = !!sch?.started;

  // longitud del loop = del código que está REALMENTE en el editor (lo que suena)
  const meta = parseMeta(ed?.code ?? '');
  const loopCycles = Math.max(meta.loopCycles || 1, 1e-6);
  const cps = (started && sch?.cps ? sch.cps : meta.cps) || 0.5;

  // posición dentro del loop: sonando → scheduler; pausado → posición recordada;
  // arrastrando → manda el dedo (solo visual hasta soltar)
  const pausedAt = pausedAtRef.current;
  const nowCycle = started ? (sch?.now?.() ?? 0) : (pausedAt ?? 0);
  const posCycle = ((nowCycle % loopCycles) + loopCycles) % loopCycles;
  const frac = dragFrac ?? posCycle / loopCycles;
  const shownCycle = dragFrac != null ? dragFrac * loopCycles : posCycle;
  const totalSec = loopCycles / cps;
  const elapsedSec = frac * totalSec;
  const pct = `${(Math.min(Math.max(frac, 0), 1) * 100).toFixed(1)}%`;

  const displayed = projects.slice().reverse();
  const curIdx = displayed.findIndex((x) => x.name === playingName);

  // ── SEEK: saltar a un punto concreto del loop ──
  const seekTo = (f) => {
    const e = editor();
    if (!e) return;
    const target = Math.min(Math.max(f, 0), 0.999) * loopCycles;
    const s = e.repl?.scheduler;
    if (s?.started) {
      // mantenemos la iteración actual del arrange y movemos solo la fase
      const base = Math.floor((s.now?.() ?? 0) / loopCycles) * loopCycles;
      s.setCycle?.(base + target);
    } else {
      // parado/pausado: recordar el punto; play arrancará desde ahí
      pausedAtRef.current = target;
    }
  };

  const togglePlay = async () => {
    const e = editor();
    if (!e) return;
    const s = e.repl?.scheduler;
    if (s?.started) {
      // PAUSA: recuerda dónde íbamos (dentro del loop) y para el audio
      const now = s.now?.() ?? 0;
      pausedAtRef.current = ((now % loopCycles) + loopCycles) % loopCycles;
      e.stop();
    } else {
      // PLAY: si hay posición recordada (pausa o seek en parado), reanuda ahí
      const resume = pausedAtRef.current;
      pausedAtRef.current = null;
      await e.evaluate();
      if (resume != null) e.repl?.scheduler?.setCycle?.(resume);
    }
  };

  const skip = (dir) => {
    const e = editor();
    if (!e || !displayed.length) return;
    pausedAtRef.current = null; // cambiar de tema descarta la posición pausada
    const base = curIdx < 0 ? (dir > 0 ? -1 : 0) : curIdx;
    const idx = (base + dir + displayed.length) % displayed.length;
    const p = displayed[idx];
    e.setCode(p.code);
    $playing.set(p.name);
    $resetPending.set(true); // el track nuevo arranca desde el ciclo 0
    e.evaluate();
  };

  // ── scrubbing con puntero (click o arrastre; el salto se aplica al soltar) ──
  const fracFromEvent = (ev) => {
    const el = barRef.current;
    if (!el) return 0;
    const r = el.getBoundingClientRect();
    return Math.min(Math.max((ev.clientX - r.left) / r.width, 0), 1);
  };
  const onPointerDown = (ev) => {
    ev.preventDefault();
    ev.currentTarget.setPointerCapture?.(ev.pointerId);
    setDragFrac(fracFromEvent(ev));
  };
  const onPointerMove = (ev) => {
    if (dragFrac == null) return;
    setDragFrac(fracFromEvent(ev));
  };
  const onPointerUp = (ev) => {
    if (dragFrac == null) return;
    const f = fracFromEvent(ev);
    setDragFrac(null);
    seekTo(f);
  };

  // 5 marcas de ciclo debajo de la barra (0 … total)
  const marks = [0, 1, 2, 3, 4].map((i) => Math.round((loopCycles * i) / 4));

  const circle =
    'rounded-full border-2 border-muted flex items-center justify-center text-foreground hover:bg-cyan-400/10 hover:border-cyan-400/70 transition-colors shrink-0';

  return (
    <div className="shrink-0 border-t border-muted bg-lineHighlight px-4 pt-2 pb-1 flex flex-col gap-1 select-none">
      {/* fila 1: controles CENTRADOS (estilo Spotify) */}
      <div className="flex items-center justify-center gap-5">
        <button onClick={() => skip(-1)} title={t('previous')} className={cx(circle, 'w-10 h-10 text-lg')}>
          ⏮
        </button>
        <button
          onClick={togglePlay}
          title={started ? t('pause') : t('play')}
          className={cx(circle, 'w-12 h-12 text-xl', started && 'border-cyan-400 text-cyan-300 bg-cyan-400/10')}
        >
          {started ? '⏸' : '▶'}
        </button>
        <button onClick={() => skip(1)} title={t('next')} className={cx(circle, 'w-10 h-10 text-lg')}>
          ⏭
        </button>
      </div>

      {/* fila 2: transcurrido · BARRA ARRASTRABLE · duración */}
      <div className="flex items-center gap-3">
        <div className="text-xs font-bold tabular-nums text-cyan-300 w-12 text-right shrink-0">{fmt(elapsedSec)}</div>
        <div className="flex-1 min-w-0">
          <div className="relative">
            {/* número flotante = ciclo actual (sigue al dedo al arrastrar) */}
            <div
              className="absolute -top-3.5 -translate-x-1/2 text-[11px] font-bold text-cyan-300 tabular-nums pointer-events-none whitespace-nowrap"
              style={{ left: pct }}
            >
              {Math.floor(shownCycle)}
            </div>
            {/* pista clicable / arrastrable */}
            <div
              ref={barRef}
              onPointerDown={onPointerDown}
              onPointerMove={onPointerMove}
              onPointerUp={onPointerUp}
              className="group h-5 flex items-center cursor-pointer touch-none"
              title={t('seekHint')}
            >
              <div className="relative h-1.5 group-hover:h-2.5 w-full rounded-full bg-muted/50 transition-all">
                <div
                  className={cx(
                    'absolute left-0 top-0 h-full rounded-full',
                    dragFrac != null ? 'bg-cyan-300' : 'bg-cyan-400',
                  )}
                  style={{ width: pct }}
                />
                {/* tirador (visible al pasar el ratón o arrastrar) */}
                <div
                  className={cx(
                    'absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-3 h-3 rounded-full bg-foreground shadow transition-opacity',
                    dragFrac != null ? 'opacity-100' : 'opacity-0 group-hover:opacity-100',
                  )}
                  style={{ left: pct }}
                />
              </div>
            </div>
            {/* números de ciclo a lo largo de la barra */}
            <div className="relative h-3.5 text-[10px] opacity-60 tabular-nums pointer-events-none">
              {marks.map((label, i) => (
                <span
                  key={i}
                  className={cx(
                    'absolute top-0',
                    i === 0 && 'left-0',
                    i === 4 && 'right-0',
                    i > 0 && i < 4 && '-translate-x-1/2',
                  )}
                  style={i > 0 && i < 4 ? { left: `${i * 25}%` } : undefined}
                >
                  {label}
                </span>
              ))}
            </div>
          </div>
        </div>
        <div className="text-right shrink-0 leading-tight w-14">
          <div className="text-xs font-bold tabular-nums">{fmt(totalSec)}</div>
          <div className="text-[9px] opacity-60 tabular-nums whitespace-nowrap">
            {Math.floor(shownCycle)}/{Math.round(loopCycles)} {t('cycles')}
          </div>
        </div>
      </div>
    </div>
  );
}
