import { Module, Global, OnModuleDestroy, Inject } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import Knex from 'knex';
import { Model } from 'objection';
import { ModelsModule } from './models.module';

export const KNEX_CONNECTION = 'KNEX_CONNECTION';

@Global()
@Module({
  imports: [ModelsModule],
  providers: [
    {
      provide: KNEX_CONNECTION,
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => {
        const knex = Knex({
          client: 'pg',
          connection: {
            host: configService.get<string>('database.host'),
            port: configService.get<number>('database.port'),
            database: configService.get<string>('database.database'),
            user: configService.get<string>('database.username'),
            password: configService.get<string>('database.password'),
            ssl: configService.get<boolean>('database.ssl') ? { rejectUnauthorized: false } : false,
          },
          pool: {
            min: 2,
            max: 10,
          },
          debug: configService.get<boolean>('database.logging'),
        });

        // Bind Objection.js to Knex
        Model.knex(knex);

        return knex;
      },
    },
  ],
  exports: [KNEX_CONNECTION, ModelsModule],
})
export class DatabaseModule implements OnModuleDestroy {
  constructor(@Inject(KNEX_CONNECTION) private readonly knex: Knex.Knex) {}

  async onModuleDestroy(): Promise<void> {
    if (this.knex) {
      await (this.knex as unknown as Knex.Knex).destroy();
    }
  }
}
