import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
// import { ScheduleModule } from '@nestjs/schedule';
import { CacheModule } from '@nestjs/cache-manager';
import { AccessControlModule } from 'nest-access-control';
import {
  // utilities as nestWinstonModuleUtilities,
  WinstonModule,
} from 'nest-winston';
import { PrismaModule } from 'nestjs-prisma';
import * as winston from 'winston';
import config from '../config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import modules from './modules';

import { ScheduleModule } from '@nestjs/schedule';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
import { LogFormat } from './lib/logger';
import { AgendaModule } from './modules/agenda/agenda.module';
import { HealthModule } from './modules/health/health.module';
import { RoleModule } from './modules/role/role.module';
import { RoleService } from './modules/role/role.service';
import { RolesRefresherService } from './modules/role/roles-refresher.service';

@Module({
  imports: [
    ScheduleModule.forRoot(),

    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', 'www'),
      exclude: ['/api/(.*)'],
    }),

    ConfigModule.forRoot({ isGlobal: true, load: [config] }),

    AccessControlModule.forRootAsync({
      imports: [
        /* Any modules providing RoleService */
        RoleModule,
      ],
      inject: [RoleService],
      useFactory: async (roleService: RoleService) => {
        const rolesData = await roleService.getBuilder(); // Fetch roles from DB
        return rolesData;
      },
    }),

    WinstonModule.forRootAsync({
      useFactory: (configService: ConfigService) => {
        const loggerConfig = configService.get('logger');
        return {
          level: loggerConfig.level,
          transports: [
            new winston.transports.Console({
              format: LogFormat,
            }),
          ],
        };
      },
      inject: [ConfigService],
    }),

    PrismaModule.forRootAsync({
      isGlobal: true,
      useFactory: async (configService: ConfigService) => {
        const prismaConfig = configService.get('prisma');
        return {
          prismaOptions: {
            log:
              process.env.NODE_ENV === 'development'
                ? prismaConfig.log
                : ['warn', 'error'],
          },
          explicitConnect: prismaConfig.explicit,
        };
      },
      inject: [ConfigService],
    }),

    CacheModule.register({
      isGlobal: true,
      ttl: 5 * 60 * 1000, // 5 minutes
    }),

    ...modules,
    AgendaModule,
    HealthModule,
  ],

  controllers: [AppController],
  providers: [AppService, RoleService, RolesRefresherService],
})
export class AppModule {}
