import { createProviderEnvSpec, } from "../provider-launch-config.js";
import { execCommand } from "../../../utils/spawn.js";
export function formatProviderDiagnostic(providerName, entries) {
    return [providerName, ...entries.map((entry) => `  ${entry.label}: ${entry.value}`)].join("\n");
}
export function formatProviderDiagnosticError(providerName, error) {
    return formatProviderDiagnostic(providerName, [
        {
            label: "Error",
            value: toDiagnosticErrorMessage(error),
        },
    ]);
}
export function formatAvailabilityStatus(available) {
    return available ? "Available" : "Unavailable";
}
export function formatDiagnosticStatus(available, error) {
    if (error) {
        return `Error (${error.source} failed: ${toDiagnosticErrorMessage(error.cause)})`;
    }
    return formatAvailabilityStatus(available);
}
const DIAGNOSTIC_OUTPUT_CAP = 4096;
function truncateForDiagnostic(value) {
    const trimmed = value.trim();
    if (trimmed.length <= DIAGNOSTIC_OUTPUT_CAP) {
        return trimmed;
    }
    return `${trimmed.slice(0, DIAGNOSTIC_OUTPUT_CAP)}…(truncated)`;
}
function readStringProperty(error, key) {
    if (!(key in error))
        return undefined;
    const value = error[key];
    if (typeof value === "string") {
        return value;
    }
    if (typeof value === "number" || typeof value === "bigint") {
        return String(value);
    }
    return undefined;
}
function readUnknownProperty(error, key) {
    if (!(key in error))
        return undefined;
    return error[key];
}
function pushIfNonEmpty(sections, label, value) {
    if (value && value.trim().length > 0) {
        sections.push(`${label}: ${value.trim()}`);
    }
}
function pushTruncatedIfNonEmpty(sections, label, value) {
    if (value && value.trim().length > 0) {
        sections.push(`${label}: ${truncateForDiagnostic(value)}`);
    }
}
function formatErrorDiagnostic(error) {
    const sections = [];
    if (error.message && error.message.trim().length > 0) {
        sections.push(error.message.trim());
    }
    pushIfNonEmpty(sections, "exit code", readStringProperty(error, "code"));
    pushIfNonEmpty(sections, "signal", readStringProperty(error, "signal"));
    pushTruncatedIfNonEmpty(sections, "stderr", readStringProperty(error, "stderr"));
    pushTruncatedIfNonEmpty(sections, "stdout", readStringProperty(error, "stdout"));
    const cause = readUnknownProperty(error, "cause");
    if (cause !== undefined && cause !== null) {
        const causeMessage = toDiagnosticErrorMessage(cause);
        if (causeMessage && causeMessage !== "Unknown error") {
            sections.push(`caused by: ${causeMessage}`);
        }
    }
    return sections.length > 0 ? sections.join("\n") : "Unknown error";
}
function formatNonErrorDiagnostic(error) {
    try {
        const serialized = JSON.stringify(error);
        if (serialized && serialized !== "{}" && serialized !== '""') {
            return serialized;
        }
    }
    catch {
        // fall through to String() below
    }
    const stringified = String(error);
    if (stringified.length > 0 && stringified !== "[object Object]") {
        return stringified;
    }
    return "Unknown error";
}
export function toDiagnosticErrorMessage(error) {
    if (error instanceof Error) {
        return formatErrorDiagnostic(error);
    }
    if (typeof error === "string") {
        const trimmed = error.trim();
        return trimmed.length > 0 ? trimmed : "Unknown error";
    }
    if (error === null || error === undefined) {
        return "Unknown error";
    }
    return formatNonErrorDiagnostic(error);
}
export async function resolveBinaryVersion(binaryPath) {
    try {
        const { stdout } = await execCommand(binaryPath, ["--version"], {
            ...createProviderEnvSpec(),
            timeout: 5000,
        });
        return stdout.trim() || "unknown";
    }
    catch (error) {
        return `error: ${toDiagnosticErrorMessage(error)}`;
    }
}
async function resolveCommandVersion(invocation) {
    try {
        const { stdout, stderr } = await execCommand(invocation.command, invocation.args, {
            ...createProviderEnvSpec({ runtimeSettings: { env: invocation.env } }),
            timeout: 5000,
        });
        return stdout.trim() || stderr.trim() || "unknown";
    }
    catch (error) {
        return `error: ${toDiagnosticErrorMessage(error)}`;
    }
}
export async function buildBinaryDiagnosticRows(launch, availability, options = {}) {
    const defaultBinaryLabel = launch.source === "override" ? "Binary (override)" : "Binary";
    const binaryLabel = options.binaryLabel ?? defaultBinaryLabel;
    let version = "unknown";
    if (options.versionCommand && availability.available) {
        version = await resolveCommandVersion(options.versionCommand);
    }
    else if (availability.available) {
        version = await resolveCommandVersion({
            command: availability.resolvedPath ?? launch.command,
            args: [...launch.args, "--version"],
        });
    }
    return [
        {
            label: binaryLabel,
            value: launch.command,
        },
        {
            label: "Resolved path",
            value: availability.resolvedPath ?? "not found",
        },
        {
            label: "Version",
            value: version,
        },
    ];
}
export function formatConfiguredCommand(defaultArgv, runtimeSettings) {
    const command = runtimeSettings?.command;
    if (!command || command.mode === "default") {
        return `${defaultArgv.join(" ")} (default)`;
    }
    if (command.mode === "append") {
        return [defaultArgv[0], ...(command.args ?? []), ...defaultArgv.slice(1)].join(" ");
    }
    return command.argv.join(" ");
}
//# sourceMappingURL=diagnostic-utils.js.map