import { HttpModule } from "@nestjs/axios";
import { CacheModule, Logger, MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { SequelizeModule } from "@nestjs/sequelize";
import { ServeStaticModule } from "@nestjs/serve-static";
import { join } from "path";
import { AuthModule } from "./modules/auth/auth.module";
import { AppConfigService } from "./share/app-config.service";
import { ShareModule } from "./share/share.module";
import { UsersModule } from "./modules/users/users.module";
import { MomentTimezoneProvider } from "./common/providers/moment-timezone.provider";
import { LoggingMiddleware } from './middleware/logging.middleware';
import { LoggerService } from "./common/logger/logger.service";
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR } from "@nestjs/core";
import { ExceptionInterceptor } from "./interceptors/exception.interceptor";
import { NotFoundInterceptor } from "./interceptors/not-found.interceptor";
import { UnauthorizedInterceptor } from "./interceptors/unauthorized.interceptor";
import { ForbiddenInterceptor } from "./interceptors/forbidden.interceptor";

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: ".env",
    }),
    SequelizeModule.forRootAsync({
      imports: [ShareModule],
      inject: [AppConfigService, LoggerService],
      useFactory: (appConfigService: AppConfigService, logger: LoggerService) => ({
        dialect: appConfigService.db().dialect,
        host: appConfigService.db().host,
        port: appConfigService.db().port,
        username: appConfigService.db().username,
        password: appConfigService.db().password,
        database: appConfigService.db().database,
        autoLoadModels: true, // models will be loaded automatically
        synchronize: false, // disable automatically loaded models will be synchronized, use migrate
        benchmark: appConfigService.db().logging,
        timezone: appConfigService.db().timezone || "+07:00",
        logging: (query, options) => {
          if (appConfigService.db().logging) {
            logger.mysql_log(query, options);
          }
        },
        ...(process.env.DB_SSL == 'true' && {
          ssl: process.env.NEST_ENV == 'production',
          dialectOptions: {
            ssl: {
              rejectUnauthorized: false,
            },
          },
        }),
      }),
    }),
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, "..", "public"),
      exclude: ["/api*"],
    }),
    CacheModule.register({ isGlobal: true }),
    HttpModule,
    ShareModule,
    AuthModule,
    UsersModule,
  ],
  providers: [
    MomentTimezoneProvider,
    Logger,
    {
      provide: APP_INTERCEPTOR,
      useClass: ExceptionInterceptor
    },
    {
      provide: APP_FILTER,
      useClass: NotFoundInterceptor
    },
    {
      provide: APP_FILTER,
      useClass: UnauthorizedInterceptor
    },
    {
      provide: APP_FILTER,
      useClass: ForbiddenInterceptor
    }
  ]
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggingMiddleware).forRoutes('*');
  }
}