import { existsSync } from 'node:fs';

/**
 * Anti-detection browser hardening (PRD D-5), derived from a competitor teardown.
 *
 * Measured effect (offline fingerprint probe, 2026-07-06): the launch flags below
 * flip navigator.webdriver false→undefined, but the strongest headless tells
 * (plugins=0, no window.chrome, SwiftShader software WebGL) are ONLY fixed by
 * running the real Chrome binary (channel:'chrome'), not bundled Chromium. So the
 * two levers are: (1) always apply these stealth flags + init script (works in
 * bundled Chromium), (2) prefer real Chrome when the host has it.
 */

export type BrowserChannel = 'chrome' | 'chromium';
export type ChannelPref = BrowserChannel | 'auto';

/** Launch flags that hide the automation fingerprint. Pure so it's unit-tested. */
export function stealthLaunchOptions(): { args: string[]; ignoreDefaultArgs: string[] } {
  return {
    // --enable-automation is what sets navigator.webdriver=true and shows the
    // "controlled by automated test software" infobar; dropping it + blink flag
    // removes the two cheapest client-side bot signals.
    args: [
      '--disable-blink-features=AutomationControlled',
      '--no-default-browser-check',
      '--disable-popup-blocking',
    ],
    ignoreDefaultArgs: ['--enable-automation'],
  };
}

/** Runs at document start in every page: belt-and-suspenders removal of the
 *  webdriver flag (in case a Chromium build still exposes it). */
export const STEALTH_INIT_SCRIPT = `Object.defineProperty(navigator, 'webdriver', { get: () => undefined });`;

/** Resolve which browser build to launch. 'auto' picks real Chrome when present
 *  (closes the fingerprint gap), else the bundled Chromium the app already ships. */
export function resolveChannel(pref: ChannelPref, chromeAvailable: boolean): BrowserChannel {
  if (pref === 'auto') return chromeAvailable ? 'chrome' : 'chromium';
  return pref;
}

/** Best-effort check for an installed Google Chrome, per platform. I/O, so kept
 *  out of the pure helpers above. Playwright's channel:'chrome' resolves the real
 *  binary itself; this just decides whether to ask for it. */
export function hostChromeAvailable(platform: NodeJS.Platform = process.platform): boolean {
  const candidates =
    platform === 'darwin'
      ? ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome']
      : platform === 'win32'
        ? [
            'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
            'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
            `${process.env.LOCALAPPDATA ?? ''}\\Google\\Chrome\\Application\\chrome.exe`,
          ]
        : ['/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/opt/google/chrome/chrome'];
  return candidates.some((p) => p && existsSync(p));
}
