import { existsSync } from "node:fs";
import { basename, resolve } from "node:path";
import { confirm, input, select } from "@inquirer/prompts";
import { logger } from "../common/logger.js";
import { printCriticalFailureToConsoleAndExit, printResultToConsoleAndExitGracefully, printWarningToConsole, } from "../common/output.js";
import settings from "../common/settings.js";
import { isInteractiveTerminal } from "../common/terminal.js";
import { deploy } from "../deploy/handler.js";
import { login } from "../login/login.js";
import { getAuthToken } from "../login/tokens.js";
import { createProject } from "../project/create/handler.js";
async function fetchAccounts(authToken) {
    try {
        const response = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts`, {
            method: "GET",
            headers: {
                Authorization: `Bearer ${authToken}`,
            },
        });
        if (response.ok) {
            const data = await response.json();
            return data.data;
        }
        logger.error(`Failed to fetch accounts: received ${response.status} ${response.statusText}`);
    }
    catch (error) {
        logger.error(`Failed to fetch accounts: ${String(error)}`);
    }
    return [];
}
async function fetchProjects(authToken, accountName) {
    const url = new URL(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/projects`);
    url.searchParams.set("accountName", accountName);
    try {
        const response = await fetch(url, {
            method: "GET",
            headers: {
                Authorization: `Bearer ${authToken}`,
            },
        });
        if (!response.ok) {
            let errorBody;
            try {
                errorBody = await response.text();
            }
            catch {
            }
            logger.error(`Failed to fetch projects for account "${accountName}": ` +
                `${response.status} ${response.statusText}` +
                (errorBody ? ` - ${errorBody}` : ""));
            return [];
        }
        const data = await response.json();
        return data.data;
    }
    catch (error) {
        logger.error(`Error while fetching projects for account "${accountName}":`, error);
        return [];
    }
}
async function ensureAuthenticated() {
    let token = await getAuthToken();
    if (!token) {
        if (!isInteractiveTerminal()) {
            logger.debug("Non-interactive mode, skipping login prompt");
            return undefined;
        }
        const shouldLogin = await confirm({
            message: "You are not logged in. Would you like to log in now?",
            default: true,
        });
        if (!shouldLogin) {
            return undefined;
        }
        await login();
        token = await getAuthToken();
    }
    return token;
}
export async function init(argv) {
    const skipPrompts = argv.yes || !isInteractiveTerminal();
    let projectPath;
    if (argv.dir) {
        projectPath = resolve(argv.dir);
    }
    else {
        projectPath = process.cwd();
    }
    if (!existsSync(projectPath)) {
        await printCriticalFailureToConsoleAndExit(`Directory ${projectPath} does not exist. Please create your project first using 'npx create-zuplo-api'.`);
        return;
    }
    const authToken = await ensureAuthenticated();
    if (!authToken) {
        await printResultToConsoleAndExitGracefully("\nSkipped platform initialization. You can run 'zuplo init' later to set up your project.");
        return;
    }
    let accountName;
    let projectName;
    if (argv.withAccount) {
        accountName = argv.withAccount;
    }
    else {
        const accounts = await fetchAccounts(authToken);
        if (accounts.length === 0) {
            console.log("\nNo accounts found. Please create an account at https://portal.zuplo.com first.");
            return;
        }
        else if (accounts.length === 1) {
            accountName = accounts[0].name;
        }
        else if (!skipPrompts) {
            accountName = await select({
                message: "Select the account",
                choices: accounts.map((acc) => ({
                    name: acc.name,
                    value: acc.name,
                })),
            });
        }
        else {
            accountName = accounts[0].name;
        }
    }
    if (!accountName) {
        await printCriticalFailureToConsoleAndExit("No account selected.");
        return;
    }
    const shouldCreateProject = argv.withProject !== undefined ||
        (skipPrompts
            ? true
            : await confirm({
                message: "Would you like to create a new Zuplo project?",
                default: true,
            }));
    if (shouldCreateProject) {
        projectName = argv.withProject || basename(projectPath);
        if (!argv.withProject && !skipPrompts) {
            projectName = await input({
                message: "Enter the project name",
                default: basename(projectPath),
            });
        }
        try {
            await createProject({
                name: projectName,
                account: accountName,
                authToken,
            });
        }
        catch {
            console.log("\nFailed to create project. You can create one later at https://portal.zuplo.com");
            return;
        }
    }
    else {
        const projects = await fetchProjects(authToken, accountName);
        if (projects.length === 0) {
            console.log("\nNo projects found. Create a project first using 'zuplo project create'.");
        }
        else if (projects.length === 1) {
            projectName = projects[0].name;
        }
        else if (!skipPrompts) {
            projectName = await select({
                message: "Select the project",
                choices: projects.map((proj) => ({
                    name: proj.name,
                    value: proj.name,
                })),
            });
        }
    }
    if (!projectName) {
        await printResultToConsoleAndExitGracefully("\nNo project selected. You can run 'zuplo init' later to set up your project.");
        return;
    }
    const shouldDeploy = skipPrompts ||
        (await confirm({
            message: "Would you like to deploy your project now? (This creates the initial environment)",
            default: true,
        }));
    const defaultEnvironment = "main";
    if (shouldDeploy) {
        console.log();
        console.log("Deploying your project...");
        try {
            await deploy({
                account: accountName,
                project: projectName,
                dir: projectPath,
                environment: defaultEnvironment,
                authToken,
            });
        }
        catch (error) {
            logger.debug("Initial deployment failed", error);
            printWarningToConsole("Initial deployment failed. You can deploy later using 'zuplo deploy'.");
        }
    }
    const isCurrentDir = resolve(projectPath) === resolve(process.cwd());
    const getStartedMessage = `\nProject initialized successfully!\n\nTo get started:\n${isCurrentDir ? "" : `  cd ${basename(projectPath)}\n`}  npm run dev`;
    await printResultToConsoleAndExitGracefully(getStartedMessage);
}
//# sourceMappingURL=handler.js.map