const ANSI = {
    reset: "\u001b[0m",
    dim: "\u001b[2m",
    bold: "\u001b[1m",
    cyan: "\u001b[36m",
    green: "\u001b[32m",
    yellow: "\u001b[33m",
    red: "\u001b[31m"
};
const optionalImport = new Function("specifier", "return import(specifier)");
function colorize(text, color) {
    return `${ANSI[color]}${text}${ANSI.reset}`;
}
export function info(text) {
    return colorize(text, "cyan");
}
export function success(text) {
    return colorize(text, "green");
}
export function warn(text) {
    return colorize(text, "yellow");
}
export function error(text) {
    return colorize(text, "red");
}
export function dim(text) {
    return colorize(text, "dim");
}
export async function createSpinner(text) {
    try {
        const oraModule = await optionalImport("ora");
        const spinnerFactory = oraModule.default;
        const spinner = spinnerFactory({
            text,
            isEnabled: process.stdout.isTTY
        }).start();
        return spinner;
    }
    catch {
        return {
            text,
            succeed(message) {
                if (message) {
                    process.stdout.write(`${success("✔")} ${message}\n`);
                }
            },
            fail(message) {
                if (message) {
                    process.stdout.write(`${error("✖")} ${message}\n`);
                }
            },
            stop() {
                // noop fallback
            }
        };
    }
}
export async function renderTable(headers, rows) {
    try {
        const tableModule = await optionalImport("cli-table3");
        const Table = tableModule.default;
        const table = new Table({
            head: headers.map((header) => colorize(header, "bold")),
            wordWrap: true,
            style: {
                head: [],
                border: []
            }
        });
        rows.forEach((row) => table.push(row));
        return table.toString();
    }
    catch {
        const widths = headers.map((header, index) => Math.max(stripAnsi(header).length, ...rows.map((row) => stripAnsi(row[index] ?? "").length)));
        const renderRow = (values) => values
            .map((value, index) => pad(value, widths[index] ?? value.length))
            .join("  ");
        return [
            renderRow(headers),
            renderRow(widths.map((width) => "-".repeat(width))),
            ...rows.map((row) => renderRow(row))
        ].join("\n");
    }
}
export async function printTable(logger, headers, rows) {
    logger.info(await renderTable(headers, rows));
}
export function printSection(logger, title) {
    logger.info(colorize(title, "bold"));
}
function stripAnsi(value) {
    return value.replace(/\u001b\[[0-9;]*m/g, "");
}
function pad(value, width) {
    const visible = stripAnsi(value).length;
    const padding = Math.max(0, width - visible);
    return `${value}${" ".repeat(padding)}`;
}
