// Comprehensive Playwright stealth patches — hides automation signals from bot detection
// Based on puppeteer-extra-plugin-stealth evasions + modern CF bypass techniques

// 1. Hide webdriver flag
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
delete navigator.__proto__.webdriver;

// 2. Fix chrome runtime (missing in automation)
if (!window.chrome) {
  window.chrome = {};
}
if (!window.chrome.runtime) {
  window.chrome.runtime = {
    connect: function() {},
    sendMessage: function() {},
    onMessage: { addListener: function() {}, removeListener: function() {} },
    onConnect: { addListener: function() {}, removeListener: function() {} },
    id: undefined
  };
}
if (!window.chrome.loadTimes) {
  window.chrome.loadTimes = function() {
    return {
      commitLoadTime: Date.now() / 1000,
      connectionInfo: 'h2',
      finishDocumentLoadTime: Date.now() / 1000 + 0.1,
      finishLoadTime: Date.now() / 1000 + 0.2,
      firstPaintAfterLoadTime: 0,
      firstPaintTime: Date.now() / 1000 + 0.05,
      navigationType: 'Other',
      npnNegotiatedProtocol: 'h2',
      requestTime: Date.now() / 1000 - 0.5,
      startLoadTime: Date.now() / 1000 - 0.4,
      wasAlternateProtocolAvailable: false,
      wasFetchedViaSpdy: true,
      wasNpnNegotiated: true
    };
  };
}
if (!window.chrome.csi) {
  window.chrome.csi = function() {
    return {
      onloadT: Date.now(),
      startE: Date.now() - 500,
      pageT: 500,
      tran: 15
    };
  };
}
if (!window.chrome.app) {
  window.chrome.app = {
    isInstalled: false,
    InstallState: { DISABLED: 'disabled', INSTALLED: 'installed', NOT_INSTALLED: 'not_installed' },
    RunningState: { CANNOT_RUN: 'cannot_run', READY_TO_RUN: 'ready_to_run', RUNNING: 'running' },
    getDetails: function() { return null; },
    getIsInstalled: function() { return false; },
    installState: function() { return 'not_installed'; },
    runningState: function() { return 'cannot_run'; }
  };
}

// 3. Fix permissions query
const origQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (params) =>
  params.name === 'notifications'
    ? Promise.resolve({ state: Notification.permission })
    : origQuery.call(navigator.permissions, params);

// 4. Fix plugins (empty in automation — mimic real Chrome)
Object.defineProperty(navigator, 'plugins', {
  get: () => {
    const plugins = [
      { name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format', length: 1 },
      { name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '', length: 1 },
      { name: 'Native Client', filename: 'internal-nacl-plugin', description: '', length: 2 },
    ];
    plugins.refresh = function() {};
    plugins.item = function(i) { return this[i] || null; };
    plugins.namedItem = function(name) { return this.find(p => p.name === name) || null; };
    Object.setPrototypeOf(plugins, PluginArray.prototype);
    return plugins;
  },
});

// 5. Fix mimeTypes
Object.defineProperty(navigator, 'mimeTypes', {
  get: () => {
    const mimes = [
      { type: 'application/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: navigator.plugins[0] },
      { type: 'application/x-google-chrome-pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: navigator.plugins[0] },
    ];
    mimes.refresh = function() {};
    mimes.item = function(i) { return this[i] || null; };
    mimes.namedItem = function(name) { return this.find(m => m.type === name) || null; };
    Object.setPrototypeOf(mimes, MimeTypeArray.prototype);
    return mimes;
  },
});

// 6. Fix languages
Object.defineProperty(navigator, 'languages', {
  get: () => ['en-US', 'en'],
});

// 7. Fix hardwareConcurrency (automation often shows wrong value)
Object.defineProperty(navigator, 'hardwareConcurrency', {
  get: () => 8,
});

// 8. Fix deviceMemory
Object.defineProperty(navigator, 'deviceMemory', {
  get: () => 8,
});

// 9. Fix platform
Object.defineProperty(navigator, 'platform', {
  get: () => 'Win32',
});

// 10. Prevent iframe contentWindow detection
try {
  const origGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
  Object.getOwnPropertyDescriptor = function (obj, prop) {
    if (prop === 'contentWindow' && obj instanceof HTMLIFrameElement) {
      return undefined;
    }
    return origGetOwnPropertyDescriptor.call(this, obj, prop);
  };
} catch (e) {}

// 11. Fix WebGL vendor/renderer (automation has "Google Inc. (ANGLE)" or "Brian Paul")
try {
  const getParameter = WebGLRenderingContext.prototype.getParameter;
  WebGLRenderingContext.prototype.getParameter = function(param) {
    if (param === 37445) return 'Google Inc. (NVIDIA)'; // UNMASKED_VENDOR_WEBGL
    if (param === 37446) return 'ANGLE (NVIDIA, NVIDIA GeForce GTX 1060 6GB Direct3D11 vs_5_0 ps_5_0, D3D11)'; // UNMASKED_RENDERER_WEBGL
    return getParameter.call(this, param);
  };
  const getParameter2 = WebGL2RenderingContext.prototype.getParameter;
  WebGL2RenderingContext.prototype.getParameter = function(param) {
    if (param === 37445) return 'Google Inc. (NVIDIA)';
    if (param === 37446) return 'ANGLE (NVIDIA, NVIDIA GeForce GTX 1060 6GB Direct3D11 vs_5_0 ps_5_0, D3D11)';
    return getParameter2.call(this, param);
  };
} catch (e) {}

// 12. Fix window.outerWidth/outerHeight (0 in headless)
if (window.outerWidth === 0) {
  Object.defineProperty(window, 'outerWidth', { get: () => window.innerWidth });
}
if (window.outerHeight === 0) {
  Object.defineProperty(window, 'outerHeight', { get: () => window.innerHeight + 85 });
}

// 13. Fix toString() for patched functions — prevent detection via .toString()
try {
  const nativeToString = Function.prototype.toString;
  const proxyHandler = {
    apply: function(target, thisArg, args) {
      // If someone calls toString on our patched functions, return native-looking string
      if (thisArg === navigator.permissions.query) return 'function query() { [native code] }';
      return nativeToString.call(thisArg);
    }
  };
  Function.prototype.toString = new Proxy(nativeToString, proxyHandler);
} catch (e) {}

// 14. Prevent sourceURL detection (Playwright injects scripts with sourceURL comments)
// This is handled by not using sourceURL in our injected scripts

// 15. Fix media codecs — headless Chrome reports different codec support
try {
  const origCanPlayType = HTMLMediaElement.prototype.canPlayType;
  HTMLMediaElement.prototype.canPlayType = function(type) {
    if (type === 'video/mp4; codecs="avc1.42E01E"') return 'probably';
    if (type === 'audio/mpeg') return 'probably';
    if (type === 'audio/mp4; codecs="mp4a.40.2"') return 'probably';
    return origCanPlayType.call(this, type);
  };
} catch (e) {}

// 16. Fix connection.rtt — automation has rtt=0
try {
  if (navigator.connection) {
    Object.defineProperty(navigator.connection, 'rtt', { get: () => 50 });
  }
} catch (e) {}
