import { system } from '@/lib/system/SystemController';

interface BatchConfig {
    batchSize: number; // How many items to grab at once (e.g. 100)
    concurrency: number; // How many to process in parallel (e.g. 5)
    delayMs: number; // Throttle speed (e.g. wait 100ms between items)
}

export class BatchProcessor {
    constructor(private config: BatchConfig) { }

    async processQueue(
        items: any[],
        workerFunction: (item: any) => Promise<any>
    ) {
        const results = [];
        // Process in Chunks (Batch Size)
        for (let i = 0; i < items.length; i += this.config.batchSize) {
            const chunk = items.slice(i, i + this.config.batchSize);
            console.log(`Processing Batch ${(i / this.config.batchSize) + 1}...`);

            // Check System State (Standby Mode)
            if (!system.isActive()) {
                console.log('[God Mode] System in STANDBY. Pausing Batch Processor...');
                // Wait until active again (check every 2s)
                while (!system.isActive()) {
                    await new Promise(r => setTimeout(r, 2000));
                }
                console.log('[God Mode] System RESUMED.');
            }

            // Within each chunk, limit concurrency

            // Within each chunk, limit concurrency
            const chunkResults = await this.runWithConcurrency(chunk, workerFunction);
            results.push(...chunkResults);

            // Optional: Cool down between batches
            if (this.config.delayMs > 0) {
                await new Promise(r => setTimeout(r, this.config.delayMs));
            }
        }
        return results;
    }

    private async runWithConcurrency(items: any[], fn: (item: any) => Promise<any>) {
        const results: any[] = [];
        const executing: Promise<any>[] = [];

        for (const item of items) {
            const p = Promise.resolve().then(() => fn(item));
            results.push(p);

            if (this.config.concurrency <= items.length) {
                const e: Promise<any> = p.then(() => executing.splice(executing.indexOf(e), 1));
                executing.push(e);

                if (executing.length >= this.config.concurrency) {
                    await Promise.race(executing);
                }
            }
        }
        return Promise.all(results);
    }
}
