import fs from "node:fs";
import path from "node:path";
import prompts from "prompts";
import { chromium } from "playwright";
import { configExists, ensureConfigDir, getPlaywrightProfileDir, getProfile, saveConfig, } from "../config/index.js";
import { installBuiltinSkills } from "../skills/install.js";
import { CLAUDE_OPUS_MODEL, CLAUDE_SONNET_MODEL, GPT_MODEL } from "../config/models.js";
import { hasLocalGoogleRefreshToken } from "../google/token-file.js";
import { applyServerGoogleOAuthTokensForSetup } from "./setup-credentials.js";
import { checkGhAuthenticated, checkGhInstalled, checkMacOSPermissions } from "./macos-permissions.js";
import { loadProvisioningSpec } from "./provisioning-spec.js";
import { provisionEthWallet } from "./provision-eth-wallet.js";
import { deleteSetupState, loadSetupState, updateSetupState } from "./setup-state.js";
import { spawnGhAuthLoginWithBrowser } from "./gh-auth-browser.js";
import { installDaemon as installVisionclawDaemon } from "../service/daemon.js";
import { generateAndSetWallpaper } from "./generate-wallpaper.js";
import { configureMacMiniDisplayResolution } from "./prepare-mac.js";
import { applyWorkspaceProfilePhoto, authenticateGithubWithPat, buildVisionClawConfig, downloadProfilePhotos, resolveGithubUsername, writeIdentityMemory, } from "./setup-shared.js";
function findChromePath() {
    if (process.platform === "darwin") {
        return "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
    }
    const candidates = [
        path.join(process.env.PROGRAMFILES ?? "C:\\Program Files", "Google", "Chrome", "Application", "chrome.exe"),
        path.join(process.env["PROGRAMFILES(X86)"] ?? "C:\\Program Files (x86)", "Google", "Chrome", "Application", "chrome.exe"),
        path.join(process.env.LOCALAPPDATA ?? "", "Google", "Chrome", "Application", "chrome.exe"),
    ];
    for (const candidate of candidates) {
        if (fs.existsSync(candidate)) {
            return candidate;
        }
    }
    return candidates[0];
}
const CHROME_PATH = findChromePath();
const ANSI_RESET = "\x1b[0m";
const ANSI_BOLD = "\x1b[1m";
const ANSI_GREEN = "\x1b[32m";
const ANSI_YELLOW = "\x1b[33m";
const ANSI_CYAN = "\x1b[36m";
function color(text, code) {
    return `${code}${text}${ANSI_RESET}`;
}
function success(text) {
    return color(text, ANSI_GREEN);
}
function action(text) {
    return color(text, ANSI_YELLOW);
}
function label(text) {
    return color(text, ANSI_CYAN);
}
function strong(text) {
    return color(text, ANSI_BOLD);
}
function resolveSetupSource(commandArgs) {
    for (let i = 0; i < commandArgs.length; i++) {
        const arg = commandArgs[i];
        if (arg === "--profile" && i + 1 < commandArgs.length) {
            i++;
            continue;
        }
        if (arg.startsWith("-")) {
            continue;
        }
        return arg;
    }
    throw new Error("Usage: visionclaw setup <6-digit-code | provisioning-json-source>");
}
async function waitForOperator(message) {
    await prompts({
        type: "confirm",
        name: "done",
        message,
        initial: true,
    });
}
async function getPrimaryPage(context) {
    const existing = context.pages().at(0);
    return existing ?? context.newPage();
}
async function launchPersistentChrome() {
    ensureConfigDir();
    const profileDir = getPlaywrightProfileDir();
    fs.mkdirSync(profileDir, { recursive: true });
    if (!fs.existsSync(CHROME_PATH)) {
        throw new Error(`Chrome not found at ${CHROME_PATH}`);
    }
    return chromium.launchPersistentContext(profileDir, {
        headless: false,
        executablePath: CHROME_PATH,
        args: ["--no-first-run", "--no-default-browser-check"],
        viewport: null,
    });
}
export async function setupPlaywrightGmailLogin(gmail) {
    const context = await launchPersistentChrome();
    try {
        const page = await getPrimaryPage(context);
        await page.goto(`https://accounts.google.com/signin/v2/identifier?service=mail&flowName=GlifWebSignIn&flowEntry=ServiceLogin&Email=${encodeURIComponent(gmail)}`, { waitUntil: "domcontentloaded" });
        console.log(`\nChrome opened with the VisionClaw Playwright profile for ${gmail}.`);
        await waitForOperator("Press Enter after you have finished refreshing the Google login.");
    }
    finally {
        await context.close();
    }
}
async function ensureGoogleBrowserLogin(context, gmail, password) {
    const page = await getPrimaryPage(context);
    await page.goto(`https://accounts.google.com/signin/v2/identifier?service=mail&flowName=GlifWebSignIn&flowEntry=ServiceLogin&Email=${encodeURIComponent(gmail)}`, { waitUntil: "domcontentloaded" });
    console.log(`\n${action(strong("Google sign-in is manual."))}`);
    console.log(action("Use the opened Chrome window in the VisionClaw Playwright profile to complete sign-in."));
    console.log(action("Google may request phone number, recovery, or other verification steps."));
    console.log(`\n${strong("Credentials for operator use:")}`);
    console.log(`  ${label("Email:")} ${strong(gmail)}`);
    console.log(`  ${label("Password:")} ${strong(password)}`);
    console.log(`\n${action(`Complete any remaining Google sign-in steps for ${gmail} in the opened Chrome window.`)}`);
    await waitForOperator("Press Enter after Google sign-in is complete.");
}
async function maybeSetupGithub(context, spec, state) {
    if (!spec.github.enabled) {
        return state;
    }
    if (state.githubAuthComplete) {
        if (!state.githubUsername) {
            const username = resolveGithubUsername();
            if (username) {
                return updateSetupState({ githubUsername: username });
            }
        }
        return state;
    }
    const ghInstalled = await checkGhInstalled();
    if (!ghInstalled) {
        throw new Error("GitHub setup requested, but gh is not installed");
    }
    const ghAuthed = await checkGhAuthenticated();
    if (ghAuthed) {
        const username = resolveGithubUsername();
        return updateSetupState({ githubAuthComplete: true, githubUsername: username });
    }
    const githubPat = spec.github.pat?.trim();
    if (githubPat) {
        const auth = authenticateGithubWithPat(githubPat);
        if (!auth.ok) {
            throw new Error(auth.error ?? "GitHub PAT auth failed");
        }
        return updateSetupState({ githubAuthComplete: true, githubUsername: auth.username });
    }
    const page = await getPrimaryPage(context);
    if (spec.github.createAccountIfMissing) {
        await page.goto("https://github.com/signup", { waitUntil: "domcontentloaded" });
        console.log("\nIf this Google identity does not already have a GitHub account, create it now using \"Continue with Google\".");
        console.log("Setup is paused and will wait for you to finish any GitHub signup friction in the browser.");
        await waitForOperator("Press Enter after GitHub signup/sign-in is complete in the browser.");
    }
    console.log("\nStarting GitHub CLI auth...");
    console.log("\n https://github.com/login/device");
    const result = spawnGhAuthLoginWithBrowser();
    if (result.status !== 0) {
        throw new Error("gh auth login --web failed");
    }
    const authedAfter = await checkGhAuthenticated();
    if (!authedAfter) {
        throw new Error("GitHub CLI auth did not complete successfully");
    }
    const username = resolveGithubUsername();
    return updateSetupState({ githubAuthComplete: true, githubUsername: username });
}
/**
 * Pre-ship manufacturer setup using a provisioning JSON source.
 */
export async function runSetup(commandArgs = []) {
    ensureConfigDir();
    console.log(`${strong("=== VisionClaw Manufacturer Setup ===")}\n`);
    const source = resolveSetupSource(commandArgs);
    const { spec, setupCode } = await loadProvisioningSpec(source);
    if (configExists()) {
        throw new Error("Setup already completed for this profile. Use reconfigure to make changes.");
    }
    let permissionsOk;
    if (process.platform === "win32") {
        const { checkWindowsPrerequisites } = await import("./windows-permissions.js");
        permissionsOk = await checkWindowsPrerequisites();
    }
    else {
        permissionsOk = await checkMacOSPermissions();
    }
    if (!permissionsOk) {
        const continueResult = (await prompts({
            type: "confirm",
            name: "continueSetup",
            message: "Continue setup without full permissions?",
            initial: true,
        }));
        if (!continueResult.continueSetup) {
            throw new Error("Setup cancelled until required permissions are granted");
        }
    }
    let state = loadSetupState();
    const deliveredGmailPassword = spec.gmailPassword?.trim();
    if (!spec.googleActivated || !deliveredGmailPassword || !spec.emailUsername) {
        throw new Error("Google Workspace account must be provisioned and activated on the onboarding server before client setup. " +
            "Complete Google provisioning/activation in the onboarding server, regenerate the spec, then retry setup.");
    }
    const workspaceAccount = {
        email: `${spec.emailUsername}@${spec.workspaceDomain}`,
        password: deliveredGmailPassword,
        existed: true,
    };
    console.log(`\n${success(`Workspace account is activated on the server (${workspaceAccount.email}).`)}`);
    state = updateSetupState({
        gmail: workspaceAccount.email,
        gmailPassword: workspaceAccount.password,
    });
    console.log(`\n${success(`Workspace account ready: ${workspaceAccount.email}`)}`);
    const context = await launchPersistentChrome();
    try {
        await ensureGoogleBrowserLogin(context, workspaceAccount.email, workspaceAccount.password);
        if (!state.googleOAuthComplete && hasLocalGoogleRefreshToken()) {
            state = updateSetupState({ googleOAuthComplete: true });
            console.log("Google OAuth tokens already present; skipping browser OAuth.");
        }
        if (!state.googleOAuthComplete && setupCode) {
            const applied = await applyServerGoogleOAuthTokensForSetup(setupCode);
            if (applied) {
                state = updateSetupState({ googleOAuthComplete: true });
                console.log("Google OAuth tokens delivered by server; skipping browser OAuth.");
            }
        }
        if (!state.googleOAuthComplete) {
            console.log("Google OAuth tokens are managed by the onboarding server and are not available locally yet. " +
                "They will be delivered by setup credentials or runtime heartbeat after server-side authorization.");
        }
        state = await maybeSetupGithub(context, spec, state);
    }
    finally {
        await context.close();
    }
    if (!state.ethAddress || !state.ethPrivateKey || !state.ethMnemonic) {
        const wallet = provisionEthWallet();
        state = updateSetupState({
            ethAddress: wallet.address,
            ethPrivateKey: wallet.privateKey,
            ethMnemonic: wallet.mnemonic,
        });
    }
    const modelResult = (await prompts({
        type: "select",
        name: "model",
        message: "AI model:",
        choices: [
            { title: "Claude Opus 4.8", value: CLAUDE_OPUS_MODEL },
            { title: "Claude Sonnet 4.6", value: CLAUDE_SONNET_MODEL },
            { title: "GPT-5.5", value: GPT_MODEL },
        ],
        initial: 0,
    }));
    const selectedModel = modelResult.model ?? CLAUDE_SONNET_MODEL;
    const config = buildVisionClawConfig({
        spec,
        state,
        gmail: state.gmail ?? workspaceAccount.email,
        gmailPassword: state.gmailPassword ?? workspaceAccount.password,
        model: selectedModel,
    });
    saveConfig(config);
    installBuiltinSkills();
    // Telegram bot name and profile photo are now set by the onboarding admin
    // when the agent is created, so we only download photos for local storage
    // and set the Google Workspace profile photo here.
    console.log("\nDownloading profile photos...");
    const photoSources = spec.telegram.profilePhotoSources?.filter(Boolean) ?? [];
    const reportPhotoStep = (msg) => { console.log(msg); };
    const savedPhotos = await downloadProfilePhotos(photoSources, reportPhotoStep);
    await applyWorkspaceProfilePhoto(spec, config.gmail, savedPhotos, reportPhotoStep);
    writeIdentityMemory({
        gmail: config.gmail,
        gmailPassword: config.gmailPassword ?? workspaceAccount.password,
        systemPassword: config.systemPassword,
        wallet: {
            address: state.ethAddress ?? "",
            privateKey: state.ethPrivateKey ?? "",
            mnemonic: state.ethMnemonic ?? "",
        },
        profilePhotos: savedPhotos,
        githubUsername: state.githubUsername ?? undefined,
    });
    if (process.platform === "darwin") {
        console.log("\nReapplying Mac mini display resolution...");
        configureMacMiniDisplayResolution();
    }
    // Generate wallpaper with agent name (green bg) and set as desktop background.
    if (process.platform === "darwin") {
        console.log("\nGenerating desktop wallpaper...");
        try {
            const wallpaperPath = generateAndSetWallpaper(config.agentName);
            console.log(`  Wallpaper set: ${wallpaperPath}`);
        }
        catch (err) {
            console.log(`  Warning: wallpaper generation failed: ${err instanceof Error ? err.message : String(err)}`);
        }
    }
    deleteSetupState();
    if (process.platform === "darwin") {
        if (!spec.installService) {
            console.log("  Daemon install disabled in spec. You can install it later with: visionclaw daemon install");
        }
        else {
            const installAgent = (await prompts({
                type: "confirm",
                name: "value",
                message: "Install visionclaw as a login service (LaunchAgent)?",
                initial: true,
            }));
            if (installAgent.value) {
                await installVisionclawDaemon({ profile: getProfile() });
            }
            else {
                console.log("  Skipped visionclaw daemon installation. You can install it later with: visionclaw daemon install");
            }
        }
    }
    console.log("\nManufacturer configuration saved successfully!");
    console.log(`Gmail: ${config.gmail}`);
    console.log(`Telegram bot: ${spec.telegram.botName.trim()}`);
    console.log(`ETH address: ${state.ethAddress}`);
    console.log("\n=== Quick Reference ===\n");
    console.log('To start agent:');
    console.log("visionclaw daemon start --debug");
    console.log("To install auto-start on login:");
    console.log("visionclaw daemon install --debug");
    console.log("To check agent logs:");
    console.log("visionclaw daemon logs");
    if (config.onboardingServiceUrl) {
        const onboardingLink = `${config.onboardingServiceUrl.replace(/\/+$/, "")}/${encodeURIComponent(config.agentName)}`;
        console.log(`\nOnboarding link: ${onboardingLink}`);
    }
}
//# sourceMappingURL=index.js.map