/**
 * Injectable `gh` reads for the GitHub repository live-status panel.
 * @module cli/ui-github-repo-gh
 */
import { execFile } from "node:child_process";
import { mapRepoSettings, mapRulesetRow, requireNamedString, } from "./ui-github-repo-map.js";
/**
 * Run `gh` without a shell and return stdout.
 *
 * Exported so every `gh` read in the CLI goes through one shell-free call site.
 * A second one would mean a second place to get argument handling and the
 * command-from-PATH exemption right, and the gate report needs a branch-rules
 * read that belongs to no existing member of `GithubRepoGhReads`.
 * @param args - gh argv after the executable
 * @param cwd - Working directory
 * @param timeoutMs - Child-process timeout
 * @param signal - Probe cancellation signal
 * @returns Trimmed stdout
 */
export function runGh(args, cwd, timeoutMs, signal) {
    return new Promise((resolve, reject) => {
        const ghExecutable = "gh";
        execFile(
        // eslint-disable-next-line sonarjs/no-os-command-from-path -- fixed user-installed gh executable
        ghExecutable, [...args], { cwd, signal, timeout: timeoutMs, encoding: "utf8" }, (error, stdout) => {
            if (error !== null) {
                reject(error);
                return;
            }
            resolve(stdout.trim());
        });
    });
}
/**
 * Parse JSON from a gh command, rejecting non-JSON payloads.
 * @param stdout - Command stdout
 * @returns Parsed JSON value
 */
function parseJson(stdout) {
    return JSON.parse(stdout);
}
/**
 * Load detailed ruleset rows for every ruleset id in the list response.
 * @param owner - Repository owner
 * @param repo - Repository name
 * @param listed - Parsed rulesets list payload
 * @param cwd - Working directory
 * @param timeoutMs - Child-process timeout
 * @param signal - Probe cancellation signal
 * @returns Panel ruleset rows
 */
async function loadRulesetDetails(owner, repo, listed, cwd, timeoutMs, signal) {
    if (!Array.isArray(listed)) {
        throw new TypeError("Rulesets list was not an array");
    }
    return await Promise.all(listed.map(async (entry) => {
        if (entry === null || typeof entry !== "object") {
            throw new TypeError("Ruleset list entry was not an object");
        }
        const id = Reflect.get(entry, "id");
        if (typeof id !== "number") {
            throw new TypeError("Ruleset list entry omitted numeric id");
        }
        const detailStdout = await runGh(["api", `repos/${owner}/${repo}/rulesets/${String(id)}`], cwd, timeoutMs, signal);
        return mapRulesetRow(parseJson(detailStdout));
    }));
}
/** Default `gh` implementations used by `lisa ui`. */
export const defaultGithubRepoGhReads = {
    readSettings: async (owner, repo, cwd, timeoutMs, signal) => {
        const stdout = await runGh(["api", `repos/${owner}/${repo}`], cwd, timeoutMs, signal);
        return mapRepoSettings(parseJson(stdout));
    },
    listRulesets: async (owner, repo, cwd, timeoutMs, signal) => {
        const listStdout = await runGh(["api", `repos/${owner}/${repo}/rulesets`], cwd, timeoutMs, signal);
        return loadRulesetDetails(owner, repo, parseJson(listStdout), cwd, timeoutMs, signal);
    },
    listLabels: async (owner, repo, cwd, timeoutMs, signal) => {
        const stdout = await runGh([
            "label",
            "list",
            "--repo",
            `${owner}/${repo}`,
            "--limit",
            "200",
            "--json",
            "name,color",
        ], cwd, timeoutMs, signal);
        const parsed = parseJson(stdout);
        if (!Array.isArray(parsed)) {
            throw new TypeError("Label list was not an array");
        }
        return parsed.map(entry => {
            if (entry === null || typeof entry !== "object") {
                throw new TypeError("Label entry was not an object");
            }
            return {
                name: requireNamedString(entry, "name"),
                color: requireNamedString(entry, "color"),
            };
        });
    },
    listSecretNames: async (owner, repo, cwd, timeoutMs, signal) => {
        const stdout = await runGh(["secret", "list", "--repo", `${owner}/${repo}`, "--json", "name"], cwd, timeoutMs, signal);
        const parsed = parseJson(stdout);
        if (!Array.isArray(parsed)) {
            throw new TypeError("Secret list was not an array");
        }
        return parsed.map(entry => {
            if (entry === null || typeof entry !== "object") {
                throw new TypeError("Secret entry was not an object");
            }
            return requireNamedString(entry, "name");
        });
    },
};
//# sourceMappingURL=ui-github-repo-gh.js.map