import { randomUUID } from "node:crypto";
import { loadConfig } from "../config/index.js";
import { logger } from "../logger.js";
import { ensureE2ERunDir, deleteE2ERunDir, listRecentRunIds } from "./artifacts.js";
import { getSuitesForMode } from "./registry.js";
import { aggregateStatus, formatE2EStartMessage, formatE2ESummary, writeReports } from "./reporter.js";
import { formatCleanupList, hasFailedCleanupItems, loadCleanupItems, runCleanupForRun, saveCleanupItems } from "./cleanup.js";
import { completeGoogleGuestSetupFromCallback, startGoogleGuestSetup, } from "./setup-google-guest.js";
function makeRunId() {
    const stamp = new Date().toISOString().replace(/[-:TZ.]/g, "").slice(0, 14);
    return `e2e_${stamp}_${randomUUID().slice(0, 4)}`;
}
export async function runE2E(options) {
    const config = loadConfig();
    if (options.mode === "help") {
        return [
            "/e2e — Run E2E tests",
            "",
            "Usage: /e2e [mode] [flags]",
            "",
            "Modes:",
            "  (none)   — all suites (self + memory + browser + cua + google)",
            "  smoke    — same as default",
            "  self     — self-check only (config, secrets, display, CDP)",
            "  browser  — browser suite + detection tests",
            "  cua      — CUA suite only (display + click/type)",
            "  google   — Google Workspace suite only",
            "  cleanup  — list runs and their cleanup state",
            "  cleanup <runId> — clean up and delete a specific run",
            "  cleanup latest — clean up and delete the most recent run",
            "  cleanup all — clean up and delete all runs",
            "  setup google-guest <email> — start remote Google guest account OAuth flow",
            "  setup google-guest <email> --local — start local browser Google guest setup",
            "  setup google-guest-code <id> <url> — complete OAuth with callback URL",
            "  help     — show this message",
            "",
            "Flags:",
            "  --json             — output raw JSON result",
            "  --auto-cleanup     — clean up test artifacts immediately after run",
            "",
            "Examples:",
            "  /e2e",
            "  /e2e cua",
            "  /e2e google --json",
            "  /e2e cleanup e2e_20260520130853_64be",
        ].join("\n");
    }
    if (options.mode === "cleanup") {
        return handleCleanup(config, options);
    }
    if (options.mode === "setup") {
        return handleSetup(config, options);
    }
    const runId = makeRunId();
    const artifactsDir = ensureE2ERunDir(runId);
    const startedAt = new Date().toISOString();
    const cleanupItems = [];
    logger.system(formatE2EStartMessage(runId, options.mode));
    const context = {
        runId,
        mode: options.mode,
        config,
        options,
        artifactsDir,
        addCleanupItem: (item) => {
            cleanupItems.push({
                ...item,
                createdAt: new Date().toISOString(),
                cleanupStatus: "pending",
            });
        },
    };
    const suites = [];
    for (const suite of getSuitesForMode(options.mode)) {
        suites.push(await suite.run(context));
    }
    saveCleanupItems(runId, cleanupItems);
    const cleanup = options.autoCleanup
        ? await runCleanupForRun(config, runId)
        : { status: "skipped", items: cleanupItems, message: "Artifacts retained; run /e2e cleanup to remove" };
    const finishedAt = new Date().toISOString();
    const result = {
        runId,
        mode: options.mode,
        startedAt,
        finishedAt,
        status: aggregateStatus([...suites.map((suite) => suite.status), cleanup.status]),
        durationMs: Date.parse(finishedAt) - Date.parse(startedAt),
        suites,
        artifactsDir,
        cleanup,
    };
    writeReports(result);
    return result;
}
async function handleCleanup(config, options) {
    const target = options.cleanupTarget;
    if (!target)
        return formatCleanupList();
    let runId = target;
    if (target === "latest") {
        runId = listRecentRunIds(1)[0] ?? "";
        if (!runId)
            return "No recent E2E runs found.";
    }
    if (target === "all" || target === "--all-stale" || target === "--failed") {
        const recentRunIds = listRecentRunIds(20);
        const runIds = target === "--failed" ? recentRunIds.filter((id) => hasFailedCleanupItems(id)) : recentRunIds;
        const lines = [`Running cleanup for ${runIds.length} run(s)...`];
        for (const id of runIds) {
            const result = await runCleanupForRun(config, id);
            deleteE2ERunDir(id);
            lines.push(`- ${id}: ${result.status} (deleted)`);
        }
        return lines.join("\n");
    }
    const items = loadCleanupItems(runId);
    if (items.length === 0) {
        const deleted = deleteE2ERunDir(runId);
        return deleted
            ? `Deleted run ${runId} (no cleanup items).`
            : `Run ${runId} not found.`;
    }
    const result = await runCleanupForRun(config, runId);
    deleteE2ERunDir(runId);
    return `Cleanup for ${runId}: ${result.status} (deleted)${result.message ? `\n${result.message}` : ""}`;
}
async function handleSetup(config, options) {
    if (options.setupKind === "google-guest-code") {
        const setupId = options.args[2];
        const callbackUrl = options.args.slice(3).join(" ");
        if (!setupId || !callbackUrl) {
            throw new Error("Usage: e2e setup google-guest-code <setupId> <callbackUrl>");
        }
        const result = await completeGoogleGuestSetupFromCallback(config, setupId, callbackUrl);
        return result.message;
    }
    if (options.setupKind === "google-guest") {
        const email = options.args.at(2) ?? config.e2e?.google?.meetGuestEmail ?? process.env.E2E_GOOGLE_MEET_GUEST_EMAIL;
        if (!email)
            throw new Error("Guest email is required");
        const result = await startGoogleGuestSetup(config, email, {
            remote: !options.flags.has("--local"),
            requestSource: "cli",
        });
        return result.message;
    }
    throw new Error("Unknown e2e setup command");
}
export function formatE2EResult(result, json = false) {
    if (json)
        return JSON.stringify(result, null, 2);
    return formatE2ESummary(result);
}
//# sourceMappingURL=runner.js.map