import { DynamicModule, Module } from '@nestjs/common';
import { ClientsModule, Transport, ClientOptions } from '@nestjs/microservices';
import { RmqService } from './rmq.service';
import { RmqModuleDefinition } from './rmq.module-definition';
interface RmqModuleOptions {
  name: string;
  rmqUri: string;
}
@Module({
  providers: [RmqService],
  exports: [],
})
export class RmqModule extends RmqModuleDefinition.ConfigurableModuleClass {
  // Static method to register the RMQ module with dynamic options
  static register({ name, rmqUri }: RmqModuleOptions): DynamicModule {
    return {
      module: RmqModule,
      imports: [
        ClientsModule.registerAsync([
          {
            name,
            useFactory: () => ({
              transport: Transport.RMQ,
              options: {
                urls: [rmqUri || ''],
                queue: `${name}_QUEUE`,
                queueOptions: {
                  durable: true,
                },
                prefetchCount: 1,
              },
            }),
          },
        ]),
      ],
      exports: [ClientsModule, RmqModule],
    };
  }

  static forRoot(
    options: typeof RmqModuleDefinition.OPTIONS_TYPE,
  ): DynamicModule {
    return {
      module: RmqModule,
      imports: [
        ClientsModule.registerAsync([
          {
            name: options.config?.name,
            useFactory: () => ({
              transport: Transport.RMQ,
              options: {
                urls: [options.config?.uri || ''],
                queue: `${options.config?.name}_QUEUE`,
                queueOptions: {
                  durable: true,
                },
                prefetchCount: 1,
              },
            }),
          },
        ]),
      ],
      exports: [ClientsModule, RmqModule],
    };
  }

  static forRootAsync(
    options: typeof RmqModuleDefinition.ASYNC_OPTIONS_TYPE,
  ): DynamicModule {
    const { config } = options?.useFactory!(options!.inject![0]) as any;
    return {
      module: RmqModule,
      imports: [
        ...(options.imports || []),
        ClientsModule.registerAsync([
          {
            name: config?.name,
            useFactory: async (...args) => {
              const opt = await options.useFactory!(...args);
              return {
                name: opt.config.name,
                transport: Transport.RMQ,
                options: {
                  urls: [opt.config.uri || ''],
                  queue: `${opt.config.name}_QUEUE`,
                  queueOptions: {
                    durable: true,
                  },
                  prefetchCount: 1,
                },
              } as ClientOptions;
            },
            inject: (options.inject as any) || [],
            imports: options.imports || [],
          },
        ]),
      ],
      exports: [ClientsModule, RmqModule],
    };
  }
}
