import { ErrorFactory } from './exceptions/ZintrustError.js';
import { isArray, isNonEmptyString, isObject } from './helper/index.js';
import { ZintrustLang } from './lang/lang.js';
import { normalizeActiveServiceRuntime, } from './microservices/ServiceManifest.js';
import { ProjectRuntime } from './runtime/ProjectRuntime.js';
import { isNodeRuntime } from './runtime/detectRuntime.js';
const isAbsolutePath = (value) => value.startsWith('/') || /^[A-Za-z]:[\\/]/.test(value);
const fileUrlToPathLike = (value) => {
    if (!value.startsWith(ZintrustLang.FILE_PROTOCOL))
        return value;
    // Basic file URL decoding (sufficient for macOS/Linux paths).
    try {
        return decodeURIComponent(value.slice(ZintrustLang.FILE_PROTOCOL.length));
    }
    catch {
        return value.slice(ZintrustLang.FILE_PROTOCOL.length);
    }
};
export const isNodeMain = (importMetaUrl) => {
    if (!isNodeRuntime())
        return false;
    const argv1 = process.argv;
    const scriptPath = Array.isArray(argv1) ? String(argv1[1] ?? '') : '';
    if (scriptPath === '')
        return false;
    const here = fileUrlToPathLike(importMetaUrl);
    if (scriptPath === here)
        return true;
    // Best-effort: handle relative argv paths and runner wrappers.
    return scriptPath.endsWith(here);
};
export const configureStandaloneService = (activeService) => {
    const normalized = normalizeActiveServiceRuntime(activeService);
    if (normalized === undefined) {
        throw ErrorFactory.createValidationError('Standalone service runtime requires at least domain and name.');
    }
    return ProjectRuntime.set({ activeService: normalized }).activeService ?? normalized;
};
const normalizeStandaloneEnvPaths = (value) => {
    if (isNonEmptyString(value)) {
        const trimmed = value.trim();
        return trimmed === '' ? [] : [trimmed];
    }
    if (!isArray(value))
        return [];
    return value
        .filter(isNonEmptyString)
        .map((item) => item.trim())
        .filter((item) => item !== '');
};
const resolveStandaloneProjectRoot = async () => {
    const configuredRoot = process.env?.['ZINTRUST_PROJECT_ROOT'] ?? '';
    if (isNonEmptyString(configuredRoot))
        return configuredRoot;
    const { existsSync } = await import('./node-singletons/fs.js');
    const path = await import('./node-singletons/path.js');
    let current = process.cwd();
    while (true) {
        if (existsSync(path.join(current, 'package.json')))
            return current;
        const parent = path.dirname(current);
        if (parent === current)
            return process.cwd();
        current = parent;
    }
};
const resolveServiceEnvPath = async (importMetaUrl, activeService, projectRoot) => {
    const path = await import('./node-singletons/path.js');
    if (isObject(activeService) && isNonEmptyString(activeService['configRoot'])) {
        return path.dirname(path.join(projectRoot, activeService['configRoot']));
    }
    const entryFile = fileUrlToPathLike(importMetaUrl);
    const entryDir = path.dirname(entryFile);
    return path.basename(entryDir) === 'src' ? path.dirname(entryDir) : entryDir;
};
const resolveConfiguredEnvPaths = async (projectRoot, activeService, importMetaUrl) => {
    const path = await import('./node-singletons/path.js');
    const configured = isObject(activeService)
        ? normalizeStandaloneEnvPaths(activeService['envPath'])
        : [];
    if (configured.length > 0) {
        return configured.map((value) => isAbsolutePath(value) ? value : path.join(projectRoot, value));
    }
    return [await resolveServiceEnvPath(importMetaUrl, activeService, projectRoot)];
};
const ensureStandaloneServiceEnv = async (importMetaUrl, activeService) => {
    if (!isNodeRuntime())
        return;
    const { EnvFileLoader } = await import('./cli/utils/EnvFileLoader.js');
    const projectRoot = await resolveStandaloneProjectRoot();
    const envPaths = await resolveConfiguredEnvPaths(projectRoot, activeService, importMetaUrl);
    const rootEnv = !isObject(activeService) || activeService['rootEnv'] !== false;
    EnvFileLoader.ensureLoaded({
        cwd: projectRoot,
        includeCwd: rootEnv,
        envPaths,
    });
};
export const bootStandaloneService = async (importMetaUrl, activeService) => {
    await ensureStandaloneServiceEnv(importMetaUrl, activeService);
    const configuredService = configureStandaloneService(activeService);
    if (isNodeMain(importMetaUrl)) {
        await start();
    }
    return configuredService;
};
/**
 * Start the Node server (dev/prod) by delegating to the framework bootstrap.
 *
 * This uses a non-literal dynamic import so Worker bundlers don't pull Node-only modules.
 */
export const start = async () => {
    if (!isNodeRuntime())
        return;
    const projectBootstrapModule = (await import('./runtime/ProjectBootstrap.js'));
    await projectBootstrapModule.loadProjectBootstrap();
};
/**
 * Cloudflare Workers entry (module worker style).
 */
export { default } from './functions/cloudflare.js';
export { default as cloudflareWorker } from './functions/cloudflare.js';
/**
 * Deno fetch handler.
 */
export { default as deno } from './functions/deno.js';
/**
 * AWS Lambda handler.
 */
export { handler } from './functions/lambda.js';
