"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateDeckCommandHandler = void 0;
const DeckAggregate_1 = require("../../../Domain/Deck/DeckAggregate");
const UserAggregate_1 = require("../../../Domain/User/UserAggregate");
const DeckMapper_1 = require("../../DTOs/Mappers/DeckMapper");
const AdminBypassService_1 = require("../../Services/AdminBypassService");
const Logger_1 = require("../../Services/Logger");
class CreateDeckCommandHandler {
    constructor(deckRepo, userRepo, orgRepo) {
        this.deckRepo = deckRepo;
        this.userRepo = userRepo;
        this.orgRepo = orgRepo;
    }
    async execute(cmd) {
        try {
            // 1. Get user details
            const user = await this.userRepo.findById(cmd.userid);
            if (!user) {
                throw new Error('User not found');
            }
            // 2. ADMIN BYPASS - Skip all restrictions
            if (AdminBypassService_1.AdminBypassService.shouldBypassRestrictions(user.state)) {
                AdminBypassService_1.AdminBypassService.logAdminBypass('CREATE_DECK_BYPASS', user.id, 'new-deck', {
                    deckName: cmd.name,
                    deckType: cmd.type,
                    cardCount: cmd.cards.length,
                    ctype: cmd.ctype
                });
                return this.createDeck(cmd);
            }
            // 3. Check deck count limits for regular users
            const userDeckCount = await this.deckRepo.countActiveByUserId(cmd.userid);
            const maxDecks = user.state === UserAggregate_1.UserState.VERIFIED_PREMIUM ? 12 : 8;
            if (userDeckCount >= maxDecks) {
                throw new Error(`Deck limit exceeded. Maximum ${maxDecks} decks allowed for your account type.`);
            }
            // 4. Organizational deck restrictions
            if (cmd.ctype === DeckAggregate_1.CType.ORGANIZATION) {
                // Only premium users can create organizational decks
                if (user.state !== UserAggregate_1.UserState.VERIFIED_PREMIUM) {
                    throw new Error('Only premium users can create organizational decks.');
                }
                // User must belong to an organization
                if (!user.orgid) {
                    throw new Error('You must be a member of an organization to create organizational decks.');
                }
                // Check organization limits
                const org = await this.orgRepo.findById(user.orgid);
                if (!org) {
                    throw new Error('Organization not found.');
                }
                if (org.maxOrganizationalDecks === null) {
                    throw new Error('Organization deck limit not configured. Contact administrator.');
                }
                const userOrgDeckCount = await this.deckRepo.countOrganizationalByUserId(cmd.userid);
                if (userOrgDeckCount >= org.maxOrganizationalDecks) {
                    throw new Error(`Organization deck limit exceeded. Maximum ${org.maxOrganizationalDecks} organizational decks allowed.`);
                }
            }
            // 5. Create deck with restrictions passed
            return this.createDeck(cmd);
        }
        catch (error) {
            if (error instanceof Error) {
                throw error; // Re-throw known errors with original message
            }
            throw new Error('Failed to create deck');
        }
    }
    /**
     * Private method to create deck after all validations
     */
    async createDeck(cmd) {
        const deck = new DeckAggregate_1.DeckAggregate();
        deck.name = cmd.name;
        deck.type = cmd.type;
        deck.userid = cmd.userid;
        deck.cards = cmd.cards;
        deck.ctype = cmd.ctype ?? DeckAggregate_1.CType.PUBLIC;
        deck.state = DeckAggregate_1.State.ACTIVE;
        // Set organization reference for organizational decks
        if (cmd.ctype === DeckAggregate_1.CType.ORGANIZATION) {
            const user = await this.userRepo.findById(cmd.userid);
            if (user?.orgid) {
                const org = await this.orgRepo.findById(user.orgid);
                if (org) {
                    deck.organization = org;
                }
            }
        }
        const created = await this.deckRepo.create(deck);
        (0, Logger_1.logRequest)('Deck created successfully', undefined, undefined, {
            deckId: created.id,
            userId: cmd.userid,
            deckName: cmd.name,
            deckType: cmd.type,
            ctype: cmd.ctype,
            cardCount: cmd.cards.length
        });
        return DeckMapper_1.DeckMapper.toShortDto(created);
    }
}
exports.CreateDeckCommandHandler = CreateDeckCommandHandler;
//# sourceMappingURL=CreateDeckCommandHandler.js.map