import { execFile } from "node:child_process";
import { resolveCodexCli } from "./codex-cli.js";
const CODEX_CLI = "codex";
const COMMAND_TIMEOUT_MS = 10_000;
const AUTH_CACHE_TTL_MS = 30_000;
let cachedAuthStatus;
/**
 * Check whether Codex is currently authenticated.
 *
 * Priority:
 * 1. If CODEX_API_KEY is set in the environment, report authenticated via API key.
 * 2. Otherwise, shell out to `codex login status` to check CLI auth when an external CLI exists.
 * 3. If only the bundled SDK runtime is available, let the SDK validate auth when a turn starts.
 * 4. If an external CLI command fails or is unavailable, report unauthenticated.
 *
 * Results are cached for 30 seconds to avoid per-message CLI invocations.
 */
export async function checkAuthStatus(apiKey) {
    if (apiKey) {
        return {
            authenticated: true,
            method: "api-key",
            detail: "Authenticated via CODEX_API_KEY",
        };
    }
    if (cachedAuthStatus && Date.now() < cachedAuthStatus.expiresAt) {
        return cachedAuthStatus.status;
    }
    const cli = resolveCodexCli();
    if (cli.source === "bundled" && !cli.path) {
        const status = {
            authenticated: true,
            method: "bundled",
            detail: "Using bundled @openai/codex runtime; authentication will be validated when a turn starts.",
        };
        cachedAuthStatus = { status, expiresAt: Date.now() + AUTH_CACHE_TTL_MS };
        return status;
    }
    try {
        const { stdout } = await runCodexCommand(["login", "status"], cli);
        const output = stdout.trim();
        const status = {
            authenticated: true,
            method: "cli",
            detail: output || "Authenticated via Codex CLI",
        };
        cachedAuthStatus = { status, expiresAt: Date.now() + AUTH_CACHE_TTL_MS };
        return status;
    }
    catch (error) {
        const status = parseCommandError(error);
        cachedAuthStatus = { status, expiresAt: Date.now() + AUTH_CACHE_TTL_MS };
        return status;
    }
}
/**
 * Clear the cached auth status so the next check hits the CLI.
 */
export function clearAuthCache() {
    cachedAuthStatus = undefined;
}
/**
 * Attempt to start a login flow via the Codex CLI.
 * Uses --device-auth to get a device code flow suitable for headless/remote hosts.
 */
export async function startLogin() {
    clearAuthCache();
    try {
        const { stdout } = await runCodexCommand(["login", "--device-auth"]);
        const output = stdout.trim();
        return {
            success: true,
            message: output || "Login initiated. Check your terminal or browser for the next step.",
        };
    }
    catch (error) {
        const detail = extractErrorMessage(error);
        return {
            success: false,
            message: detail || "Login command failed. Try running 'codex auth login' on the host.",
        };
    }
}
/**
 * Attempt to logout via the Codex CLI.
 */
export async function startLogout() {
    clearAuthCache();
    try {
        const { stdout } = await runCodexCommand(["logout"]);
        const output = stdout.trim();
        return {
            success: true,
            message: output || "Logged out successfully.",
        };
    }
    catch (error) {
        const detail = extractErrorMessage(error);
        return {
            success: false,
            message: detail || "Logout command failed. Try running 'codex auth logout' on the host.",
        };
    }
}
function runCodexCommand(args, cli = resolveCodexCli()) {
    return new Promise((resolve, reject) => {
        execFile(cli.path ?? CODEX_CLI, args, {
            timeout: COMMAND_TIMEOUT_MS,
            env: { ...process.env },
            maxBuffer: 1024 * 1024,
        }, (error, stdout, stderr) => {
            if (error) {
                // Attach stdout/stderr to the error for richer diagnostics
                const enriched = error;
                enriched.stdout = typeof stdout === "string" ? stdout : "";
                enriched.stderr = typeof stderr === "string" ? stderr : "";
                reject(enriched);
                return;
            }
            resolve({
                stdout: typeof stdout === "string" ? stdout : "",
                stderr: typeof stderr === "string" ? stderr : "",
            });
        });
    });
}
function parseCommandError(error) {
    const errno = error?.code;
    if (errno === "ENOENT") {
        return {
            authenticated: false,
            method: "none",
            detail: "Codex CLI not found. Install it or set CODEX_API_KEY.",
        };
    }
    const detail = extractErrorMessage(error) || "Not authenticated";
    if (isConfigurationLoadError(detail)) {
        return {
            authenticated: true,
            method: "cli",
            detail: `Codex CLI auth precheck could not load configuration (${detail}); authentication will be validated when a turn starts.`,
        };
    }
    return {
        authenticated: false,
        method: "none",
        detail,
    };
}
function isConfigurationLoadError(detail) {
    return /error loading configuration/i.test(detail);
}
function extractErrorMessage(error) {
    if (typeof error === "object" && error !== null) {
        const enriched = error;
        const stderr = enriched.stderr?.trim();
        if (stderr) {
            return stderr;
        }
        const stdout = enriched.stdout?.trim();
        if (stdout) {
            return stdout;
        }
        if (enriched.signal) {
            return `Command terminated with signal ${enriched.signal}.`;
        }
        if (enriched.message) {
            return enriched.message;
        }
    }
    return error instanceof Error ? error.message : String(error);
}
