import fs from "node:fs/promises";
import path from "node:path";
import { inspect } from "node:util";
import { normalizePath } from "vite";
import yaml from "yaml";
import { getStableScopeId } from "@superblocksteam/library-shared";
import { findRouterFile, parseRouterFile, } from "./router-parser.js";
import { getErrorMeta, getLogger } from "./util/logger.js";
export async function getRoutes(rootDir) {
    const routerFile = await findRouterFile(rootDir);
    const routes = await parseRouterFile(routerFile, rootDir);
    return routes;
}
export async function getAllPages({ rootDir, }) {
    const routerFile = await findRouterFile(rootDir);
    const routes = await parseRouterFile(routerFile, rootDir);
    const pages = await Promise.all(routes.map(async (route) => {
        try {
            const contents = await fs.readFile(route.pageFilePath, "utf8");
            const name = getPageName(route.pageFilePath);
            return {
                name,
                contents,
                route: route.path,
                fileName: route.pageFilePath,
            };
        }
        catch (e) {
            getLogger().error(`Error reading page file ${route.pageFilePath}`, getErrorMeta(e));
            return null;
        }
    }));
    return pages.filter((p) => p !== null);
}
export const getPageName = (filePath) => {
    const normalizedPath = normalizePath(filePath);
    const parts = normalizedPath.split("/");
    const pagesIndex = parts.findIndex((part) => part === "pages");
    if (pagesIndex !== -1 && parts[pagesIndex + 1]) {
        return parts[pagesIndex + 1] ?? "";
    }
    return "";
};
export const getScopeNameFromPath = (filePath) => {
    // Handle page scopes (pages/PageName/index.tsx)
    if (filePath.includes("/pages/") && filePath.endsWith("/index.tsx")) {
        return getPageName(filePath);
    }
    return null;
};
/**
 * Generates a scope ID directly from a page file path.
 * This eliminates the need for scope.ts files and AST parsing.
 *
 * @param filePath - The page file path (e.g., "pages/Dashboard/index.tsx")
 * @returns The scope ID, or null if the path doesn't represent a page
 */
export const getScopeIdFromPath = (filePath) => {
    const scopeName = getScopeNameFromPath(filePath);
    if (!scopeName) {
        return null;
    }
    return getStableScopeId(scopeName);
};
export const getScopeIdFromName = (name) => {
    return getStableScopeId(name);
};
export async function getAllApiDefinitions({ rootDir, currentUrl: _currentUrl, }) {
    const logger = getLogger();
    try {
        const apisDir = path.join(rootDir, "apis");
        const objs = await fs.readdir(apisDir);
        const apiDefinitions = [];
        for (const obj of objs) {
            const stat = await fs.stat(path.join(apisDir, obj));
            if (stat.isFile() && obj.endsWith(".yaml")) {
                const contents = await fs.readFile(path.join(apisDir, obj), "utf8");
                const yamlContents = await yaml.parse(contents);
                const apiName = yamlContents.metadata.name;
                apiDefinitions.push({
                    name: apiName,
                    fileName: obj,
                    contents: yamlContents,
                });
            }
            else if (stat.isDirectory()) {
                const apiYamlPath = path.join(apisDir, obj, "api.yaml");
                const apiYamlStat = await fs.stat(apiYamlPath);
                if (apiYamlStat.isFile()) {
                    const contents = await fs.readFile(apiYamlPath, "utf8");
                    const yamlContents = await yaml.parse(contents);
                    const apiName = yamlContents.metadata.name;
                    apiDefinitions.push({
                        name: apiName,
                        fileName: path.join(apisDir, obj, "api.yaml"),
                        contents: yamlContents,
                    });
                }
            }
        }
        return apiDefinitions;
    }
    catch (e) {
        logger.error("Error getting api definitions", getErrorMeta(e));
        return [];
    }
}
export async function getApiDefinitionPath({ rootDir, currentUrl, apiName, }) {
    const apiDefinitions = await getAllApiDefinitions({ rootDir, currentUrl });
    return apiDefinitions.find((api) => api.name === apiName);
}
export const isValidApi = (api) => {
    const logger = getLogger();
    const isValidStep = (step) => {
        const isValidStep = !!step &&
            step.integration &&
            ((step.integration !== "javascript" && step.integration !== "python") ||
                (step.integration === "javascript" &&
                    typeof step.javascript?.body === "string") ||
                (step.integration === "python" &&
                    typeof step.python?.body === "string"));
        if (!isValidStep) {
            logger.warn(`API ${api.metadata.name} file incomplete: invalid step`);
        }
        return isValidStep;
    };
    const isValidBlock = (block) => {
        const isValidBlock = !!block && block.name && isValidStep(block.step);
        if (!isValidBlock) {
            logger.warn(`API ${api.metadata.name} file incomplete: invalid block`);
        }
        return isValidBlock;
    };
    const isValidMetadata = (metadata) => {
        const isValidMetadata = metadata.name && metadata.organization;
        if (!isValidMetadata) {
            logger.warn(`API ${api.metadata.name} file incomplete: invalid metadata`);
        }
        return isValidMetadata;
    };
    const isValidTrigger = (trigger) => {
        const isValidTrigger = trigger && trigger.application && trigger.application.id;
        if (!isValidTrigger) {
            logger.warn(`API ${api.metadata.name} file incomplete: invalid trigger`);
        }
        return isValidTrigger;
    };
    return (api &&
        isValidMetadata(api.metadata) &&
        isValidTrigger(api.trigger) &&
        (api.blocks?.length === 0 || api.blocks?.every(isValidBlock)));
};
/**
 * Call this on an EventEmitter to have it print all of its events in an inspectable format.
 * Very useful for debugging events.
 */
export function debugEventEmitter(emitter, name) {
    const orig_emit = emitter.emit;
    emitter.emit = function (...args) {
        const emitArgs = args;
        console.log("emitter " + name + " " + inspect(emitArgs));
        return orig_emit.apply(emitter, args);
    };
}
//# sourceMappingURL=util.js.map