const PROFILE_GLYPH_MAP = {
  xbox: {
    accept: "A",
    back: "B",
    menu: "☰",
    up: "↑",
    down: "↓",
    left: "←",
    right: "→",
    l1: "LB",
    r1: "RB",
    l2: "LT",
    r2: "RT",
    clear: "X",
    y: "Y",
  },
  playstation: {
    accept: "✕",
    back: "○",
    menu: "☰",
    up: "↑",
    down: "↓",
    left: "←",
    right: "→",
    l1: "L1",
    r1: "R1",
    l2: "L2",
    r2: "R2",
    clear: "□",
    y: "△",
  },
  switch: {
    accept: "B",
    back: "A",
    menu: "+",
    up: "↑",
    down: "↓",
    left: "←",
    right: "→",
    l1: "L",
    r1: "R",
    l2: "ZL",
    r2: "ZR",
    clear: "Y",
    y: "X",
  },
  generic: {
    accept: "A",
    back: "B",
    menu: "☰",
    up: "↑",
    down: "↓",
    left: "←",
    right: "→",
    l1: "L1",
    r1: "R1",
    l2: "L2",
    r2: "R2",
    clear: "X",
    y: "Y",
  },
};

const GLYPH_ACTIONS = [
  "accept",
  "back",
  "menu",
  "up",
  "down",
  "left",
  "right",
  "l1",
  "r1",
  "l2",
  "r2",
  "clear",
  "y",
];

const CORE_GLYPH_IDS = {
  accept: "confirm",
  back: "back",
  menu: "menu",
  up: "dpad-up",
  down: "dpad-down",
  left: "dpad-left",
  right: "dpad-right",
  l1: "lb",
  r1: "rb",
  l2: "lt",
  r2: "rt",
  clear: "x",
  y: "y",
};

export const CONTROLLER_PROFILES = ["xbox", "playstation", "switch", "generic"];

export const PROFILE_LABELS = {
  xbox: "Xbox",
  playstation: "PlayStation",
  switch: "Nintendo Switch",
  generic: "controller",
};

export const detectGamepadProfile = (gamepad) => {
  const id = `${gamepad?.id ?? ""} ${gamepad?.mapping ?? ""}`.toLowerCase();

  if (/xbox|x-input|microsoft|045e|8bitdo.*xbox|8bitdo.*x/i.test(id)) {
    return "xbox";
  }

  if (/playstation|dualsense|dualshock|ps5|ps4|054c|sony|wireless controller/i.test(id)) {
    return "playstation";
  }

  if (/nintendo|switch|pro controller|057e|joy-con|joycon/i.test(id)) {
    return "switch";
  }

  return "generic";
};

export const getActiveGamepad = () => {
  const pads = navigator.getGamepads?.() ?? [];
  return pads.find((pad) => pad?.connected) ?? null;
};

export const detectActiveProfile = () => {
  const pad = getActiveGamepad();
  return pad ? detectGamepadProfile(pad) : "generic";
};

export const getFallbackGlyphs = (profile = "generic") => ({
  ...(PROFILE_GLYPH_MAP[profile] ?? PROFILE_GLYPH_MAP.generic),
});

export const resolveGlyphsForProfile = (profile, glyphsModule) => {
  const safeProfile = CONTROLLER_PROFILES.includes(profile) ? profile : "generic";
  const platform = safeProfile === "generic" ? "xbox" : safeProfile;
  const fallback = getFallbackGlyphs(safeProfile);

  if (typeof glyphsModule?.getGlyph !== "function") {
    return fallback;
  }

  const resolved = {};
  GLYPH_ACTIONS.forEach((action) => {
    const glyphId = CORE_GLYPH_IDS[action];
    resolved[action] = glyphsModule.getGlyph(platform, glyphId) ?? fallback[action];
  });
  return resolved;
};

export const watchGamepadProfile = (onChange) => {
  let current = detectActiveProfile();

  const emitIfChanged = () => {
    const next = detectActiveProfile();
    if (next === current) {
      return;
    }
    current = next;
    onChange(next);
  };

  window.addEventListener("gamepadconnected", emitIfChanged);
  window.addEventListener("gamepaddisconnected", emitIfChanged);

  let rafId = 0;
  const poll = () => {
    emitIfChanged();
    rafId = requestAnimationFrame(poll);
  };
  rafId = requestAnimationFrame(poll);

  return () => {
    window.removeEventListener("gamepadconnected", emitIfChanged);
    window.removeEventListener("gamepaddisconnected", emitIfChanged);
    if (rafId) {
      cancelAnimationFrame(rafId);
    }
  };
};
