import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { hapticEngine, loadSoundEnabled, loadSoundVolume, type SoundCue } from '../audio/hapticEngine';

type SoundContextValue = {
  enabled: boolean;
  volume: number;
  setEnabled: (v: boolean) => void;
  setVolume: (v: number) => void;
  play: (cue: SoundCue) => void;
  preview: (cue?: SoundCue) => void;
};

const SoundContext = createContext<SoundContextValue | null>(null);

export function SoundProvider({ children }: { children: React.ReactNode }) {
  const [enabled, setEnabledState] = useState(loadSoundEnabled);
  const [volume, setVolumeState] = useState(loadSoundVolume);

  const setEnabled = useCallback((v: boolean) => {
    hapticEngine.setEnabled(v);
    setEnabledState(v);
  }, []);

  const setVolume = useCallback((v: number) => {
    hapticEngine.setVolume(v);
    setVolumeState(hapticEngine.getVolume());
  }, []);

  const play = useCallback((cue: SoundCue) => {
    hapticEngine.play(cue);
  }, []);

  const preview = useCallback((cue: SoundCue = 'click') => {
    hapticEngine.unlock();
    hapticEngine.play(cue);
  }, []);

  useEffect(() => {
    hapticEngine.setEnabled(enabled);
    hapticEngine.setVolume(volume);
  }, [enabled, volume]);

  useEffect(() => {
    const unlock = () => hapticEngine.unlock();
    window.addEventListener('pointerdown', unlock, { once: true, passive: true });
    window.addEventListener('keydown', unlock, { once: true });
    return () => {
      window.removeEventListener('pointerdown', unlock);
      window.removeEventListener('keydown', unlock);
    };
  }, []);

  useEffect(() => {
    const onClick = (e: MouseEvent) => {
      if (!hapticEngine.isEnabled()) return;
      const target = e.target as HTMLElement | null;
      if (!target) return;
      if (target.closest('[data-sfx="off"]')) return;
      const interactive = target.closest(
        'button:not(:disabled), .btn:not(:disabled), [role="button"]:not([aria-disabled="true"]), .nav-link, .mobile-nav__link, .mobile-nav__more-btn'
      );
      if (!interactive) return;
      const isNav =
        interactive.classList.contains('nav-link') ||
        !!interactive.closest('.layout-nav, .mobile-nav');
      hapticEngine.play(isNav ? 'nav' : 'click');
    };
    document.addEventListener('click', onClick, true);
    return () => document.removeEventListener('click', onClick, true);
  }, [enabled]);

  const value = useMemo(
    () => ({ enabled, volume, setEnabled, setVolume, play, preview }),
    [enabled, volume, setEnabled, setVolume, play, preview]
  );

  return <SoundContext.Provider value={value}>{children}</SoundContext.Provider>;
}

const noopSound: SoundContextValue = {
  enabled: false,
  volume: 0,
  setEnabled: () => {},
  setVolume: () => {},
  play: () => {},
  preview: () => {},
};

export function useSound() {
  const ctx = useContext(SoundContext);
  return ctx ?? noopSound;
}
