"use strict";
/**
 * Copyright: (c) Myia SAS 2026.
 * This file and its contents are licensed under the AGPLv3 License.
 * Please see the LICENSE file at the root of this repository
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommanderCliAdapter = void 0;
// Tiny Commander wrapper for the trace viewer. Mirrors the shape of
// heal-cli's CommanderCliAdapter but with a single subcommand
// (`view`). Lives in `src/application/...` to keep room for further
// commands later (e.g. `prune`, `export`).
const node_child_process_1 = require("node:child_process");
const node_fs_1 = require("node:fs");
const path = __importStar(require("node:path"));
const commander_1 = require("commander");
const local_viewer_server_1 = require("../../infrastructure/local-viewer-adapter/local-viewer-server");
// Bind to port 0 — the OS picks a free ephemeral port. We then read
// the actual port back from the listening server's AddressInfo and
// use that for the printed URL and the browser-open. Avoids "port in
// use" failures when several copies of `heal-tracer view` overlap or
// when port 3000 is already taken by another dev server.
const RANDOM_PORT = 0;
const defaultBundleDir = () => 
// Resolves to <package-root>/tracer-viewer-bundle. At runtime,
// __dirname is `<package-root>/dist/application/commander-cli-adapter`
// — both during local dev and when the package is installed under
// `node_modules/@heal-dev/heal-playwright-tracer/`. Walking three
// levels up lands at the package root, where the committed bundle
// lives. In tests, the caller passes `bundleDir` explicitly.
path.resolve(__dirname, '..', '..', '..', 'tracer-viewer-bundle');
const openInBrowser = (url) => {
    const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start ""' : 'xdg-open';
    (0, node_child_process_1.exec)(`${cmd} ${JSON.stringify(url)}`);
};
class CommanderCliAdapter {
    constructor(options = {}) {
        this.options = options;
        this.program = new commander_1.Command();
        this.initialize();
    }
    initialize() {
        this.program
            .name('heal-tracer')
            .description('Local viewer for heal-playwright-tracer artefacts')
            .version(this.options.version ?? '0.0.0', '-v, --version', 'Show version')
            .helpOption('-h, --help', 'Show this help');
        this.program
            .command('view')
            .description('Serve the local trace viewer over an http server')
            .action(async () => {
            await this.handleView();
        });
    }
    log(msg) {
        (this.options.log ?? console.log.bind(console))(msg);
    }
    async handleView() {
        const rootDir = process.cwd();
        const bundleDir = this.options.bundleDir ?? defaultBundleDir();
        if (!(0, node_fs_1.existsSync)(path.join(bundleDir, 'index.html'))) {
            console.error(`[heal-tracer] viewer bundle not found at ${bundleDir}.\n` +
                `Reinstall @heal-dev/heal-playwright-tracer.`);
            process.exit(1);
        }
        const server = new local_viewer_server_1.LocalViewerServer({
            rootDir,
            bundleDir,
            port: RANDOM_PORT,
            log: (m) => this.log(m),
        });
        await server.start();
        const port = server.boundPort();
        if (port === null) {
            console.error('[heal-tracer] server failed to bind a port');
            process.exit(1);
        }
        const url = `http://localhost:${String(port)}`;
        this.log(`✓ heal-tracer viewer running at ${url}`);
        this.log(`  scanning: ${rootDir} (recursive)`);
        openInBrowser(url);
        this.log('Press Ctrl+C to stop.');
        await new Promise((resolve) => {
            const shutdown = () => {
                this.log('\nStopping viewer…');
                server
                    .stop()
                    .catch(() => undefined)
                    .finally(() => resolve());
            };
            process.once('SIGINT', shutdown);
            process.once('SIGTERM', shutdown);
        });
        process.exit(0);
    }
    async parse(argv) {
        await this.program.parseAsync(argv ?? this.options.argv ?? process.argv);
    }
}
exports.CommanderCliAdapter = CommanderCliAdapter;
