import { useEffect } from "react";
import { preloadAllSounds, playSound } from "./sounds";

/**
 * Mounts global HUD sound behavior:
 * - Preloads every registered sound file once.
 * - Plays "click" on any click whose target (or ancestor) is recognizably
 *   clickable: <button>, <a>, role="button"/etc., or `cursor: pointer`.
 *   Centralizing here means div/span clickables get sound automatically
 *   without touching every call site.
 * - Plays "key-tap" on keydown OUTSIDE text inputs, so navigating menus and
 *   overlays feels tactile but typing into compose stays silent.
 */
export function SoundEffectsProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    preloadAllSounds();
  }, []);

  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (e.button !== 0) return; // left click only
      if (!(e.target instanceof Element)) return;
      if (isClickable(e.target)) playSound("click");
    };
    document.addEventListener("click", handler);
    return () => document.removeEventListener("click", handler);
  }, []);

  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if (e.repeat) return;
      if (isPureModifier(e.key)) return;
      if (isTextInputTarget(e.target)) return;

      if (e.key === "Escape" || e.key === "Enter" || e.key === "Tab") {
        playSound("key-action");
      } else {
        playSound("key-tap");
      }
    };
    window.addEventListener("keydown", handler);
    return () => window.removeEventListener("keydown", handler);
  }, []);

  return children;
}

const CLICKABLE_ROLES = new Set([
  "button",
  "link",
  "menuitem",
  "menuitemcheckbox",
  "menuitemradio",
  "tab",
  "switch",
  "checkbox",
  "radio",
  "option",
]);

/**
 * Walks up to MAX_DEPTH ancestors looking for a recognizably-clickable element.
 * Tag/role checks are cheap — getComputedStyle is the fallback for div-style
 * clickables that only signal intent through `cursor: pointer`.
 */
function isClickable(target: Element): boolean {
  const MAX_DEPTH = 6;
  let el: Element | null = target;
  for (let depth = 0; el && depth < MAX_DEPTH; depth++, el = el.parentElement) {
    const tag = el.tagName;
    if (tag === "BUTTON" || tag === "A" || tag === "SUMMARY") return true;
    const role = el.getAttribute("role");
    if (role && CLICKABLE_ROLES.has(role)) return true;
    if (window.getComputedStyle(el).cursor === "pointer") return true;
  }
  return false;
}

function isPureModifier(key: string): boolean {
  return key === "Shift" || key === "Control" || key === "Meta" || key === "Alt";
}

function isTextInputTarget(target: EventTarget | null): boolean {
  if (!(target instanceof HTMLElement)) return false;
  const tag = target.tagName;
  if (tag === "TEXTAREA") return true;
  if (tag === "INPUT") {
    const type = (target as HTMLInputElement).type;
    return (
      type === "" ||
      type === "text" ||
      type === "search" ||
      type === "email" ||
      type === "url" ||
      type === "password" ||
      type === "tel" ||
      type === "number"
    );
  }
  if (target.isContentEditable) return true;
  return false;
}
