import { forwardRef, Inject, Module, type OnApplicationShutdown } from '@nestjs/common';
import { createQueue, type QueueHandle } from '@mosaicstack/queue';
import { ChatModule } from '../chat/chat.module.js';
import { GCModule } from '../gc/gc.module.js';
import { ReloadModule } from '../reload/reload.module.js';
import { CommandAuthorizationService } from './command-authorization.service.js';
import { CommandExecutorService } from './command-executor.service.js';
import { CommandRegistryService } from './command-registry.service.js';
import { CommandRuntimeApprovalVerifier } from './runtime-approval-verifier.js';
import { COMMANDS_REDIS } from './commands.tokens.js';

const COMMANDS_QUEUE_HANDLE = 'COMMANDS_QUEUE_HANDLE';

@Module({
  imports: [GCModule, forwardRef(() => ReloadModule), forwardRef(() => ChatModule)],
  providers: [
    {
      provide: COMMANDS_QUEUE_HANDLE,
      useFactory: (): QueueHandle => {
        return createQueue();
      },
    },
    {
      provide: COMMANDS_REDIS,
      useFactory: (handle: QueueHandle) => handle.redis,
      inject: [COMMANDS_QUEUE_HANDLE],
    },
    CommandRegistryService,
    CommandAuthorizationService,
    CommandRuntimeApprovalVerifier,
    CommandExecutorService,
  ],
  exports: [
    CommandRegistryService,
    CommandAuthorizationService,
    CommandRuntimeApprovalVerifier,
    CommandExecutorService,
  ],
})
export class CommandsModule implements OnApplicationShutdown {
  constructor(@Inject(COMMANDS_QUEUE_HANDLE) private readonly handle: QueueHandle) {}

  async onApplicationShutdown(): Promise<void> {
    await this.handle.close().catch(() => {});
  }
}
