import { importCommands, initializeCommandHandling, registerCommands } from '@commands';
import { Client } from '@projectdysnomia/dysnomia';
import kv, { asyncKV } from '@star-kitten/util/kv.js';
import type { KVStore } from './kv-store.type.ts';
import type { Cache } from './cache.type.ts';

export interface DiscordBotOptions {
  token?: string;
  intents?: number[];
  commandPattern?: string;
  commandBaseDir?: string;
  keyStore?: KVStore;
  cache?: Cache;
  onError?: (error: Error) => void;
  onReady?: () => void;
}

export function startDiscordBot({
  token = process.env.DISCORD_BOT_TOKEN || '',
  intents = [],
  commandPattern = '**/*.command.{js,ts}',
  commandBaseDir = 'src',
  keyStore = asyncKV,
  cache = kv,
  onError,
  onReady,
}: DiscordBotOptions = {}): Client {
  const client = new Client(`Bot ${token}`, {
    gateway: {
      intents,
    },
  });

  client.on('ready', async () => {
    console.debug(`Logged in as ${client.user?.username}#${client.user?.discriminator}`);
    onReady?.();
    const commands = await importCommands(commandPattern, commandBaseDir);
    await registerCommands(
      client,
      Object.values(commands).map((cmd) => cmd.definition),
    );
    initializeCommandHandling(commands, { client, cache, kv: keyStore });
    console.debug('Bot is ready and command handling is initialized.');
  });

  client.on('error', (error) => {
    console.error('An error occurred:', error);
    onError?.(error);
  });

  client.connect().catch(console.error);

  return client;
}
