import { EventEmitter } from "node:events";
import type { Transaction } from "@shared/lib/types";

/**
 * Global system event bus for cross-module communication.
 * Used for real-time dashboard updates and domain event decoupling.
 */
class SystemEventEmitter extends EventEmitter {
    /**
     * Emit an event and await all listeners sequentially.
     * Used for domain events that must preserve transaction atomicity
     * (e.g., quest progress tracking within the caller's DB transaction).
     */
    async emitAsync(event: string, ...args: any[]): Promise<boolean> {
        const listeners = this.listeners(event);
        for (const listener of listeners) {
            await (listener as Function)(...args);
        }
        return listeners.length > 0;
    }
}

export const systemEvents = new SystemEventEmitter();

export const EVENTS = {
    DASHBOARD: {
        STATS_UPDATE: "dashboard:stats_update",
        NEW_EVENT: "dashboard:new_event",
    },
    ACTIONS: {
        RELOAD_COMMANDS: "actions:reload_commands",
        CLEAR_CACHE: "actions:clear_cache",
        MAINTENANCE_MODE: "actions:maintenance_mode",
    },
    QUEST: {
        COMPLETED: "quest:completed",
    },
    DOMAIN: {
        BALANCE_CHANGED: "domain:balance_changed",
        XP_GAINED: "domain:xp_gained",
        ITEM_COLLECTED: "domain:item_collected",
        ITEM_USED: "domain:item_used",
        TRANSFER_COMPLETED: "domain:transfer_completed",
        DAILY_CLAIMED: "domain:daily_claimed",
        TRIVIA_STARTED: "domain:trivia_started",
        TRIVIA_WON: "domain:trivia_won",
        EXAM_PASSED: "domain:exam_passed",
    },
} as const;

export interface DomainEventPayloads {
    [EVENTS.DOMAIN.BALANCE_CHANGED]: { userId: string; type: string; tx: Transaction };
    [EVENTS.DOMAIN.XP_GAINED]: { userId: string; amount: number; tx: Transaction };
    [EVENTS.DOMAIN.ITEM_COLLECTED]: { userId: string; itemId: number; quantity: number; tx: Transaction };
    [EVENTS.DOMAIN.ITEM_USED]: { userId: string; itemId: number; tx: Transaction };
    [EVENTS.DOMAIN.TRANSFER_COMPLETED]: { userId: string; username: string; amount: bigint; toUserId: string; tx: Transaction };
    [EVENTS.DOMAIN.DAILY_CLAIMED]: { userId: string; username: string; amount: bigint; tx: Transaction };
    [EVENTS.DOMAIN.TRIVIA_STARTED]: { username: string; difficulty: string };
    [EVENTS.DOMAIN.TRIVIA_WON]: { userId: string; username: string | undefined; reward: bigint; tx: Transaction };
    [EVENTS.DOMAIN.EXAM_PASSED]: { userId: string; username: string; reward: bigint; tx: Transaction };
}
