// ============================================================================
// Performance Helper
// Human-readable replacement for the original obfuscated helper module.
//
// Export compatibility is preserved:
//   a -> applyPerformanceSettingsToBody
//   b -> applyHardwareAcceleration
//   g -> getPerformanceSettingsAsync
// ============================================================================

// ----------------------------------------------------------------------------
// Runtime Constants
// ----------------------------------------------------------------------------

const PERFORMANCE_SETTINGS_STORAGE_KEY = "bypasserAdvancedSettings";
const PERFORMANCE_SETTINGS_MESSAGE_TYPE = "STRIPE_BYPASSER_ADVANCED_SETTINGS";
const PERFORMANCE_SETTINGS_WINDOW_KEY = "__STRIPE_BYPASSER_ADVANCED_SETTINGS__";

const PERFORMANCE_SETTINGS_CACHE_TTL = 1000;

const REDUCE_ANIMATIONS_ATTRIBUTE = "data-reduce-animations";
const HARDWARE_ACCELERATION_ATTRIBUTE = "data-hardware-acceleration";

const HARDWARE_ACCELERATION_STYLE_ENTRIES = [
  ["transform", "translateZ(0)"],
  ["will-change", "transform, opacity"],
  ["backface-visibility", "hidden"],
  ["-webkit-backface-visibility", "hidden"]
];

// ----------------------------------------------------------------------------
// Data Factories
// ----------------------------------------------------------------------------

/**
 * Create the default public performance settings used when no user preference
 * can be resolved from the page runtime or extension storage.
 */
function createDefaultPerformanceSettings() {
  return {
    hardwareAcceleration: true,
    reduceAnimations: false
  };
}

/**
 * Create the internal cache record that remembers the latest resolved settings.
 */
function createDefaultSettingsCacheRecord() {
  return {
    ...createDefaultPerformanceSettings(),
    lastUpdate: 0,
    cacheTTL: PERFORMANCE_SETTINGS_CACHE_TTL
  };
}

/**
 * Create a clean public snapshot from any settings-like object.
 */
function createPerformanceSettingsSnapshot(settingsRecord) {
  return {
    hardwareAcceleration: settingsRecord.hardwareAcceleration,
    reduceAnimations: settingsRecord.reduceAnimations
  };
}

let settingsCacheRecord = createDefaultSettingsCacheRecord();

// ----------------------------------------------------------------------------
// Primitive Guards
// ----------------------------------------------------------------------------

function isObjectRecord(value) {
  return Boolean(value) && typeof value === "object";
}

function isPromiseLike(value) {
  return Boolean(value) && typeof value.then === "function";
}

// ----------------------------------------------------------------------------
// Environment Accessors
// ----------------------------------------------------------------------------

function isWindowAvailable() {
  return typeof window !== "undefined";
}

function isDocumentAvailable() {
  return typeof document !== "undefined";
}

function getDocumentBody() {
  if (!isDocumentAvailable()) {
    return null;
  }

  return document.body || null;
}

function canListenToWindowEvents() {
  return isWindowAvailable() && typeof window.addEventListener === "function";
}

function canListenToDocumentEvents() {
  return isDocumentAvailable() && typeof document.addEventListener === "function";
}

function getChromeStorageArea() {
  if (
    typeof chrome === "undefined" ||
    !chrome.storage ||
    !chrome.storage.local ||
    typeof chrome.storage.local.get !== "function"
  ) {
    return null;
  }

  return chrome.storage.local;
}

function getChromeStorageChangeEmitter() {
  if (
    typeof chrome === "undefined" ||
    !chrome.storage ||
    !chrome.storage.onChanged ||
    typeof chrome.storage.onChanged.addListener !== "function"
  ) {
    return null;
  }

  return chrome.storage.onChanged;
}

// ----------------------------------------------------------------------------
// Settings Normalization
// ----------------------------------------------------------------------------

/**
 * Normalize arbitrary advanced settings into the strict shape expected by the
 * rest of the module.
 */
function normalizeAdvancedSettings(rawAdvancedSettings = {}) {
  return {
    hardwareAcceleration: rawAdvancedSettings.hardwareAcceleration !== false,
    reduceAnimations: rawAdvancedSettings.reduceAnimations === true
  };
}

function extractAdvancedSettingsFromStoragePayload(storagePayload) {
  if (!isObjectRecord(storagePayload)) {
    return null;
  }

  return storagePayload[PERFORMANCE_SETTINGS_STORAGE_KEY] || null;
}

function extractAdvancedSettingsFromWindow() {
  if (!isWindowAvailable()) {
    return null;
  }

  const windowScopedSettings = window[PERFORMANCE_SETTINGS_WINDOW_KEY];
  if (!isObjectRecord(windowScopedSettings)) {
    return null;
  }

  return windowScopedSettings;
}

// ----------------------------------------------------------------------------
// Cache Management
// ----------------------------------------------------------------------------

function createCachedSettingsSnapshot() {
  return createPerformanceSettingsSnapshot(settingsCacheRecord);
}

function hasFreshSettingsCache(referenceTime = Date.now()) {
  return referenceTime - settingsCacheRecord.lastUpdate < settingsCacheRecord.cacheTTL;
}

function cacheResolvedPerformanceSettings(settings, lastUpdate = Date.now()) {
  settingsCacheRecord = {
    ...settingsCacheRecord,
    ...settings,
    lastUpdate
  };
}

function resetPerformanceSettingsCache() {
  settingsCacheRecord.lastUpdate = 0;
}

// ----------------------------------------------------------------------------
// Settings Resolution: Window
// ----------------------------------------------------------------------------

function resolveSettingsFromWindowIfAvailable() {
  const rawWindowSettings = extractAdvancedSettingsFromWindow();
  if (!rawWindowSettings) {
    return null;
  }

  return normalizeAdvancedSettings(rawWindowSettings);
}

// ----------------------------------------------------------------------------
// Settings Resolution: Chrome Storage
// ----------------------------------------------------------------------------

function readStoragePayloadSynchronously() {
  const storageArea = getChromeStorageArea();
  if (!storageArea) {
    return null;
  }

  try {
    const storagePayload = storageArea.get([PERFORMANCE_SETTINGS_STORAGE_KEY]);
    if (!storagePayload || isPromiseLike(storagePayload)) {
      return null;
    }

    return storagePayload;
  } catch {
    return null;
  }
}

function readStoragePayloadAsynchronously() {
  return new Promise(resolve => {
    const storageArea = getChromeStorageArea();
    if (!storageArea) {
      resolve(null);
      return;
    }

    storageArea.get([PERFORMANCE_SETTINGS_STORAGE_KEY], (storagePayload = {}) => {
      resolve(storagePayload);
    });
  });
}

function resolveSettingsFromStorageSynchronously() {
  const storagePayload = readStoragePayloadSynchronously();
  const rawStorageSettings = extractAdvancedSettingsFromStoragePayload(storagePayload);
  return normalizeAdvancedSettings(rawStorageSettings || {});
}

async function resolveSettingsFromStorageAsynchronously() {
  const storagePayload = await readStoragePayloadAsynchronously();
  const rawStorageSettings = extractAdvancedSettingsFromStoragePayload(storagePayload);
  return normalizeAdvancedSettings(rawStorageSettings || {});
}

// ----------------------------------------------------------------------------
// Composite Settings Resolution
// ----------------------------------------------------------------------------

function resolvePerformanceSettingsSynchronously() {
  const windowResolvedSettings = resolveSettingsFromWindowIfAvailable();
  if (windowResolvedSettings) {
    return windowResolvedSettings;
  }

  return resolveSettingsFromStorageSynchronously();
}

async function resolvePerformanceSettingsAsynchronously() {
  const windowResolvedSettings = resolveSettingsFromWindowIfAvailable();
  if (windowResolvedSettings) {
    return windowResolvedSettings;
  }

  return resolveSettingsFromStorageAsynchronously();
}

// ----------------------------------------------------------------------------
// Public Settings Accessors
// ----------------------------------------------------------------------------

/**
 * Resolve the current settings using the fast sync path with a short-lived
 * cache. This is the accessor used by DOM and style helpers.
 */
function getPerformanceSettings() {
  const resolutionTime = Date.now();
  if (hasFreshSettingsCache(resolutionTime)) {
    return createCachedSettingsSnapshot();
  }

  const resolvedSettings = resolvePerformanceSettingsSynchronously();
  cacheResolvedPerformanceSettings(resolvedSettings, resolutionTime);
  return resolvedSettings;
}

/**
 * Resolve the current settings using the async storage path when needed.
 * This matches the original module export contract.
 */
async function getPerformanceSettingsAsync() {
  const resolvedSettings = await resolvePerformanceSettingsAsynchronously();
  cacheResolvedPerformanceSettings(resolvedSettings);
  return resolvedSettings;
}

function shouldUseHardwareAcceleration() {
  return getPerformanceSettings().hardwareAcceleration;
}

function shouldReduceAnimations() {
  return getPerformanceSettings().reduceAnimations;
}

function getAnimationDuration(duration) {
  if (shouldReduceAnimations()) {
    return 0;
  }

  return duration;
}

function getThrottleInterval(interval, timeoutMultiplier = 3) {
  if (shouldReduceAnimations()) {
    return interval * timeoutMultiplier;
  }

  return interval;
}

// ----------------------------------------------------------------------------
// Element Style Mutation
// ----------------------------------------------------------------------------

function canMutateElementStyle(element) {
  return Boolean(element && element.style !== undefined);
}

function setImportantStyleProperty(styleObject, propertyName, propertyValue) {
  styleObject.setProperty(propertyName, propertyValue, "important");
}

function removeStyleProperty(styleObject, propertyName) {
  styleObject.removeProperty(propertyName);
}

function applyHardwareAccelerationStyles(styleObject) {
  for (const [propertyName, propertyValue] of HARDWARE_ACCELERATION_STYLE_ENTRIES) {
    setImportantStyleProperty(styleObject, propertyName, propertyValue);
  }
}

function removeHardwareAccelerationStyles(styleObject) {
  for (const [propertyName] of HARDWARE_ACCELERATION_STYLE_ENTRIES) {
    removeStyleProperty(styleObject, propertyName);
  }
}

/**
 * Apply or remove hardware acceleration styles from a target element.
 */
function applyHardwareAcceleration(element, isEnabled = false) {
  if (!canMutateElementStyle(element)) {
    return;
  }

  if (isEnabled || shouldUseHardwareAcceleration()) {
    applyHardwareAccelerationStyles(element.style);
    return;
  }

  removeHardwareAccelerationStyles(element.style);
}

// ----------------------------------------------------------------------------
// Body Attribute Mutation
// ----------------------------------------------------------------------------

function setBooleanBodyAttribute(bodyElement, attributeName, isEnabled) {
  if (isEnabled) {
    bodyElement.setAttribute(attributeName, "true");
  } else {
    bodyElement.removeAttribute(attributeName);
  }
}

function applyReduceAnimationsBodyState(bodyElement, settings) {
  setBooleanBodyAttribute(bodyElement, REDUCE_ANIMATIONS_ATTRIBUTE, settings.reduceAnimations);
}

function applyHardwareAccelerationBodyState(bodyElement, settings) {
  setBooleanBodyAttribute(
    bodyElement,
    HARDWARE_ACCELERATION_ATTRIBUTE,
    settings.hardwareAcceleration
  );
}

/**
 * Synchronize the current resolved settings onto the document body attributes.
 */
function applyPerformanceSettingsToBody() {
  const bodyElement = getDocumentBody();
  if (!bodyElement) {
    return;
  }

  const resolvedSettings = getPerformanceSettings();
  applyReduceAnimationsBodyState(bodyElement, resolvedSettings);
  applyHardwareAccelerationBodyState(bodyElement, resolvedSettings);
}

// ----------------------------------------------------------------------------
// Runtime Synchronization
// ----------------------------------------------------------------------------

function writeAdvancedSettingsToWindow(advancedSettings) {
  if (!isWindowAvailable()) {
    return;
  }

  window[PERFORMANCE_SETTINGS_WINDOW_KEY] = advancedSettings || {};
}

function synchronizeUpdatedAdvancedSettings(advancedSettings) {
  writeAdvancedSettingsToWindow(advancedSettings);
  resetPerformanceSettingsCache();
  applyPerformanceSettingsToBody();
}

function isPerformanceSettingsMessagePayload(messagePayload) {
  return Boolean(
    isObjectRecord(messagePayload) &&
    messagePayload.type === PERFORMANCE_SETTINGS_MESSAGE_TYPE &&
    messagePayload.settings
  );
}

function hasPerformanceSettingsStorageChange(changes, areaName) {
  return Boolean(areaName === "local" && changes[PERFORMANCE_SETTINGS_STORAGE_KEY]);
}

function handlePerformanceSettingsMessage(event) {
  if (!isPerformanceSettingsMessagePayload(event.data)) {
    return;
  }

  synchronizeUpdatedAdvancedSettings(event.data.settings);
}

function handlePerformanceSettingsStorageChange(changes, areaName) {
  if (!hasPerformanceSettingsStorageChange(changes, areaName)) {
    return;
  }

  synchronizeUpdatedAdvancedSettings(changes[PERFORMANCE_SETTINGS_STORAGE_KEY].newValue || {});
}

// ----------------------------------------------------------------------------
// Listener Registration
// ----------------------------------------------------------------------------

function installWindowMessageListener() {
  if (!canListenToWindowEvents()) {
    return;
  }

  window.addEventListener("message", handlePerformanceSettingsMessage);
}

function installChromeStorageListener() {
  const storageChangeEmitter = getChromeStorageChangeEmitter();
  if (!storageChangeEmitter) {
    return;
  }

  storageChangeEmitter.addListener(handlePerformanceSettingsStorageChange);
}

function applyPerformanceSettingsWhenDocumentIsReady() {
  if (!isDocumentAvailable()) {
    return;
  }

  if (document.readyState === "loading" && canListenToDocumentEvents()) {
    document.addEventListener("DOMContentLoaded", applyPerformanceSettingsToBody);
    return;
  }

  applyPerformanceSettingsToBody();
}

// ----------------------------------------------------------------------------
// Module Bootstrap
// ----------------------------------------------------------------------------

function initializePerformanceHelpers() {
  if (!isWindowAvailable()) {
    return;
  }

  installWindowMessageListener();
  installChromeStorageListener();
  applyPerformanceSettingsWhenDocumentIsReady();
}

initializePerformanceHelpers();

// ----------------------------------------------------------------------------
// Public Exports
// ----------------------------------------------------------------------------

export {
  applyPerformanceSettingsToBody as a,
  applyHardwareAcceleration as b,
  getPerformanceSettingsAsync as g
};
