#!/usr/bin/env npx tsx

/**
 * Browser launcher using CloakBrowser with persistent profile
 *
 * Usage:
 *   npx tsx browse.ts --url "https://example.com"
 *   npx tsx browse.ts --url "https://example.com" --screenshot --output page.png
 *   npx tsx browse.ts --url "https://example.com" --headless false --wait 5000
 */

import { launchPersistentContext } from 'cloakbrowser';
import { homedir } from 'os';
import { join } from 'path';
import { existsSync, mkdirSync } from 'fs';
import parseArgs from 'minimist';
import type { Page, BrowserContext } from 'playwright-core';

interface BrowseOptions {
  url: string;
  headless?: boolean;
  screenshot?: boolean;
  output?: string;
  wait?: number;
  timeout?: number;
  interactive?: boolean;
}

interface BrowseResult {
  title: string;
  url: string;
  screenshotPath?: string;
}

function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

const getProfilePath = (): string => {
  const customPath = process.env.CLOAKBROWSER_PROFILE_PATH || process.env.CAMOUFOX_PROFILE_PATH;
  if (customPath) return customPath;

  const profileDir = join(homedir(), '.cloakbrowser-profile');
  if (!existsSync(profileDir)) {
    mkdirSync(profileDir, { recursive: true });
  }
  return profileDir;
};

export async function launchBrowser(options: {
  headless?: boolean;
}): Promise<BrowserContext> {
  const profilePath = getProfilePath();
  const envHeadless = process.env.CLOAKBROWSER_HEADLESS ?? process.env.CAMOUFOX_HEADLESS;
  const headless = options.headless ?? (envHeadless ? envHeadless === 'true' : true);

  console.log(`Using profile: ${profilePath}`);
  console.log(`Headless mode: ${headless}`);

  const context = await launchPersistentContext({
    userDataDir: profilePath,
    headless,
    humanize: true,
  });

  return context;
}

export async function browse(options: BrowseOptions): Promise<BrowseResult> {
  const browser = await launchBrowser({ headless: options.headless });
  const page = browser.pages()[0] || await browser.newPage();

  try {
    console.log(`Navigating to: ${options.url}`);
    await page.goto(options.url, {
      timeout: options.timeout ?? 60000,
      waitUntil: 'domcontentloaded',
    });

    if (options.wait) {
      console.log(`Waiting ${options.wait}ms...`);
      await sleep(options.wait);
    }

    const result: BrowseResult = {
      title: await page.title(),
      url: page.url(),
    };

    console.log(`Page title: ${result.title}`);
    console.log(`Final URL: ${result.url}`);

    if (options.screenshot) {
      const outputPath = options.output ?? 'screenshot.png';
      await page.screenshot({ path: outputPath, fullPage: true });
      result.screenshotPath = outputPath;
      console.log(`Screenshot saved: ${outputPath}`);
    }

    if (options.interactive) {
      console.log('\nInteractive mode - browser will stay open.');
      console.log('Press Ctrl+C to close.');
      await new Promise(() => {});
    }

    return result;
  } finally {
    if (!options.interactive) {
      await browser.close();
    }
  }
}

export async function getPage(options?: {
  headless?: boolean;
}): Promise<{ page: Page; browser: BrowserContext }> {
  const browser = await launchBrowser({ headless: options?.headless });
  const page = browser.pages()[0] || await browser.newPage();
  return { page, browser };
}

async function main() {
  const args = parseArgs(process.argv.slice(2), {
    string: ['url', 'output'],
    boolean: ['screenshot', 'headless', 'interactive', 'help'],
    default: {
      headless: true,
      screenshot: false,
      interactive: false,
    },
    alias: {
      u: 'url',
      o: 'output',
      s: 'screenshot',
      h: 'help',
      i: 'interactive',
    },
  });

  if (args.help || !args.url) {
    console.log(`
Web Browser with CloakBrowser

Usage:
  npx tsx browse.ts --url <url> [options]

Options:
  -u, --url <url>       URL to navigate to (required)
  -s, --screenshot      Take a screenshot of the page
  -o, --output <path>   Output path for screenshot (default: screenshot.png)
  --headless <bool>     Run in headless mode (default: true)
  --wait <ms>           Wait time after page load in milliseconds
  --timeout <ms>        Navigation timeout (default: 60000)
  -i, --interactive     Keep browser open for manual interaction
  -h, --help            Show this help message

Examples:
  npx tsx browse.ts --url "https://example.com"
  npx tsx browse.ts --url "https://example.com" --screenshot --output page.png
  npx tsx browse.ts --url "https://example.com" --headless false --interactive

Environment Variables:
  CLOAKBROWSER_PROFILE_PATH  Custom profile directory (default: ~/.cloakbrowser-profile/)
  CLOAKBROWSER_HEADLESS      Default headless mode (true/false)

Compatibility Aliases:
  CAMOUFOX_PROFILE_PATH      Legacy alias for CLOAKBROWSER_PROFILE_PATH
  CAMOUFOX_HEADLESS          Legacy alias for CLOAKBROWSER_HEADLESS
`);
    process.exit(args.help ? 0 : 1);
  }

  try {
    await browse({
      url: args.url,
      headless: args.headless,
      screenshot: args.screenshot,
      output: args.output,
      wait: args.wait ? parseInt(args.wait, 10) : undefined,
      timeout: args.timeout ? parseInt(args.timeout, 10) : undefined,
      interactive: args.interactive,
    });
  } catch (error) {
    console.error('Error:', error instanceof Error ? error.message : error);
    process.exit(1);
  }
}

const isMainModule = process.argv[1]?.includes('browse.ts');
if (isMainModule) {
  main();
}
