"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAppModules = createAppModules;
exports.registerRoutes = registerRoutes;
exports.wireHandlers = wireHandlers;
exports.registerBotHandlers = registerBotHandlers;
exports.wireBotHandlers = wireBotHandlers;
const index_js_1 = require("./modules/data-store/index.js");
const encryption_js_1 = require("./modules/data-store/encryption.js");
const index_js_2 = require("./modules/queue-system/index.js");
const persistence_js_1 = require("./modules/queue-system/persistence.js");
const rate_limiter_js_1 = require("./modules/queue-system/rate-limiter.js");
const index_js_3 = require("./modules/character-engine/index.js");
const client_js_1 = require("./modules/openrouter/client.js");
const index_js_4 = require("./modules/conversation-engine/index.js");
const index_js_5 = require("./modules/timer-system/index.js");
const index_js_6 = require("./modules/image-engine/index.js");
const index_js_7 = require("./modules/telegram-manager/index.js");
const index_js_8 = require("./modules/translation/index.js");
const index_js_9 = require("./modules/analytics/index.js");
const index_js_10 = require("./modules/automation/index.js");
const index_js_11 = require("./modules/userbot/index.js");
const config_js_1 = require("./utils/config.js");
const logger_js_1 = require("./utils/logger.js");
const queue_processor_js_1 = require("./queue-processor.js");
const characters_js_1 = __importDefault(require("./routes/characters.js"));
const conversations_js_1 = __importDefault(require("./routes/conversations.js"));
const images_js_1 = __importDefault(require("./routes/images.js"));
const templates_js_1 = __importDefault(require("./routes/templates.js"));
const stars_js_1 = __importDefault(require("./routes/stars.js"));
const telegram_js_1 = __importDefault(require("./routes/telegram.js"));
const analytics_js_1 = __importDefault(require("./routes/analytics.js"));
const system_js_1 = __importDefault(require("./routes/system.js"));
const webhooks_js_1 = __importDefault(require("./routes/webhooks.js"));
const userbot_js_1 = __importDefault(require("./routes/userbot.js"));
const notifications_js_1 = __importDefault(require("./routes/notifications.js"));
const telegram_management_js_1 = __importDefault(require("./routes/telegram-management.js"));
const index_js_12 = require("./modules/notification/index.js");
const log = (0, logger_js_1.createModuleLogger)('wiring');
async function createAppModules() {
    log.info('Initializing application modules');
    // 1. Data layer — no dependencies
    const dataStore = new index_js_1.DataStore();
    await dataStore.init();
    const encryptedStore = new encryption_js_1.EncryptedKeyStore();
    await encryptedStore.init();
    // 2. Queue & rate limiting — use the singleton instance so all modules share the same queue
    const queue = index_js_2.queue;
    const queuePersistence = new persistence_js_1.QueuePersistence();
    await queuePersistence.init();
    // Load persisted queue items
    const persistedItems = await queuePersistence.loadAll();
    if (persistedItems.length > 0) {
        queue.loadItems(persistedItems);
        log.info({ count: persistedItems.length }, 'Loaded persisted queue items');
    }
    // Wire persistence callback
    queue.setOnPersist(async (items) => {
        await queuePersistence.savePending(items);
    });
    const rateLimiter = new rate_limiter_js_1.RateLimiter();
    // 3. OpenRouter client — depends on config
    const openRouterClient = new client_js_1.OpenRouterClient(config_js_1.config.openrouterApiKey);
    // 4. Character engine — uses dataStore (via singleton internally)
    const characterEngine = new index_js_3.CharacterEngine();
    // 5. Conversation engine — uses dataStore, openRouter, queue (via singletons internally)
    const conversationEngine = new index_js_4.ConversationEngine();
    // 6. Timer config
    const timerConfig = { ...index_js_5.DEFAULT_TIMER_CONFIG };
    // 7. Image engine — uses KIE client, templates, queue, dataStore
    const imageEngine = new index_js_6.ImageEngine();
    // 8. Telegram manager — depends on dataStore, encryptedStore
    const telegramManager = new index_js_7.TelegramManager(dataStore, encryptedStore);
    // 9. Translation — depends on dataStore, openRouterClient
    const translationModule = new index_js_8.TranslationModule(dataStore, openRouterClient);
    // 10. Analytics — depends on dataStore
    const analyticsEngine = new index_js_9.AnalyticsEngine(dataStore);
    // 11. Automation — depends on most modules
    const automationManager = new index_js_10.AutomationManager(characterEngine, conversationEngine, imageEngine, telegramManager, queue, timerConfig, analyticsEngine);
    // 12. Userbot manager — MTProto client for user accounts
    const userbotManager = new index_js_11.UserbotManager(dataStore);
    // 13. Notification service — file-based notification storage
    const notificationService = new index_js_12.NotificationService();
    await notificationService.init();
    log.info('All modules initialized');
    return {
        dataStore,
        encryptedStore,
        queue,
        queuePersistence,
        rateLimiter,
        characterEngine,
        openRouterClient,
        conversationEngine,
        timerConfig,
        imageEngine,
        telegramManager,
        translationModule,
        analyticsEngine,
        automationManager,
        userbotManager,
        notificationService,
    };
}
async function registerRoutes(app, modules) {
    log.info('Registering route plugins');
    const { dataStore, characterEngine, conversationEngine, imageEngine, telegramManager, analyticsEngine, queue, translationModule, } = modules;
    // Character management routes
    await app.register(characters_js_1.default, {
        prefix: '/api/v1',
        characterEngine,
        dataStore,
    });
    // Conversation routes
    await app.register(conversations_js_1.default, {
        prefix: '/api/v1',
        dataStore,
        conversationEngine,
    });
    // Image generation routes
    await app.register(images_js_1.default, {
        prefix: '/api/v1',
        imageEngine,
        dataStore,
    });
    // Template management routes
    await app.register(templates_js_1.default, {
        prefix: '/api/v1',
        dataStore,
    });
    // Stars monetization routes
    await app.register(stars_js_1.default, {
        prefix: '/api/v1',
        starsManager: telegramManager.getStarsManager(),
    });
    // Telegram channel management routes
    await app.register(telegram_js_1.default, {
        prefix: '/api/v1',
        channelManager: telegramManager.getChannelManager(),
        telegramManager,
    });
    // Analytics routes
    await app.register(analytics_js_1.default, {
        prefix: '/api/v1',
        analyticsEngine,
    });
    // System routes (queue, backup, translation, bot tokens)
    await app.register(system_js_1.default, {
        prefix: '/api/v1',
        queue,
        translationModule,
        telegramManager,
        dataStore,
        onBotAdded: (characterId, token) => {
            registerBotHandlers(token, characterId, modules);
            modules.automationManager.setAutomationStatus(characterId, 'active');
        },
    });
    // Webhook routes (Telegram + KIE)
    await app.register(webhooks_js_1.default, {
        prefix: '/api/v1',
        webhookHandler: telegramManager.getWebhookHandler(),
    });
    // Userbot routes
    await app.register(userbot_js_1.default, {
        prefix: '/api/v1',
        userbotManager: modules.userbotManager,
        conversationEngine: modules.conversationEngine,
    });
    // Notification routes
    await app.register(notifications_js_1.default, {
        prefix: '/api/v1',
        notificationService: modules.notificationService,
    });
    // Telegram management routes (entity CRUD + GramJS stubs)
    await app.register(telegram_management_js_1.default, {
        prefix: '/api/v1',
        userbotManager: modules.userbotManager,
        dataStore: modules.dataStore,
    });
    log.info('All route plugins registered');
}
function wireHandlers(modules) {
    const { queue, telegramManager, imageEngine } = modules;
    const webhookHandler = telegramManager.getWebhookHandler();
    // 1. Register queue processor
    const processor = (0, queue_processor_js_1.createQueueProcessor)(modules);
    queue.setProcessor(processor);
    log.info('Queue processor registered');
    // 2. Register KIE webhook handler
    webhookHandler.onKIEComplete(async (response) => {
        const { taskId, status, resultUrl, error } = response;
        if (status === 'completed') {
            if (resultUrl) {
                try {
                    await imageEngine.handleWebhookResult(taskId, resultUrl);
                    // Queue quality check after successful download
                    const queueItem = queue.getById(taskId);
                    if (queueItem) {
                        await queue.add('quality_check', queueItem.characterId, {
                            imageUrl: resultUrl,
                            characterId: queueItem.characterId,
                            imageId: taskId,
                            taskId,
                        });
                        log.info({ taskId }, 'Quality check queued after image download');
                    }
                }
                catch (err) {
                    log.error({ taskId, err: err.message }, 'Failed to process KIE webhook result');
                    await imageEngine.handleFailure(taskId, err.message);
                }
            }
            else {
                log.error({ taskId }, 'KIE webhook completed but resultUrl is missing');
                await imageEngine.handleFailure(taskId, 'Completed but resultUrl missing');
            }
        }
        else if (status === 'failed') {
            log.warn({ taskId, error }, 'KIE task failed');
            await imageEngine.handleFailure(taskId, error || 'KIE task failed');
        }
    });
    log.info('KIE webhook handler registered');
}
function registerBotHandlers(botToken, characterId, modules) {
    const { telegramManager, automationManager } = modules;
    const webhookHandler = telegramManager.getWebhookHandler();
    // Message handler
    webhookHandler.onMessage(botToken, async (token, message) => {
        try {
            const charId = telegramManager.getCharacterIdByToken(token);
            if (!charId) {
                log.warn({ token: token.slice(-4) }, 'Could not resolve character ID from token');
                return;
            }
            const userId = message.from?.id ?? message.chat.id;
            const text = message.text ?? '';
            if (!text)
                return;
            await automationManager.handleIncomingMessage(charId, userId, text);
            // Fire-and-forget notification for new message
            try {
                const userName = message.from?.first_name || message.from?.username || 'Kullanıcı';
                const character = await modules.dataStore.getCharacter(charId);
                const characterName = character?.identity?.name || charId;
                await modules.notificationService.create({
                    type: 'new_message',
                    title: 'Yeni mesaj',
                    body: `${characterName} karakterine ${userName} mesaj gönderdi`,
                    characterId: charId,
                    telegramUserId: userId,
                    link: `/characters/${charId}/conversations/${userId}`,
                });
            }
            catch (notifErr) {
                log.warn({ characterId: charId, err: notifErr.message }, 'Failed to create message notification');
            }
        }
        catch (err) {
            log.error({ characterId, err: err.message }, 'Error handling incoming message');
        }
    });
    // Pre-checkout query handler
    webhookHandler.onPreCheckoutQuery(botToken, async (token, query) => {
        try {
            const charId = telegramManager.getCharacterIdByToken(token);
            if (!charId) {
                log.warn({ token: token.slice(-4) }, 'Could not resolve character ID for pre-checkout');
                const botClient = telegramManager.getBotClient(characterId);
                if (botClient) {
                    await botClient.answerPreCheckoutQuery(query.id, false, 'Internal error');
                }
                return;
            }
            const botClient = telegramManager.getBotClient(charId);
            if (!botClient) {
                log.warn({ characterId: charId }, 'No bot client for pre-checkout');
                return;
            }
            await botClient.answerPreCheckoutQuery(query.id, true);
        }
        catch (err) {
            log.error({ characterId, err: err.message }, 'Error handling pre-checkout query');
        }
    });
    // Successful payment handler
    webhookHandler.onSuccessfulPayment(botToken, async (token, payment, message) => {
        try {
            const charId = telegramManager.getCharacterIdByToken(token);
            if (!charId) {
                log.warn({ token: token.slice(-4) }, 'Could not resolve character ID for payment');
                return;
            }
            const userId = message.from?.id ?? message.chat.id;
            await automationManager.handleStarsPayment(charId, userId, payment);
            // Fire-and-forget notification for Stars purchase
            try {
                const starCount = payment.total_amount ?? 0;
                const userName = message.from?.first_name || message.from?.username || 'Kullanıcı';
                const character = await modules.dataStore.getCharacter(charId);
                const characterName = character?.identity?.name || charId;
                await modules.notificationService.create({
                    type: 'stars_purchase',
                    title: 'Stars satın alımı',
                    body: `${userName}, ${characterName} için ${starCount} Stars harcadı`,
                    characterId: charId,
                    link: `/characters/${charId}`,
                });
            }
            catch (notifErr) {
                log.warn({ characterId: charId, err: notifErr.message }, 'Failed to create payment notification');
            }
        }
        catch (err) {
            log.error({ characterId, err: err.message }, 'Error handling successful payment');
        }
    });
    log.info({ characterId }, 'Bot handlers registered');
}
async function wireBotHandlers(modules) {
    const { telegramManager, encryptedStore } = modules;
    const activeBots = telegramManager.getActiveBots();
    for (const [characterId] of activeBots) {
        try {
            const token = await encryptedStore.getKey(`bot-token:${characterId}`);
            if (!token) {
                log.warn({ characterId }, 'No token found for active bot, skipping handler registration');
                continue;
            }
            registerBotHandlers(token, characterId, modules);
            modules.automationManager.setAutomationStatus(characterId, 'active');
        }
        catch (err) {
            log.error({ characterId, err: err.message }, 'Failed to register bot handlers');
        }
    }
    log.info({ botCount: activeBots.size }, 'All bot handlers wired');
}
//# sourceMappingURL=wiring.js.map