import { readdir } from "node:fs/promises";
import { join } from "node:path";
import type { Event } from "@shared/lib/types";
import type { LoadResult } from "./types";
import type { Client } from "../BotClient";
 

/**
 * Handles loading events from the file system
 */
export class EventLoader {
    private client: Client;

    constructor(client: Client) {
        this.client = client;
    }

    /**
     * Load events from a directory recursively
     */
    async loadFromDirectory(dir: string, reload: boolean = false): Promise<LoadResult> {
        const result: LoadResult = { loaded: 0, skipped: 0, errors: [] };
        await this.scanDirectory(dir, reload, result);
        return result;
    }

    /**
     * Recursively scan directory for event files
     */
    private async scanDirectory(dir: string, reload: boolean, result: LoadResult): Promise<void> {
        try {
            const files = await readdir(dir, { withFileTypes: true });

            for (const file of files) {
                const filePath = join(dir, file.name);

                if (file.isDirectory()) {
                    await this.scanDirectory(filePath, reload, result);
                    continue;
                }

                if (!file.name.endsWith('.ts') && !file.name.endsWith('.js')) continue;

                await this.loadEventFile(filePath, reload, result);
            }
        } catch (error) {
            console.error(`Error reading directory ${dir}:`, error);
            result.errors.push({ file: dir, error });
        }
    }

    /**
     * Load a single event file
     */
    private async loadEventFile(filePath: string, reload: boolean, result: LoadResult): Promise<void> {
        try {
            const importPath = reload ? `${filePath}?t=${Date.now()}` : filePath;
            const eventModule = await import(importPath);
            const event = eventModule.default;

            if (this.isValidEvent(event)) {
                if (event.once) {
                    this.client.once(event.name, (...args) => event.execute(...args));
                } else {
                    this.client.on(event.name, (...args) => event.execute(...args));
                }
                console.log(`Loaded event: ${event.name}`);
                result.loaded++;
            } else {
                console.warn(`Skipping invalid event in ${filePath}`);
                result.skipped++;
            }
        } catch (error) {
            console.error(`Failed to load event from ${filePath}:`, error);
            result.errors.push({ file: filePath, error });
        }
    }

    /**
     * Type guard to validate event structure
     */
    private isValidEvent(event: any): event is Event<any> {
        return event && typeof event === 'object' && 'name' in event && 'execute' in event;
    }
}
