"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createQueueProcessor = createQueueProcessor;
const logger_js_1 = require("./utils/logger.js");
const quality_control_js_1 = require("./modules/image-engine/quality-control.js");
const image_provider_js_1 = require("./modules/image-engine/image-provider.js");
const index_js_1 = require("./modules/data-store/index.js");
const prompt_safety_js_1 = require("./modules/image-engine/prompt-safety.js");
const log = (0, logger_js_1.createModuleLogger)('queue-processor');
function createQueueProcessor(modules) {
    const { telegramManager, imageEngine, translationModule, queue, rateLimiter } = modules;
    /** Acquire rate-limit slot, waiting if necessary. */
    async function waitForRateLimit(service, chatId) {
        let result = await rateLimiter.acquire(service, chatId);
        while (!result.allowed) {
            log.info({ service, waitMs: result.waitMs }, 'Rate limit active, waiting...');
            await new Promise(r => setTimeout(r, result.waitMs));
            result = await rateLimiter.acquire(service, chatId);
        }
    }
    return async (item) => {
        log.info({ taskId: item.id, type: item.type, characterId: item.characterId }, 'Processing queue item');
        switch (item.type) {
            case 'chat_response': {
                const { userId, text } = item.payload;
                const botClient = telegramManager.getBotClient(item.characterId);
                if (!botClient) {
                    throw new Error(`No bot client found for character ${item.characterId}`);
                }
                await waitForRateLimit('telegramBotApi', String(userId));
                await botClient.sendMessage(userId, text);
                log.info({ taskId: item.id, characterId: item.characterId, userId }, 'Chat response sent');
                break;
            }
            case 'image_generation': {
                const payload = item.payload;
                const imgProvider = (0, image_provider_js_1.getImageProvider)();
                const model = payload.model || 'nano-banana-2';
                // Policy-safe prompt sanitization
                const safetyResult = (0, prompt_safety_js_1.sanitizePrompt)(payload.prompt);
                if (safetyResult.wasModified) {
                    log.info({ changes: safetyResult.changes }, 'Prompt sanitized for Google policy compliance');
                }
                if (safetyResult.warnings.length > 0) {
                    log.warn({ warnings: safetyResult.warnings }, 'Prompt has risky word combinations — may still trigger policy');
                }
                const request = {
                    prompt: safetyResult.sanitizedPrompt,
                    model,
                    aspectRatio: payload.aspectRatio || '1:1',
                    webhookUrl: payload.webhookUrl,
                    safetyTolerance: 6,
                    enableTranslation: true,
                };
                // Attach reference images for character consistency (skip for reference image generation itself)
                if (!payload.isReferenceImage) {
                    try {
                        const refUrls = await index_js_1.dataStore.getReferenceImageUrls(item.characterId);
                        if (refUrls) {
                            const urls = Object.values(refUrls).filter(Boolean);
                            if (urls.length > 0) {
                                request.imageInput = urls;
                                log.info({ characterId: item.characterId, refCount: urls.length }, 'Attaching reference images for consistency');
                            }
                        }
                    }
                    catch (err) {
                        log.warn({ characterId: item.characterId, err: err.message }, 'Failed to load reference image URLs, proceeding without');
                    }
                }
                // Generate image via unified provider (Gemini primary, KIE fallback)
                log.info({ taskId: item.id, characterId: item.characterId, provider: imgProvider.getPrimaryProvider() }, 'Generating image');
                const genResult = await imgProvider.generateAndWait(request);
                log.info({ taskId: item.id, provider: genResult.provider, imageUrl: genResult.imageUrl.slice(0, 80) }, 'Image generation completed');
                // Download and save the image
                const { fetch: fetchFn } = await import('undici');
                const { writeFile: writeFileFn } = await import('fs/promises');
                const { ensureDir: ensureDirFn } = await import('./modules/data-store/file-ops.js');
                const imgResponse = await fetchFn(genResult.imageUrl);
                if (imgResponse.ok) {
                    const buffer = Buffer.from(await imgResponse.arrayBuffer());
                    if (payload.outputPath) {
                        const { dirname } = await import('path');
                        await ensureDirFn(dirname(payload.outputPath));
                        await writeFileFn(payload.outputPath, buffer);
                    }
                    else {
                        const imagesDir = index_js_1.dataStore.getGeneratedImagesDir(item.characterId);
                        await ensureDirFn(imagesDir);
                        const { resolve: resolvePath } = await import('path');
                        const savePath = resolvePath(imagesDir, `photo_${Date.now()}.jpg`);
                        await writeFileFn(savePath, buffer);
                    }
                    // Save reference image URL for character consistency (like KIE poller did)
                    if (payload.isReferenceImage && payload.outputPath) {
                        const filename = payload.outputPath.split('/').pop();
                        if (filename) {
                            await index_js_1.dataStore.addReferenceImageUrl(item.characterId, filename, genResult.imageUrl);
                            log.info({ characterId: item.characterId, filename }, 'Reference image URL saved for consistency');
                        }
                    }
                }
                else {
                    throw new Error(`Failed to download generated image: ${imgResponse.status}`);
                }
                await queue.updateStatus(item.id, 'completed');
                break;
            }
            case 'quality_check': {
                const { imageUrl, characterId, imageId, taskId } = item.payload;
                const qc = (0, quality_control_js_1.getQualityController)();
                await waitForRateLimit('openrouter');
                const report = await qc.checkQuality(imageUrl, characterId, imageId, taskId);
                if (report.passed) {
                    log.info({ imageId, score: report.totalScore }, 'Image passed quality check');
                }
                else {
                    log.warn({ imageId, score: report.totalScore }, 'Image failed quality check, triggering retry');
                    await imageEngine.handleFailure(taskId, `Quality check failed: score ${report.totalScore}`);
                }
                break;
            }
            case 'stars_payment': {
                const { characterId, userId, payment } = item.payload;
                const botClient = telegramManager.getBotClient(characterId);
                if (!botClient) {
                    throw new Error(`No bot client found for character ${characterId}`);
                }
                const starsManager = telegramManager.getStarsManager();
                await starsManager.handleSuccessfulPayment(characterId, payment, userId, botClient);
                log.info({ taskId: item.id, characterId, userId }, 'Stars payment processed');
                break;
            }
            case 'channel_publish': {
                const { characterId, channelType, imageId, caption } = item.payload;
                const channelManager = telegramManager.getChannelManager();
                if (channelType === 'vip' && imageId) {
                    const channelConfig = await channelManager.getChannelConfig(characterId);
                    const starPrice = channelConfig?.vipChannel?.starPrice ?? 50;
                    await channelManager.publishToVIP(characterId, imageId, starPrice, caption);
                }
                else {
                    await channelManager.publishToNormal(characterId, {
                        text: caption,
                        photoUrl: imageId,
                        caption,
                    });
                }
                log.info({ taskId: item.id, characterId, channelType }, 'Channel content published');
                break;
            }
            case 'translation': {
                const { text } = item.payload;
                await waitForRateLimit('openrouter');
                const result = await translationModule.translatePrompt(text);
                log.info({ taskId: item.id, original: text, translated: result.translated }, 'Translation completed');
                break;
            }
            default:
                throw new Error(`Bilinmeyen görev tipi: ${item.type}`);
        }
    };
}
//# sourceMappingURL=queue-processor.js.map