"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChannelManager = void 0;
const cron = __importStar(require("node-cron"));
const index_js_1 = require("../../utils/index.js");
const log = (0, index_js_1.createModuleLogger)('channel-manager');
class ChannelManager {
    store;
    getBotClient;
    configs = new Map();
    cronJobs = new Map();
    constructor(store, getBotClient) {
        this.store = store;
        this.getBotClient = getBotClient;
    }
    async createChannels(characterId, botClient, normalTitle, vipTitle) {
        log.info({ characterId }, 'Creating normal and VIP channels');
        const normalResult = await botClient.createChannel(normalTitle, 'Public promotional content');
        const vipResult = await botClient.createChannel(vipTitle, 'VIP exclusive content — Stars access');
        const now = new Date().toISOString();
        const config = {
            characterId,
            normalChannel: {
                chatId: normalResult.chatId,
                title: normalTitle,
                inviteLink: normalResult.inviteLink,
                memberCount: 0,
            },
            vipChannel: {
                chatId: vipResult.chatId,
                title: vipTitle,
                inviteLink: vipResult.inviteLink,
                memberCount: 0,
                starPrice: 50,
            },
            createdAt: now,
            updatedAt: now,
        };
        this.configs.set(characterId, config);
        await this.saveConfig(characterId, config);
        log.info({ characterId, normalChatId: normalResult.chatId, vipChatId: vipResult.chatId }, 'Channels created');
        return config;
    }
    async getChannelConfig(characterId) {
        const cached = this.configs.get(characterId);
        if (cached)
            return cached;
        const stored = await this.loadConfig(characterId);
        if (stored) {
            this.configs.set(characterId, stored);
        }
        return stored;
    }
    async updateChannelConfig(characterId, updates) {
        const existing = await this.getChannelConfig(characterId);
        if (!existing) {
            throw new Error(`Channel config not found for character ${characterId}`);
        }
        const updated = {
            ...existing,
            ...updates,
            characterId: existing.characterId,
            createdAt: existing.createdAt,
            updatedAt: new Date().toISOString(),
        };
        if (updates.normalChannel) {
            updated.normalChannel = { ...existing.normalChannel, ...updates.normalChannel };
        }
        if (updates.vipChannel) {
            updated.vipChannel = { ...existing.vipChannel, ...updates.vipChannel };
        }
        this.configs.set(characterId, updated);
        await this.saveConfig(characterId, updated);
        // Reschedule cron if publishSchedule changed
        if (updates.publishSchedule !== undefined) {
            this.stopSchedule(characterId);
            if (updates.publishSchedule) {
                this.startSchedule(characterId, updates.publishSchedule);
            }
        }
        log.info({ characterId }, 'Channel config updated');
        return updated;
    }
    async publishToNormal(characterId, content) {
        const config = await this.getChannelConfig(characterId);
        if (!config?.normalChannel) {
            throw new Error(`Normal channel not configured for character ${characterId}`);
        }
        const botClient = this.getBotClient(characterId);
        if (!botClient) {
            throw new Error(`Bot client not available for character ${characterId}`);
        }
        const chatId = config.normalChannel.chatId;
        if (content.photoUrl) {
            await botClient.sendPhoto(chatId, content.photoUrl, content.caption);
        }
        else if (content.text) {
            await botClient.sendMessage(chatId, content.text);
        }
        log.info({ characterId, chatId }, 'Published to normal channel');
    }
    async publishToVIP(characterId, imageUrl, starCount, caption) {
        const config = await this.getChannelConfig(characterId);
        if (!config?.vipChannel) {
            throw new Error(`VIP channel not configured for character ${characterId}`);
        }
        const botClient = this.getBotClient(characterId);
        if (!botClient) {
            throw new Error(`Bot client not available for character ${characterId}`);
        }
        const effectiveStarCount = starCount || config.vipChannel.starPrice;
        await botClient.sendPaidMedia({
            chat_id: config.vipChannel.chatId,
            star_count: effectiveStarCount,
            media: [{ type: 'photo', media: imageUrl }],
            caption,
        });
        log.info({ characterId, chatId: config.vipChannel.chatId, starCount: effectiveStarCount }, 'Published paid media to VIP channel');
    }
    async getStats(characterId) {
        const config = await this.getChannelConfig(characterId);
        if (!config)
            return null;
        const botClient = this.getBotClient(characterId);
        if (!botClient)
            return null;
        let normalMembers = config.normalChannel?.memberCount ?? 0;
        let vipMembers = config.vipChannel?.memberCount ?? 0;
        try {
            if (config.normalChannel) {
                normalMembers = await botClient.getChatMemberCount(config.normalChannel.chatId);
                config.normalChannel.memberCount = normalMembers;
            }
            if (config.vipChannel) {
                vipMembers = await botClient.getChatMemberCount(config.vipChannel.chatId);
                config.vipChannel.memberCount = vipMembers;
            }
            config.updatedAt = new Date().toISOString();
            this.configs.set(characterId, config);
            await this.saveConfig(characterId, config);
        }
        catch (err) {
            log.warn({ characterId, err }, 'Failed to refresh member counts from Telegram');
        }
        return { normalMembers, vipMembers };
    }
    // --- Scheduling ---
    startSchedule(characterId, cronExpression) {
        if (!cron.validate(cronExpression)) {
            throw new Error(`Invalid cron expression: ${cronExpression}`);
        }
        this.stopSchedule(characterId);
        const task = cron.schedule(cronExpression, () => {
            log.info({ characterId, cronExpression }, 'Scheduled publish triggered');
            // The actual publish logic is delegated to the automation layer
            // This emits a log entry; the orchestrator listens and calls publishToNormal/VIP
        });
        this.cronJobs.set(characterId, task);
        log.info({ characterId, cronExpression }, 'Publish schedule started');
    }
    stopSchedule(characterId) {
        const existing = this.cronJobs.get(characterId);
        if (existing) {
            existing.stop();
            this.cronJobs.delete(characterId);
            log.info({ characterId }, 'Publish schedule stopped');
        }
    }
    stopAllSchedules() {
        for (const [characterId, task] of this.cronJobs) {
            task.stop();
            log.info({ characterId }, 'Publish schedule stopped');
        }
        this.cronJobs.clear();
    }
    // --- Persistence helpers ---
    async saveConfig(characterId, config) {
        await this.store.saveCharacterChannelConfig(characterId, config);
    }
    async loadConfig(characterId) {
        return this.store.getCharacterChannelConfig(characterId);
    }
}
exports.ChannelManager = ChannelManager;
//# sourceMappingURL=channel-manager.js.map