'use client';

import { useEffect, useRef, useState } from 'react';
import { alpha, useThemeColor } from '@djangocfg/ui-core/styles/palette';
import { useAnalyser } from '../../hooks/useAnalyser';
import { useElementWidth } from '../../hooks/useResizeObserver';
import { usePlayerAudio, usePlayerControls, usePlayerLevels } from '../../context/selectors';
import { attachHover, attachSeek } from './waveformInteraction';
import { paintLive } from './waveformRenderer';

type Props = {
  height: number;
  barWidth: number;
  barGap: number;
  seekStartsPlayback?: boolean;
};

export function LiveWaveform({ height, barWidth, barGap, seekStartsPlayback }: Props) {
  const audio = usePlayerAudio();
  const controls = usePlayerControls();
  const store = usePlayerLevels();
  const [container, setContainer] = useState<HTMLDivElement | null>(null);
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const fgHex = useThemeColor('primary');
  const mutedHex = useThemeColor('muted-foreground');
  const colorRef = useRef(fgHex);
  colorRef.current = fgHex;
  useElementWidth(container);

  useAnalyser(audio, store, true);

  // rAF paint loop reads from the imperative store. Zero React renders.
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    let raf = 0;
    const tick = () => {
      if (typeof document !== 'undefined' && document.hidden) {
        raf = requestAnimationFrame(tick);
        return;
      }
      paintLive(canvas, store.getCurrent(), {
        color: colorRef.current,
        barWidth,
        barGap,
        minBarHeight: 1,
      });
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [store, barWidth, barGap]);

  useEffect(() => {
    if (!container) return;
    const detachSeek = attachSeek(container, audio, {
      startsPlayback: seekStartsPlayback,
      onPlayRequest: () => void controls.play(),
    });
    const detachHover = attachHover(container, audio);
    return () => {
      detachSeek();
      detachHover();
    };
  }, [audio, container, controls, seekStartsPlayback]);

  return (
    <div
      ref={setContainer}
      className="audioplayer-waveform relative w-full select-none cursor-pointer"
      style={{ height }}
      data-mode="live"
    >
      <canvas ref={canvasRef} className="absolute inset-0 h-full w-full" aria-hidden="true" />
      <div
        className="audioplayer-hover pointer-events-none absolute top-0 bottom-0 w-px transition-opacity"
        style={{
          left: 'var(--hp, -10px)',
          opacity: 'var(--ho, 0)',
          backgroundColor: alpha(mutedHex, 0.5),
        }}
        aria-hidden="true"
      />
      <div
        data-audioplayer-time-tip
        className="audioplayer-tip pointer-events-none absolute -top-7 -translate-x-1/2 rounded bg-foreground px-1.5 py-0.5 text-[10px] tabular-nums text-background transition-opacity"
        style={{
          left: 'var(--hp, -100px)',
          opacity: 'var(--ht, 0)',
        }}
        aria-hidden="true"
      />
    </div>
  );
}
