/**
 * `spectral login` — interactive authentication against the Aexol MCP backend.
 *
 * Flow:
 *   1. Choose auth method: Team API key or OAuth (browser).
 *   2a. API key: prompt for team API key (masked input). Verify the
 *       sk-aexol-team- prefix locally so we don't send obviously-wrong
 *       credentials. The API URL is taken from env or the hard default.
 *   2b. OAuth: open browser for Aexol Studio authorization.
 *   3. Verify reachability + auth by calling tools/list against the URL.
 *   4. On success: persist to ~/.spectral/config.json (mode 0600).
 *
 * Exits non-zero on any failure so shell scripts can detect it.
 *
 * NOTE: pure logic lives in `performLogin` — the interactive `runLogin`
 * wrapper delegates to it after collecting prompts. Tests target
 * `performLogin` directly so we don't have to drive `@inquirer/prompts`.
 */
import { password, select } from "@inquirer/prompts";
import pc from "picocolors";
import { TEAM_API_KEY_PREFIX, getApiUrl, getConfigFile, validateTeamApiKey, writeConfig, } from "../config.js";
import { AexolMcpClient, AexolMcpError } from "../mcp-client.js";
/**
 * Pure login logic. Throws `Error` with one of these stable message prefixes:
 *   - "Invalid API key prefix"  — local validation failed
 *   - "Invalid token"           — server returned 401/403
 *   - "Authentication failed"   — server rejected the request (other 4xx/5xx)
 *   - "Could not reach"         — network error (DNS, refused connection, timeout)
 *
 * Tests assert on these substrings.
 */
export async function performLogin(opts) {
    const apiUrl = opts.apiUrl?.trim() ?? "";
    const teamApiKey = opts.teamApiKey?.trim() ?? "";
    if (!apiUrl) {
        throw new Error("API URL is required");
    }
    if (!validateTeamApiKey(teamApiKey)) {
        throw new Error(`Invalid API key prefix: token must start with "${TEAM_API_KEY_PREFIX}"`);
    }
    const client = new AexolMcpClient(apiUrl, teamApiKey);
    let toolCount;
    try {
        const tools = await client.listTools();
        toolCount = tools.length;
    }
    catch (err) {
        if (err instanceof AexolMcpError) {
            if (err.status === 401 || err.status === 403) {
                throw new Error(`Invalid token: Authentication failed (HTTP ${err.status}). Check that the key is correct and active.`);
            }
            if (err.status !== undefined) {
                throw new Error(`Authentication failed: ${err.message}`);
            }
            throw new Error(`Could not reach ${apiUrl}: ${err.message}`);
        }
        const msg = err instanceof Error ? err.message : String(err);
        throw new Error(`Could not reach ${apiUrl}: ${msg}`);
    }
    const cfg = { apiUrl, teamApiKey };
    await writeConfig(cfg);
    return { toolCount };
}
export async function runLogin() {
    process.stdout.write(pc.bold("Spectral login\n"));
    process.stdout.write(pc.dim(`Authenticate against the Aexol MCP backend. Credentials are stored at ${getConfigFile()} (chmod 600).\n\n`));
    // Step 1: choose auth method
    let authMethod;
    try {
        authMethod = await select({
            message: "How would you like to authenticate?",
            choices: [
                { name: "Team API key", value: "apikey" },
                { name: "OAuth (browser)", value: "oauth" },
            ],
        });
    }
    catch (err) {
        const name = err?.name;
        if (name === "ExitPromptError") {
            process.stderr.write(pc.yellow("\nLogin cancelled.\n"));
            process.exit(130);
        }
        throw err;
    }
    if (authMethod === "oauth") {
        const { runLoginOAuth } = await import("./login-oauth.js");
        await runLoginOAuth();
        return;
    }
    // Team API key flow: no URL prompt — use env or default.
    const apiUrl = getApiUrl();
    let teamApiKey;
    try {
        teamApiKey = (await password({
            message: `Team API key (starts with "${TEAM_API_KEY_PREFIX}")`,
            mask: "*",
            validate: (v) => {
                const trimmed = v.trim();
                if (trimmed.length === 0)
                    return "Token is required";
                if (!validateTeamApiKey(trimmed)) {
                    return `Token must start with "${TEAM_API_KEY_PREFIX}"`;
                }
                return true;
            },
        })).trim();
    }
    catch (err) {
        const name = err?.name;
        if (name === "ExitPromptError") {
            process.stderr.write(pc.yellow("\nLogin cancelled.\n"));
            process.exit(130);
        }
        throw err;
    }
    process.stdout.write(pc.dim(`\nVerifying credentials against ${apiUrl} ...\n`));
    let result;
    try {
        result = await performLogin({ apiUrl, teamApiKey });
    }
    catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        process.stderr.write(pc.red(`✗ ${msg}\n`));
        process.exit(1);
    }
    process.stdout.write(pc.green(`✓ Authenticated. Found ${result.toolCount} tools.\n`));
    process.stdout.write(pc.dim(`Saved credentials to ${getConfigFile()}\n`));
}
