'use client';

// Lazy peaks fetch with module-cache + in-flight dedupe. Triggers on first
// `play()`, IntersectionObserver visibility, or explicit `decodeOnMount` flag.

import { useEffect, useState } from 'react';
import { getPeaks, getPeaksFromCache } from '../audio/peaksCache';

export type UsePeaksOptions = {
  src: string;
  enabled?: boolean;
  triggerRef?: React.RefObject<Element | null>;
  decodeOnMount?: boolean;
};

export function usePeaks(opts: UsePeaksOptions): {
  peaks: Float32Array | null;
  loading: boolean;
  error: unknown;
} {
  const { src, enabled = true, triggerRef, decodeOnMount = false } = opts;
  const cached = getPeaksFromCache(src) ?? null;
  const [peaks, setLocal] = useState<Float32Array | null>(cached);
  const [loading, setLoading] = useState<boolean>(!cached && enabled);
  const [error, setError] = useState<unknown>(null);

  useEffect(() => {
    if (!enabled) return;
    const hit = getPeaksFromCache(src);
    if (hit) {
      setLocal(hit);
      setLoading(false);
      return;
    }
    setLocal(null);
    setLoading(true);
    let cancelled = false;
    let started = false;

    const startDecode = () => {
      if (started) return;
      started = true;
      getPeaks(src)
        .then((p) => {
          if (cancelled) return;
          setLocal(p);
          setLoading(false);
        })
        .catch((e) => {
          if (cancelled) return;
          setError(e);
          setLoading(false);
        });
    };

    if (decodeOnMount || !triggerRef?.current || typeof IntersectionObserver === 'undefined') {
      startDecode();
      return () => {
        cancelled = true;
      };
    }

    const obs = new IntersectionObserver(
      (entries) => {
        for (const entry of entries) {
          if (entry.isIntersecting) {
            startDecode();
            obs.disconnect();
            break;
          }
        }
      },
      { rootMargin: '200px' },
    );
    obs.observe(triggerRef.current);
    return () => {
      cancelled = true;
      obs.disconnect();
    };
  }, [src, enabled, decodeOnMount, triggerRef]);

  return { peaks, loading, error };
}
