import { ATPCompiler, createDefaultCompiler, initializeRuntime as initializeCompilerRuntime, resumableForOf, resumableWhile, resumableForLoop, resumableMap, resumableForEach, resumableFilter, resumableReduce, resumableFind, resumableSome, resumableEvery, resumableFlatMap, resumablePromiseAll, resumablePromiseAllSettled, batchParallel, } from '@mondaydotcomorg/atp-compiler';
import { ATP_COMPILER_ENABLED, ATP_BATCH_SIZE_THRESHOLD } from './constants.js';
/**
 * Adapter for ATPCompiler to match ICompiler interface
 */
class ATPCompilerAdapter {
    compiler;
    constructor(config) {
        this.compiler = new ATPCompiler(config);
    }
    detect(code) {
        return this.compiler.detect(code);
    }
    transform(code) {
        return this.compiler.transform(code);
    }
    getType() {
        return 'ATPCompiler';
    }
    getCacheStats() {
        return null;
    }
}
/**
 * Adapter for PluggableCompiler to match ICompiler interface
 */
class PluggableCompilerAdapter {
    compiler;
    constructor(config) {
        this.compiler = createDefaultCompiler(config);
    }
    async detect(code) {
        return await this.compiler.detect(code);
    }
    async transform(code) {
        return await this.compiler.transform(code);
    }
    getType() {
        return 'PluggableCompiler';
    }
    getCacheStats() {
        return this.compiler.getCacheStats();
    }
}
/**
 * Compiler factory - creates the appropriate compiler based on configuration
 * This is where you can easily add new compiler types
 */
class CompilerFactory {
    static create(config) {
        const compilerType = process.env.ATP_USE_PLUGGABLE_COMPILER === 'true' ? 'pluggable' : 'atp';
        switch (compilerType) {
            case 'pluggable':
                return new PluggableCompilerAdapter(config);
            case 'atp':
            default:
                return new ATPCompilerAdapter(config);
        }
    }
    /**
     * Allow custom compiler injection for testing or custom implementations
     */
    static createCustom(compiler) {
        return compiler;
    }
}
/**
 * Unified compiler wrapper - works with any ICompiler implementation
 * This abstracts sync/async differences and provides a consistent API
 */
class CompilerWrapper {
    compiler;
    constructor(compiler) {
        this.compiler = compiler;
    }
    async detect(code) {
        const result = this.compiler.detect(code);
        return result instanceof Promise ? await result : result;
    }
    async transform(code) {
        const result = this.compiler.transform(code);
        return result instanceof Promise ? await result : result;
    }
    getType() {
        return this.compiler.getType();
    }
    getCacheStats() {
        return this.compiler.getCacheStats?.() ?? null;
    }
}
const transformCache = new Map();
function getCodeHash(code) {
    let hash = 0;
    for (let i = 0; i < code.length; i++) {
        const char = code.charCodeAt(i);
        hash = (hash << 5) - hash + char;
        hash = hash & hash;
    }
    return hash.toString(36);
}
export function getCompilerRuntime() {
    return {
        resumableForOf,
        resumableWhile,
        resumableForLoop,
        resumableMap,
        resumableForEach,
        resumableFilter,
        resumableReduce,
        resumableFind,
        resumableSome,
        resumableEvery,
        resumableFlatMap,
        resumablePromiseAll,
        resumablePromiseAllSettled,
        batchParallel,
    };
}
export async function transformCodeWithCompiler(code, executionId, cacheProvider, executionLogger, injectedCompiler) {
    if (!ATP_COMPILER_ENABLED) {
        return { code, useCompiler: false };
    }
    try {
        // Use injected compiler or create default via factory
        const compilerImpl = injectedCompiler ??
            CompilerFactory.create({
                enableBatchParallel: true,
                batchSizeThreshold: ATP_BATCH_SIZE_THRESHOLD,
            });
        const compiler = new CompilerWrapper(compilerImpl);
        executionLogger.debug('Using ATP compiler', {
            type: compiler.getType(),
            batchSizeThreshold: ATP_BATCH_SIZE_THRESHOLD,
        });
        // Detect patterns (abstracted sync/async handling)
        const detection = await compiler.detect(code);
        executionLogger.info('ATP Compiler detection result', {
            needsTransform: detection.needsTransform,
            patterns: detection.patterns,
            batchable: detection.batchableParallel,
        });
        if (detection.needsTransform) {
            const codeHash = getCodeHash(code);
            const cached = transformCache.get(codeHash);
            if (cached) {
                executionLogger.debug('Using cached transformed code', { codeHash });
                initializeCompilerRuntime({
                    executionId,
                    cache: cacheProvider,
                });
                return {
                    code: cached,
                    useCompiler: true,
                    metadata: {
                        patterns: detection.patterns,
                        batchable: detection.batchableParallel,
                    },
                };
            }
            initializeCompilerRuntime({
                executionId,
                cache: cacheProvider,
            });
            // Transform code (abstracted sync/async handling)
            const transformed = await compiler.transform(code);
            transformCache.set(codeHash, transformed.code);
            // Log transformation results with optional cache stats
            const logData = {
                patterns: detection.patterns,
                batchable: detection.batchableParallel,
                loopCount: transformed.metadata.loopCount,
                arrayMethodCount: transformed.metadata.arrayMethodCount,
                parallelCallCount: transformed.metadata.parallelCallCount,
                batchSizeThreshold: ATP_BATCH_SIZE_THRESHOLD,
            };
            // Add cache stats if available
            const cacheStats = compiler.getCacheStats();
            if (cacheStats) {
                logData.astCacheSize = cacheStats.size;
                logData.astCacheEnabled = cacheStats.enabled;
            }
            executionLogger.info('Code transformed by ATP compiler', logData);
            return {
                code: transformed.code,
                useCompiler: true,
                metadata: {
                    patterns: detection.patterns,
                    batchable: detection.batchableParallel,
                    loopCount: transformed.metadata.loopCount,
                    arrayMethodCount: transformed.metadata.arrayMethodCount,
                    parallelCallCount: transformed.metadata.parallelCallCount,
                },
            };
        }
    }
    catch (error) {
        executionLogger.error('ATP compiler transformation failed, falling back', {
            error: error instanceof Error ? error.message : String(error),
            stack: error instanceof Error ? error.stack : undefined,
        });
    }
    return { code, useCompiler: false };
}
//# sourceMappingURL=compiler-config.js.map