import { DynamicModule, Module, Provider } from "@nestjs/common";

import {
  EXCHANGE_OPTIONS,
  ExchangeAsyncOptions,
  ExchangeOptions,
} from "./exchange.options";
import { ExchangeService } from "./exchange.service";

/**
 * Provides {@link ExchangeService} (currency conversion, currently CBE-backed).
 *
 * Register once in the app root, then inject `ExchangeService` anywhere:
 *
 * ```ts
 * // static config
 * ExchangeModule.forRoot({ fallbackRate: 135 })
 *
 * // config resolved from ConfigService
 * ExchangeModule.forRootAsync({
 *   inject: [ConfigService],
 *   useFactory: (config: ConfigService) => config.get('app.exchange'),
 * })
 * ```
 */
@Module({})
export class ExchangeModule {
  static forRoot(options: ExchangeOptions = {}): DynamicModule {
    return {
      module: ExchangeModule,
      providers: [
        { provide: EXCHANGE_OPTIONS, useValue: options },
        ExchangeService,
      ],
      exports: [ExchangeService],
    };
  }

  static forRootAsync(options: ExchangeAsyncOptions): DynamicModule {
    const optionsProvider: Provider = {
      provide: EXCHANGE_OPTIONS,
      useFactory: options.useFactory,
      inject: (options.inject ?? []) as never[],
    };

    return {
      module: ExchangeModule,
      providers: [optionsProvider, ExchangeService],
      exports: [ExchangeService],
    };
  }
}
