"use strict";
/**
 * `vyuh-dxkit issue` — open a pre-filled GitHub Issue against
 * `vyuh-labs/dxkit` in the customer's default browser.
 *
 * The dxkit team triages bugs / false-positive reports / feature
 * requests in GitHub Issues. Sending customers there directly (vs
 * email / a custom form) keeps:
 *
 *   - Triage centralized (labels, assignees, dedup search)
 *   - Status visible to the customer (they can subscribe to their
 *     own issue, see comments, get notified on resolution)
 *   - Zero infra for us to maintain (no SMTP, no webhook, no DB)
 *
 * The CLI builds a URL with pre-filled title + body + labels and
 * opens it via the platform's default browser. Customer reviews
 * the prefill before clicking "Submit new issue" — nothing is
 * sent without their explicit click.
 *
 * Body prefill includes:
 *   - dxkit version (from package.json)
 *   - Node version, platform, arch (so triage can reproduce)
 *   - Issue type + optional fingerprint (when reporting a
 *     false-positive on a specific finding)
 *   - Customer's `--about` text (free-form description) OR a
 *     "TODO: describe..." placeholder
 *
 * # Privacy
 *
 * NOTHING is submitted automatically. The CLI opens a URL with
 * query-string pre-fill; the customer reviews + edits + clicks
 * "Submit." All env data in the prefill is the kind already
 * visible in `npx vyuh-dxkit --version` — no source content, no
 * customer-identifying paths beyond the project name.
 */
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.ISSUE_TYPES = void 0;
exports.buildIssueUrl = buildIssueUrl;
exports.runIssueSubmit = runIssueSubmit;
const child_process_1 = require("child_process");
const fs_1 = require("fs");
const path = __importStar(require("path"));
const logger = __importStar(require("./logger"));
exports.ISSUE_TYPES = [
    'false-positive',
    'missing-finding',
    'bug',
    'feature-request',
    'docs',
];
/** Per-type GitHub label that will be pre-applied. The labels
 *  themselves must exist on the repo; dxkit's repo carries these
 *  by convention. */
const LABEL_BY_TYPE = Object.freeze({
    'false-positive': 'false-positive',
    'missing-finding': 'missing-finding',
    bug: 'bug',
    'feature-request': 'enhancement',
    docs: 'documentation',
});
/** Per-type title prefix surfaced in the GitHub Issues list. */
const TITLE_PREFIX_BY_TYPE = Object.freeze({
    'false-positive': 'False positive',
    'missing-finding': 'Missing finding',
    bug: 'Bug',
    'feature-request': 'Feature request',
    docs: 'Docs',
});
const ISSUES_BASE_URL = 'https://github.com/vyuh-labs/dxkit/issues/new';
/**
 * Pure function: build the GitHub Issues "new issue" URL with
 * pre-filled title / body / labels. Exposed for unit testing —
 * callers without browser-open side effects can verify the URL
 * shape directly.
 */
function buildIssueUrl(input) {
    const params = new URLSearchParams();
    params.set('title', buildTitle(input));
    params.set('body', buildBody(input));
    params.set('labels', LABEL_BY_TYPE[input.type]);
    return `${ISSUES_BASE_URL}?${params.toString()}`;
}
async function runIssueSubmit(cwd, opts) {
    const type = parseIssueType(opts.type);
    const url = buildIssueUrl({
        type,
        about: opts.about,
        fingerprint: opts.fingerprint?.trim() || undefined,
        dxkitVersion: readDxkitVersion(),
        nodeVersion: process.version,
        platform: process.platform,
        arch: process.arch,
    });
    if (opts.noBrowser) {
        // Print URL to stdout so callers in CI / SSH can copy.
        process.stdout.write(url + '\n');
        return;
    }
    logger.info(`Opening pre-filled issue in your browser…`);
    logger.info(`If the browser doesn't open, copy this URL:`);
    logger.info(`  ${url}`);
    void openBrowser(cwd, url);
}
// ─── Internals ────────────────────────────────────────────────────────────
function parseIssueType(raw) {
    if (!raw) {
        logger.fail(`--type is required. One of: ${exports.ISSUE_TYPES.join(', ')}.`);
        process.exit(1);
    }
    if (!exports.ISSUE_TYPES.includes(raw)) {
        logger.fail(`--type ${JSON.stringify(raw)} is not a known issue type. ` +
            `One of: ${exports.ISSUE_TYPES.join(', ')}.`);
        process.exit(1);
    }
    return raw;
}
function buildTitle(input) {
    const prefix = TITLE_PREFIX_BY_TYPE[input.type];
    const aboutShort = input.about ? truncate(input.about, 60) : '';
    if (aboutShort) {
        return `[${prefix}] ${aboutShort}`;
    }
    if (input.fingerprint) {
        return `[${prefix}] finding ${input.fingerprint}`;
    }
    return `[${prefix}] `;
}
function buildBody(input) {
    const lines = [];
    lines.push(`**Type:** ${input.type}`);
    lines.push(`**dxkit version:** ${input.dxkitVersion}`);
    lines.push(`**Node version:** ${input.nodeVersion}`);
    lines.push(`**Platform:** ${input.platform} / ${input.arch}`);
    if (input.fingerprint) {
        lines.push(`**Finding fingerprint:** \`${input.fingerprint}\``);
    }
    lines.push('');
    lines.push('## What happened');
    lines.push('');
    lines.push(input.about ?? '<!-- Describe what you observed -->');
    lines.push('');
    lines.push('## What you expected');
    lines.push('');
    lines.push('<!-- Describe the behavior you expected -->');
    lines.push('');
    lines.push('## How to reproduce');
    lines.push('');
    lines.push('<!-- Minimal repro steps. Pseudo-code / sample input is fine. -->');
    lines.push('');
    lines.push('## Anything else');
    lines.push('');
    lines.push('<!-- Logs, screenshots, related issues, etc. -->');
    return lines.join('\n');
}
function readDxkitVersion() {
    try {
        // Two possible locations: same package as this module (dev / source)
        // and `node_modules/@vyuhlabs/dxkit/package.json` (installed).
        // __dirname points at dist/ or src/ depending on build; resolve
        // upward to find package.json.
        const candidates = [
            path.join(__dirname, '..', 'package.json'),
            path.join(__dirname, '..', '..', 'package.json'),
        ];
        for (const candidate of candidates) {
            try {
                const pkg = JSON.parse((0, fs_1.readFileSync)(candidate, 'utf8'));
                if (typeof pkg.version === 'string')
                    return pkg.version;
            }
            catch {
                continue;
            }
        }
    }
    catch {
        // fall through
    }
    return 'unknown';
}
function truncate(s, max) {
    if (s.length <= max)
        return s;
    return s.slice(0, max - 1) + '…';
}
/**
 * Open `url` in the customer's default browser. Detached so the CLI
 * exits without waiting for the browser process. Errors are
 * swallowed — the URL is also printed to stdout so the customer can
 * copy it manually if the open fails (corporate workstation, no
 * `xdg-open` configured, etc.).
 */
function openBrowser(cwd, url) {
    let cmd;
    let args;
    if (process.platform === 'darwin') {
        cmd = 'open';
        args = [url];
    }
    else if (process.platform === 'win32') {
        cmd = 'cmd';
        args = ['/c', 'start', '""', url];
    }
    else {
        // Linux / WSL / *BSD — xdg-open is the freedesktop standard.
        // WSL2 environments without an X server fall through to no-op
        // (the URL was already printed by the caller).
        cmd = 'xdg-open';
        args = [url];
    }
    try {
        const child = (0, child_process_1.spawn)(cmd, args, { cwd, detached: true, stdio: 'ignore' });
        child.unref();
    }
    catch {
        // Silent — the URL is already in the customer's terminal.
    }
}
//# sourceMappingURL=issue-cli.js.map