import { useEffect, useMemo, useReducer, useRef, useState, type ReactNode } from "react";
import { SoundContext } from "../SoundContext";
import { initialState, reducer } from "../reducers/SoundContextReducer";
import { useCameraBlackboard } from "../../hooks/useCameraBlackboard";

type SoundContextProviderProps = {
  children: ReactNode;
};

const SoundContextProvider = ({ children }: SoundContextProviderProps) => {
  const audioReady = useRef(false);
  const [audioArmed, setAudioArmed] = useState(false);
  const audioCtxRef = useRef<AudioContext | null>(null);
  const [state, dispatch] = useReducer(reducer, initialState);
  const { mutation } = useCameraBlackboard();

  useEffect(() => {
    const fetchSound = async () => {
      const result = await mutation.mutateAsync({
        operation: "VIEW",
        path: "soundSettings",
      });

      if (!result.result || typeof result.result !== "object") {
        dispatch({ type: "UPDATE", payload: state });
      } else {
        dispatch({ type: "UPDATE", payload: result.result });
      }
    };
    fetchSound();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    const unlock = async () => {
      if (!audioCtxRef.current) audioCtxRef.current = new AudioContext();
      if (audioCtxRef.current.state !== "running") {
        try {
          await audioCtxRef.current.resume();
        } catch {
          /* empty */
        }
      }
      const armed = audioCtxRef.current.state === "running";
      audioReady.current = audioCtxRef.current.state === "running";
      setAudioArmed(armed);
      if (audioReady.current) {
        window.removeEventListener("pointerdown", unlock);
        window.removeEventListener("keydown", unlock);
        window.removeEventListener("touchstart", unlock);
      }
    };
    window.addEventListener("pointerdown", unlock, { once: false });
    window.addEventListener("keydown", unlock, { once: false });
    window.addEventListener("touchstart", unlock, { once: false });
    return () => {
      window.removeEventListener("pointerdown", unlock);
      window.removeEventListener("keydown", unlock);
      window.removeEventListener("touchstart", unlock);
    };
  }, []);

  const value = useMemo(() => ({ state, dispatch, audioArmed }), [state, audioArmed]);
  return <SoundContext.Provider value={value}>{children}</SoundContext.Provider>;
};

export default SoundContextProvider;
