import { readFile } from "node:fs/promises";
import { input, select } from "@inquirer/prompts";
import { createProject, ProjectCreationError, } from "../../project/create/handler.js";
import { logger } from "../logger.js";
import { printCriticalFailureToConsoleAndExit, textOrJson } from "../output.js";
import { confirmLinkedValue, readLinkedConfig, USE_LINKED_DETAILS, } from "../read-linked-config.js";
import settings from "../settings.js";
import { isInteractiveTerminal } from "../terminal.js";
function isPromptExitError(error) {
    return (error instanceof Error &&
        (error.name === "ExitPromptError" ||
            ("isTtyError" in error &&
                error.isTtyError === true)));
}
function sanitizePackageJsonNameAsDefault(name) {
    if (typeof name !== "string")
        return undefined;
    const stripped = name.startsWith("@") ? (name.split("/")[1] ?? "") : name;
    return /^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/.test(stripped)
        ? stripped
        : undefined;
}
async function promptAndCreateProject(account, authToken, message) {
    let projectName;
    try {
        const packageJson = JSON.parse(await readFile("package.json", "utf-8"));
        projectName = sanitizePackageJsonNameAsDefault(packageJson.name);
    }
    catch (error) {
        logger.trace(error, "Failed to read package.json");
    }
    while (true) {
        let outputProjectName;
        try {
            outputProjectName = (await input({
                message,
                default: projectName,
                validate: (value) => {
                    if (!value.trim()) {
                        return "Project name cannot be empty.";
                    }
                    return true;
                },
            })).trim();
            projectName = outputProjectName;
        }
        catch (error) {
            if (isPromptExitError(error)) {
                process.exit(1);
            }
            throw error;
        }
        try {
            await createProject({ name: outputProjectName, account, authToken });
        }
        catch (error) {
            if (error instanceof ProjectCreationError && error.retryable) {
                continue;
            }
            throw error;
        }
        logger.trace({ projectName: outputProjectName }, "Project created successfully.");
        return outputProjectName;
    }
}
export async function fetchProject(argv) {
    if (argv.project && typeof argv.project === "string") {
        return;
    }
    if (!argv.account || typeof argv.account !== "string") {
        throw new Error("Invalid state: account is not set.");
    }
    if (argv[USE_LINKED_DETAILS] !== false) {
        const linked = await readLinkedConfig(argv);
        if (linked.projectName && linked.accountName === argv.account) {
            if (!isInteractiveTerminal()) {
                argv.project = linked.projectName;
                return;
            }
            const useLinked = await confirmLinkedValue(`Use linked project '${linked.projectName}'?`);
            if (useLinked) {
                argv.project = linked.projectName;
                return;
            }
            argv[USE_LINKED_DETAILS] = false;
        }
    }
    if (!isInteractiveTerminal()) {
        await printCriticalFailureToConsoleAndExit("Error: --project is required in non-interactive environments (e.g. CI/CD).\nSee your available projects at https://portal.zuplo.com, then re-run with --project <name>.");
        return;
    }
    const baseUrl = `${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/projects`;
    const queryParams = {
        accountName: argv.account,
    };
    const url = new URL(baseUrl);
    url.search = new URLSearchParams(queryParams).toString();
    const response = await fetch(url, {
        method: "GET",
        headers: {
            Authorization: `Bearer ${argv.authToken}`,
        },
    });
    if (response.ok) {
        const projectsJson = await response.json();
        if (projectsJson.data.length === 0) {
            try {
                argv.project = await promptAndCreateProject(argv.account, argv.authToken, "You don't have any projects configured for this account. Please enter a project name to create one.");
            }
            catch (error) {
                if (error instanceof ProjectCreationError) {
                    process.exit(1);
                }
                throw error;
            }
        }
        else {
            let selected;
            try {
                selected = await select({
                    message: "Select the project",
                    choices: [
                        { name: "+ Create a new project", value: null },
                        ...projectsJson.data
                            .map((project) => {
                            return {
                                name: project.name,
                                value: project.name,
                            };
                        })
                            .sort((a, b) => a.name.localeCompare(b.name)),
                    ],
                });
            }
            catch (error) {
                if (isPromptExitError(error)) {
                    process.exit(1);
                }
                logger.trace(error, "Failed to select project");
                process.exit(1);
            }
            if (selected === null) {
                try {
                    argv.project = await promptAndCreateProject(argv.account, argv.authToken, `Enter a name for the new project in account '${argv.account}'`);
                }
                catch (error) {
                    if (error instanceof ProjectCreationError) {
                        process.exit(1);
                    }
                    throw error;
                }
            }
            else {
                argv.project = selected;
            }
        }
    }
    else {
        if (response.status === 404) {
            await printCriticalFailureToConsoleAndExit("You don't have any projects configured for this account. Create a project in the Zuplo dashboard and try again.");
            return;
        }
        logger.trace({
            status: response.status,
            statusText: response.statusText,
            response: textOrJson(await response.text()),
        }, "Failed to request projects for account");
        await printCriticalFailureToConsoleAndExit("Error: Failed to request projects for the account.");
    }
}
//# sourceMappingURL=get-project-param.js.map