import { REST, Routes, Collection, Client, ChatInputCommandInteraction, GatewayIntentBits } from 'discord.js';
import fs from 'fs';
import path from 'path';
import { SlashCommand } from '../utils/types';
import { env } from '../config/env';
import { logger } from '../utils/logger';
import { AdminService } from './adminService';
import { StatuspageService } from './statuspageService';
import { settingsStore } from '../config/state';
import { ModuleKey } from './moduleService';

export class CommandHandler {
  private commands = new Collection<string, SlashCommand>();
  private moduleMap: Record<string, ModuleKey> = {
    // Tickets
    ticket: 'ticketsEnabled',
    ticketpanel: 'ticketsEnabled',
    transcript: 'ticketsEnabled',
    close: 'ticketsEnabled',
    claim: 'ticketsEnabled',
    // Music
    play: 'musicEnabled',
    skip: 'musicEnabled',
    stop: 'musicEnabled',
    pause: 'musicEnabled',
    resume: 'musicEnabled',
    loop: 'musicEnabled',
    queue: 'musicEnabled',
    // Level
    rank: 'levelingEnabled',
    // Statuspage
    status: 'statuspageEnabled',
    // Birthday
    birthday: 'birthdayEnabled',
    // Events
    event: 'eventsEnabled',
    events: 'eventsEnabled'
  };

  constructor(private client: Client, private admin?: AdminService, private statuspage?: StatuspageService) {}

  public async loadCommands() {
    const commandsPath = path.join(process.cwd(), 'src', 'commands');
    const commandFiles = this.getCommandFiles(commandsPath);

    for (const file of commandFiles) {
      const mod = await import(file);
      const command: SlashCommand = mod.default;
      if (command?.data && command?.execute) {
        this.commands.set(command.data.name, command);
        logger.info(`Loaded command ${command.data.name}`);
      }
    }
  }

  private getCommandFiles(dir: string): string[] {
    const entries = fs.readdirSync(dir, { withFileTypes: true });
    const files: string[] = [];
    for (const entry of entries) {
      const res = path.resolve(dir, entry.name);
      if (entry.isDirectory()) {
        files.push(...this.getCommandFiles(res));
      } else if (entry.isFile() && (entry.name.endsWith('.ts') || entry.name.endsWith('.js'))) {
        files.push(res);
      }
    }
    return files;
  }

  public async registerSlashCommands() {
    const rest = new REST({ version: '10' }).setToken(env.token);
    const body = this.commands.map((command) => command.data.toJSON());

    const guilds = env.guildIds.length ? env.guildIds : [];
    if (guilds.length) {
      for (const gid of guilds) {
        try {
          await rest.put(Routes.applicationGuildCommands(env.clientId, gid), { body });
          logger.info(`Registered ${body.length} slash commands for guild ${gid}`);
        } catch (err) {
          logger.error(`Failed to register slash commands for guild ${gid}`, err);
        }
      }
    } else {
      try {
        await rest.put(Routes.applicationCommands(env.clientId), { body });
        logger.info(`Registered ${body.length} global slash commands`);
      } catch (err) {
        logger.error('Failed to register global slash commands', err);
      }
    }
  }

  public async registerGuildCommands(guildId: string) {
    const rest = new REST({ version: '10' }).setToken(env.token);
    const body = this.commands.map((command) => command.data.toJSON());
    try {
      await rest.put(Routes.applicationGuildCommands(env.clientId, guildId), { body });
      logger.info(`Registered ${body.length} slash commands for guild ${guildId}`);
    } catch (err) {
      logger.error(`Failed to register commands for guild ${guildId}`, err);
    }
  }

  public async handleInteraction(interaction: ChatInputCommandInteraction) {
    const command = this.commands.get(interaction.commandName);
    if (!command) return;
    if (command.guildOnly && !interaction.inGuild()) {
      await interaction.reply({ content: 'Dieser Befehl funktioniert nur auf Servern.', ephemeral: true });
      return;
    }
    if (interaction.inGuild()) {
      const moduleKey = this.moduleMap[interaction.commandName];
      if (moduleKey) {
        const cfg = settingsStore.get(interaction.guildId!);
        const enabled = cfg?.[moduleKey];
        if (enabled === false) {
          await interaction.reply({ content: 'Dieses Modul ist fuer diese Guild deaktiviert.', ephemeral: true });
          return;
        }
      }
    }
    try {
      this.admin?.trackCommand(interaction.guildId);
      if (interaction.guildId) this.admin?.trackGuildEvent(interaction.guildId, 'commands');
      await command.execute(interaction, this.client);
    } catch (err) {
      logger.error(`Command ${interaction.commandName} failed`, err);
      if (interaction.deferred || interaction.replied) {
        await interaction.followUp({ content: 'Es ist ein Fehler aufgetreten.', ephemeral: true });
      } else {
        await interaction.reply({ content: 'Es ist ein Fehler aufgetreten.', ephemeral: true });
      }
    }
  }
}
