import Taro from "@tarojs/taro";

type HapticType = "light" | "medium" | "heavy";

let lastHapticAt = 0;
let installed = false;

const INTERACTIVE_CLASS_RE = /(btn|button|tab|chip|pill|card|item|link|entry|action|switch|filter|upload|remove|close|edit|save|submit|confirm|cancel|detail|create|more|arrow|logout|agree|checkbox|radio|picker|media|grid|carousel|branch|guess|tag|profile|social|drawer)/i;
const PATCH_METHODS = [
  "navigateTo",
  "redirectTo",
  "reLaunch",
  "switchTab",
  "navigateBack",
  "showActionSheet",
  "showModal",
  "setClipboardData",
  "chooseImage",
  "chooseMedia",
  "previewImage",
  "scanCode",
  "makePhoneCall",
  "openLocation"
];

export function haptic(type: HapticType = "light", minGap = 80) {
  const now = Date.now();
  if (now - lastHapticAt < minGap) return;
  lastHapticAt = now;
  try {
    void Taro.vibrateShort({ type });
  } catch {
    // Devtools and some devices may not expose haptics.
  }
}

export function installTaroHaptics() {
  if (installed) return;
  installed = true;
  PATCH_METHODS.forEach((method) => {
    const original = (Taro as any)[method];
    if (typeof original !== "function") return;
    (Taro as any)[method] = function patchedTaroMethod(...args: any[]) {
      haptic(method === "showModal" || method === "showActionSheet" ? "medium" : "light");
      return original.apply(this, args);
    };
  });
}

export function hapticFromTap(event: any) {
  const target = event?.target || {};
  const dataset = target.dataset || {};
  if (dataset.haptic === "none") return;
  if (dataset.haptic === "medium" || dataset.haptic === "heavy") {
    haptic(dataset.haptic);
    return;
  }
  const className = String(target.className || target.class || "");
  const id = String(target.id || "");
  if (dataset.haptic === "light" || INTERACTIVE_CLASS_RE.test(className) || INTERACTIVE_CLASS_RE.test(id)) {
    haptic("light");
  }
}
