import { Logger } from '../config/logger.js';
import { clearMiddlewareConfigCache } from '../config/middleware.js';
import { CloudflareAdapter } from '../runtime/adapters/CloudflareAdapter.js';
import mergeOverrideValues from '../runtime/OverrideValueMerge.js';
import { ProjectRuntime } from '../runtime/ProjectRuntime.js';
import { StartupConfigFile, StartupConfigFileRegistry, } from '../runtime/StartupConfigFileRegistry.js';
import { WorkerAdapterImports } from '../runtime/WorkerAdapterImports.js';
import { getKernel } from '../runtime/getKernel.js';
const startupConfigModules = Object.freeze([
    {
        file: StartupConfigFile.Broadcast,
        serviceModuleId: '@service-runtime-config/' + 'broadcast.ts',
    },
    {
        file: StartupConfigFile.Cache,
        serviceModuleId: '@service-runtime-config/' + 'cache.ts',
    },
    {
        file: StartupConfigFile.Database,
        serviceModuleId: '@service-runtime-config/' + 'database.ts',
    },
    {
        file: StartupConfigFile.Mail,
        serviceModuleId: '@service-runtime-config/' + 'mail.ts',
    },
    {
        file: StartupConfigFile.Middleware,
        serviceModuleId: '@service-runtime-config/' + 'middleware.ts',
    },
    {
        file: StartupConfigFile.Notification,
        serviceModuleId: '@service-runtime-config/' + 'notification.ts',
    },
    {
        file: StartupConfigFile.Queue,
        serviceModuleId: '@service-runtime-config/' + 'queue.ts',
    },
    {
        file: StartupConfigFile.Storage,
        serviceModuleId: '@service-runtime-config/' + 'storage.ts',
    },
    {
        file: StartupConfigFile.Workers,
        serviceModuleId: '@service-runtime-config/' + 'workers.ts',
    },
]);
const importRootBroadcastModule = async () => {
    return (await import('@runtime-config/' + 'broadcast.ts').catch(() => ({})));
};
const importRootCacheModule = async () => {
    return (await import('@runtime-config/' + 'cache.ts').catch(() => ({})));
};
const importRootDatabaseModule = async () => {
    return (await import('@runtime-config/' + 'database.ts').catch(() => ({})));
};
const importRootMailModule = async () => {
    return (await import('@runtime-config/' + 'mail.ts').catch(() => ({})));
};
const importRootMiddlewareModule = async () => {
    return (await import('@runtime-config/' + 'middleware.ts').catch(() => ({})));
};
const importRootNotificationModule = async () => {
    return (await import('@runtime-config/' + 'notification.ts').catch(() => ({})));
};
const importRootQueueModule = async () => {
    return (await import('@runtime-config/' + 'queue.ts').catch(() => ({})));
};
const importRootStorageModule = async () => {
    return (await import('@runtime-config/' + 'storage.ts').catch(() => ({})));
};
const importRootWorkersModule = async () => {
    return (await import('@runtime-config/' + 'workers.ts').catch(() => ({})));
};
const rootStartupImporters = Object.freeze({
    [StartupConfigFile.Broadcast]: importRootBroadcastModule,
    [StartupConfigFile.Cache]: importRootCacheModule,
    [StartupConfigFile.Database]: importRootDatabaseModule,
    [StartupConfigFile.Mail]: importRootMailModule,
    [StartupConfigFile.Middleware]: importRootMiddlewareModule,
    [StartupConfigFile.Notification]: importRootNotificationModule,
    [StartupConfigFile.Queue]: importRootQueueModule,
    [StartupConfigFile.Storage]: importRootStorageModule,
    [StartupConfigFile.Workers]: importRootWorkersModule,
});
const importOptionalDefault = async (importer) => {
    try {
        const module = await importer();
        return module.default;
    }
    catch {
        return undefined;
    }
};
const importOptionalDefaultById = async (moduleId) => {
    try {
        const module = (await import(moduleId));
        return module.default;
    }
    catch {
        return undefined;
    }
};
const resolveStartupOverrideValue = async (entry) => {
    const rootOverride = await importOptionalDefault(rootStartupImporters[entry.file]);
    const serviceOverride = ProjectRuntime.getActiveService() === undefined
        ? undefined
        : await importOptionalDefaultById(entry.serviceModuleId);
    if (rootOverride === undefined)
        return serviceOverride;
    if (serviceOverride === undefined)
        return rootOverride;
    return mergeOverrideValues(rootOverride, serviceOverride);
};
const applyStartupConfigOverrides = async () => {
    try {
        const globalAny = globalThis;
        globalAny.__zintrustStartupConfigOverrides ??= new Map();
        const resolvedEntries = await Promise.all(startupConfigModules.map(async (entry) => ({
            file: entry.file,
            value: await resolveStartupOverrideValue(entry),
        })));
        for (const entry of resolvedEntries) {
            if (entry.value === undefined) {
                globalAny.__zintrustStartupConfigOverrides.delete(entry.file);
                continue;
            }
            globalAny.__zintrustStartupConfigOverrides.set(entry.file, entry.value);
        }
        StartupConfigFileRegistry.clear();
        clearMiddlewareConfigCache();
        await StartupConfigFileRegistry.preload(startupConfigModules.map((entry) => entry.file));
    }
    catch (error) {
        Logger.error('Error applying startup config overrides:', error);
        // Best-effort: log and swallow errors since this is an optional.
    }
};
const injectIoredisModule = async () => {
    const globalAny = globalThis;
    if (globalAny.__zintrustIoredisModule !== undefined)
        return;
    try {
        const module = await import('ioredis');
        globalAny.__zintrustIoredisModule = module;
    }
    catch {
        // Best-effort: leave undefined so resolveIORedis can surface a config error.
    }
};
let startupConfigOverridesPromise;
const WORKER_ENV_SNAPSHOT_KEY = 'ZINTRUST_WORKER_ENV_SNAPSHOT';
const resolveWorkersEnv = (env) => {
    const bindings = typeof env === 'object' && env !== null ? { ...env } : {};
    const rawSnapshot = bindings[WORKER_ENV_SNAPSHOT_KEY];
    if (typeof rawSnapshot !== 'string' || rawSnapshot.trim() === '') {
        return bindings;
    }
    try {
        const parsed = JSON.parse(rawSnapshot);
        Reflect.deleteProperty(bindings, WORKER_ENV_SNAPSHOT_KEY);
        return {
            ...parsed,
            ...bindings,
        };
    }
    catch {
        return bindings;
    }
};
const ensureStartupConfigOverridesLoaded = async () => {
    startupConfigOverridesPromise ??= applyStartupConfigOverrides();
    await startupConfigOverridesPromise;
};
export default {
    async fetch(request, _env, _ctx) {
        try {
            const workersEnv = resolveWorkersEnv(_env);
            // Make bindings available to framework code in Workers
            globalThis.env = workersEnv;
            const AppRoutes = (await import('@routes/' + 'api.ts'));
            if (AppRoutes !== undefined) {
                globalThis.__zintrustRoutes = AppRoutes;
            }
            await ProjectRuntime.tryLoadWorkerRuntime();
            await ensureStartupConfigOverridesLoaded();
            await WorkerAdapterImports.ready; // NOSONAR - Ensure adapter imports are ready before handling requests.
            await injectIoredisModule();
            const kernel = await getKernel();
            const adapter = CloudflareAdapter.create({
                handler: async (req, res) => {
                    await kernel.handle(req, res);
                },
            });
            const platformResponse = await adapter.handle(request);
            return adapter.formatResponse(platformResponse);
        }
        catch (error) {
            const err = error;
            Logger.error('Cloudflare handler error:', err);
            if (typeof err?.stack === 'string' && err.stack.trim() !== '') {
                Logger.error('Cloudflare handler stack:', err.stack);
            }
            return new Response('Internal Server Error', { status: 500 });
        }
    },
};
