"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var program_exports = {};
__export(program_exports, {
  calculateSha1: () => calculateSha1,
  program: () => program
});
module.exports = __toCommonJS(program_exports);
var import_child_process = require("child_process");
var import_crypto = __toESM(require("crypto"));
var import_os = __toESM(require("os"));
var import_path = __toESM(require("path"));
var import_registry = require("./registry");
var import_session = require("./session");
var import_package = require("../../package");
var import_serverRegistry = require("../../serverRegistry");
var import_minimist = require("./minimist");
const globalOptions = [
  "cdp",
  "endpoint",
  "browser",
  "config",
  "extension",
  "headed",
  "help",
  "persistent",
  "profile",
  "raw",
  "session",
  "version"
];
const booleanOptions = [
  "all",
  "help",
  "raw",
  "version"
];
async function program(options) {
  const clientInfo = (0, import_registry.createClientInfo)();
  const help = require((0, import_package.libPath)("tools", "cli-client", "help.json"));
  const argv = process.argv.slice(2);
  const boolean = [...help.booleanOptions, ...booleanOptions];
  const args = (0, import_minimist.minimist)(argv, { boolean, string: ["_"] });
  if (args.s) {
    args.session = args.s;
    delete args.s;
  }
  const commandName = args._?.[0];
  if (args.version || args.v) {
    console.log(options?.embedderVersion ?? clientInfo.version);
    process.exit(0);
  }
  const command = commandName && help.commands[commandName];
  if (args.help || args.h) {
    if (command) {
      console.log(command.help);
    } else {
      console.log("playwright-cli - run playwright mcp commands from terminal\n");
      console.log(help.global);
    }
    process.exit(0);
  }
  if (!command) {
    console.error(`Unknown command: ${commandName}
`);
    console.log(help.global);
    process.exit(1);
  }
  validateFlags(args, command);
  const registry = await import_registry.Registry.load();
  const sessionName = (0, import_registry.resolveSessionName)(args.session);
  switch (commandName) {
    case "list": {
      await listSessions(registry, clientInfo, !!args.all);
      return;
    }
    case "close-all": {
      const entries = registry.entries(clientInfo);
      for (const entry of entries)
        await new import_session.Session(entry).stop(true);
      return;
    }
    case "delete-data": {
      const entry = registry.entry(clientInfo, sessionName);
      if (!entry) {
        console.log(`No user data found for browser '${sessionName}'.`);
        return;
      }
      await new import_session.Session(entry).deleteData();
      return;
    }
    case "kill-all": {
      await killAllDaemons();
      return;
    }
    case "open": {
      await startSession(sessionName, registry, clientInfo, args);
      return;
    }
    case "attach": {
      const attachTarget = args._[1];
      if (attachTarget && (args.cdp || args.endpoint || args.extension)) {
        console.error(`Error: cannot use target name with --cdp, --endpoint, or --extension`);
        process.exit(1);
      }
      if (attachTarget)
        args.endpoint = attachTarget;
      if (typeof args.extension === "string") {
        args.browser = args.extension;
        args.extension = true;
      }
      const attachSessionName = (0, import_registry.explicitSessionName)(args.session) ?? attachTarget ?? sessionName;
      args.session = attachSessionName;
      await startSession(attachSessionName, registry, clientInfo, args);
      return;
    }
    case "close":
      const closeEntry = registry.entry(clientInfo, sessionName);
      const session = closeEntry ? new import_session.Session(closeEntry) : void 0;
      if (!session || !await session.canConnect()) {
        console.log(`Browser '${sessionName}' is not open.`);
        return;
      }
      await session.stop();
      return;
    case "install":
      await runInitWorkspace(args);
      return;
    case "install-browser":
      await installBrowser();
      return;
    case "show": {
      const daemonScript = (0, import_package.libPath)("entry", "dashboardApp.js");
      const child = (0, import_child_process.spawn)(process.execPath, [daemonScript], {
        detached: true,
        stdio: "ignore"
      });
      child.unref();
      if (process.env.PLAYWRIGHT_PRINT_DASHBOARD_PID_FOR_TEST)
        console.log(`### Dashboard opened with pid ${child.pid}.`);
      return;
    }
    default: {
      const entry = registry.entry(clientInfo, sessionName);
      if (!entry) {
        console.log(`The browser '${sessionName}' is not open, please run open first`);
        console.log("");
        console.log(`  playwright-cli${sessionName !== "default" ? ` -s=${sessionName}` : ""} open [params]`);
        process.exit(1);
      }
      await runInSession(entry, clientInfo, args);
    }
  }
}
async function startSession(sessionName, registry, clientInfo, args) {
  const entry = registry.entry(clientInfo, sessionName);
  if (entry)
    await new import_session.Session(entry).stop(true);
  await import_session.Session.startDaemon(clientInfo, args);
  const newEntry = await registry.loadEntry(clientInfo, sessionName);
  await runInSession(newEntry, clientInfo, args);
}
async function runInSession(entry, clientInfo, args) {
  const raw = !!args.raw;
  for (const globalOption of globalOptions)
    delete args[globalOption];
  const session = new import_session.Session(entry);
  const result = await session.run(clientInfo, args, { raw });
  console.log(result.text);
}
async function runInitWorkspace(args) {
  const cliPath = (0, import_package.libPath)("entry", "cliDaemon.js");
  const daemonArgs = [cliPath, "--init-workspace", ...args.skills ? ["--init-skills", String(args.skills)] : []];
  await new Promise((resolve, reject) => {
    const child = (0, import_child_process.spawn)(process.execPath, daemonArgs, {
      stdio: "inherit",
      cwd: process.cwd()
    });
    child.on("close", (code) => {
      if (code === 0)
        resolve();
      else
        reject(new Error(`Workspace initialization failed with exit code ${code}`));
    });
  });
}
async function installBrowser() {
  const argv = process.argv.map((arg) => arg === "install-browser" ? "install" : arg);
  const { libCli } = require("../../coreBundle.js");
  const { program: program2 } = require("../../utilsBundle.js");
  if (!program2.version())
    libCli.decorateProgram(program2);
  program2.parse(argv);
}
const daemonProcessPatterns = ["run-mcp-server", "run-cli-server", "cli-daemon", "cliDaemon.js", "dashboardApp.js"];
async function killAllDaemons() {
  const platform = import_os.default.platform();
  const pidFilterEnv = process.env.PLAYWRIGHT_KILL_ALL_PID_FILTER_FOR_TEST;
  const pidFilter = pidFilterEnv ? new Set(pidFilterEnv.split(",").map((p) => parseInt(p, 10)).filter((n) => !isNaN(n))) : void 0;
  let killed = 0;
  try {
    if (platform === "win32") {
      const clauses = [`(${daemonProcessPatterns.map((p) => `$_.CommandLine -like '*${p}*'`).join(" -or ")})`];
      if (pidFilter)
        clauses.push(`(${[...pidFilter].map((p) => `$_.ProcessId -eq ${p}`).join(" -or ")})`);
      const whereClause = clauses.join(" -and ");
      const result = (0, import_child_process.execSync)(
        `powershell -NoProfile -NonInteractive -Command "Get-CimInstance Win32_Process | Where-Object { ${whereClause} } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue; $_.ProcessId }"`,
        { encoding: "utf-8" }
      );
      const pids = result.split("\n").map((line) => line.trim()).filter((line) => /^\d+$/.test(line));
      for (const pid of pids)
        console.log(`Killed daemon process ${pid}`);
      killed = pids.length;
    } else {
      const result = (0, import_child_process.execSync)("ps auxww", { encoding: "utf-8" });
      const lines = result.split("\n");
      for (const line of lines) {
        if (daemonProcessPatterns.some((p) => line.includes(p))) {
          const parts = line.trim().split(/\s+/);
          const pid = parts[1];
          if (pid && /^\d+$/.test(pid)) {
            const numericPid = parseInt(pid, 10);
            if (pidFilter && !pidFilter.has(numericPid))
              continue;
            try {
              process.kill(numericPid, "SIGKILL");
              console.log(`Killed daemon process ${pid}`);
              killed++;
            } catch {
            }
          }
        }
      }
    }
  } catch (e) {
  }
  if (killed === 0)
    console.log("No daemon processes found.");
  else if (killed > 0)
    console.log(`Killed ${killed} daemon process${killed === 1 ? "" : "es"}.`);
}
async function listSessions(registry, clientInfo, all) {
  console.log("### Browsers");
  let count = 0;
  const runningSessions = /* @__PURE__ */ new Set();
  const entries = registry.entryMap();
  const key = (0, import_registry.clientKey)(clientInfo);
  for (const [workspaceKey, list] of entries) {
    if (!all && workspaceKey !== key)
      continue;
    count += await gcAndPrintSessions(clientInfo, list.map((entry) => new import_session.Session(entry)), all ? `${import_path.default.relative(process.cwd(), workspaceKey) || "/"}:` : void 0, runningSessions);
  }
  const serverEntries = await import_serverRegistry.serverRegistry.list();
  const filteredServerEntries = /* @__PURE__ */ new Map();
  for (const [workspaceKey, list] of serverEntries) {
    if (!all && workspaceKey !== key)
      continue;
    const unattached = list.filter((d) => !runningSessions.has(d.title));
    if (unattached.length)
      filteredServerEntries.set(workspaceKey, unattached);
  }
  if (filteredServerEntries.size) {
    if (count)
      console.log("");
    console.log("### Browser servers available for attach");
  }
  for (const [workspaceKey, list] of filteredServerEntries)
    count += await gcAndPrintBrowserSessions(workspaceKey, list);
  if (!count)
    console.log("  (no browsers)");
}
async function gcAndPrintSessions(clientInfo, sessions, header, runningSessions) {
  const running = [];
  const stopped = [];
  for (const session of sessions) {
    const canConnect = await session.canConnect();
    if (canConnect) {
      running.push(session);
      runningSessions?.add(session.name);
    } else {
      if (session.config.cli.persistent)
        stopped.push(session);
      else
        await session.deleteSessionConfig();
    }
  }
  if (header && (running.length || stopped.length))
    console.log(header);
  for (const session of running)
    console.log(await renderSessionStatus(clientInfo, session));
  for (const session of stopped)
    console.log(await renderSessionStatus(clientInfo, session));
  return running.length + stopped.length;
}
async function gcAndPrintBrowserSessions(workspace, list) {
  if (!list.length)
    return 0;
  if (workspace)
    console.log(`${import_path.default.relative(process.cwd(), workspace) || "/"}:`);
  for (const descriptor of list) {
    const text = [];
    text.push(`- browser "${descriptor.title}":`);
    text.push(`  - browser: ${descriptor.browser.browserName}`);
    text.push(`  - version: v${descriptor.playwrightVersion}`);
    text.push(`  - status: ${descriptor.canConnect ? "open" : "closed"}`);
    if (descriptor.browser.userDataDir)
      text.push(`  - data-dir: ${descriptor.browser.userDataDir}`);
    else
      text.push(`  - data-dir: <in-memory>`);
    text.push(`  - run \`playwright-cli attach "${descriptor.title}"\` to attach`);
    console.log(text.join("\n"));
  }
  return list.length;
}
async function renderSessionStatus(clientInfo, session) {
  const text = [];
  const config = session.config;
  const canConnect = await session.canConnect();
  text.push(`- ${session.name}:`);
  text.push(`  - status: ${canConnect ? "open" : "closed"}`);
  if (canConnect && !session.isCompatible(clientInfo))
    text.push(`  - version: v${config.version} [incompatible please re-open]`);
  if (config.browser)
    text.push(...(0, import_session.renderResolvedConfig)(config));
  return text.join("\n");
}
function validateFlags(args, command) {
  const unknownFlags = [];
  for (const key of Object.keys(args)) {
    if (key === "_")
      continue;
    if (globalOptions.includes(key))
      continue;
    if (!(key in command.flags))
      unknownFlags.push(key);
  }
  if (unknownFlags.length) {
    console.error(`Unknown option${unknownFlags.length > 1 ? "s" : ""}: ${unknownFlags.map((f) => `--${f}`).join(", ")}`);
    console.log("");
    console.log(command.help);
    process.exit(1);
  }
}
function calculateSha1(buffer) {
  const hash = import_crypto.default.createHash("sha1");
  hash.update(buffer);
  return hash.digest("hex");
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  calculateSha1,
  program
});
