import { CacheModule, MiddlewareConsumer, Module } from '@nestjs/common';
import { HealthController } from './health.controller';
import { ServeStaticModule } from '@nestjs/serve-static';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { join } from 'path';
import { LoggerMiddleware } from './common/loggerMiddleware';
import { AuthModule } from './features/auth/auth.module';
import { AuthController } from './features/auth/auth.controller';
import { AuthService } from './features/auth/auth.service';
import { AdB2cModule } from './gateways/adb2c/adb2c.module';
import { AccountsController } from './features/accounts/accounts.controller';
import { AccountsService } from './features/accounts/accounts.service';
import { AccountsModule } from './features/accounts/accounts.module';
import { UsersController } from './features/users/users.controller';
import { UsersService } from './features/users/users.service';
import { UsersModule } from './features/users/users.module';
import { AccountsRepositoryModule } from './repositories/accounts/accounts.repository.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { SendGridModule } from './gateways/sendgrid/sendgrid.module';
import { UsersRepositoryModule } from './repositories/users/users.repository.module';
import { LicensesRepositoryModule } from './repositories/licenses/licenses.repository.module';
import { AudioFilesRepositoryModule } from './repositories/audio_files/audio_files.repository.module';
import { AudioOptionItemsRepositoryModule } from './repositories/audio_option_items/audio_option_items.repository.module';
import { TasksRepositoryModule } from './repositories/tasks/tasks.repository.module';
import { NotificationhubModule } from './gateways/notificationhub/notificationhub.module';
import { NotificationhubService } from './gateways/notificationhub/notificationhub.service';
import { NotificationModule } from './features/notification/notification.module';
import { FilesModule } from './features/files/files.module';
import { FilesController } from './features/files/files.controller';
import { FilesService } from './features/files/files.service';
import { TemplatesModule } from './features/templates/templates.module';
import { TemplatesController } from './features/templates/templates.controller';
import { TasksService } from './features/tasks/tasks.service';
import { TasksController } from './features/tasks/tasks.controller';
import { TasksModule } from './features/tasks/tasks.module';
import { AuthGuardsModule } from './common/guards/auth/authguards.module';
import { BlobstorageModule } from './gateways/blobstorage/blobstorage.module';
import { LicensesModule } from './features/licenses/licenses.module';
import { LicensesService } from './features/licenses/licenses.service';
import { LicensesController } from './features/licenses/licenses.controller';
import { CheckoutPermissionsRepositoryModule } from './repositories/checkout_permissions/checkout_permissions.repository.module';
import { UserGroupsRepositoryModule } from './repositories/user_groups/user_groups.repository.module';
import { SortCriteriaRepositoryModule } from './repositories/sort_criteria/sort_criteria.repository.module';
import { TemplateFilesRepositoryModule } from './repositories/template_files/template_files.repository.module';
import { WorktypesRepositoryModule } from './repositories/worktypes/worktypes.repository.module';
import { TemplatesService } from './features/templates/templates.service';
import { WorkflowsModule } from './features/workflows/workflows.module';
import { WorkflowsController } from './features/workflows/workflows.controller';
import { WorkflowsService } from './features/workflows/workflows.service';
import { validate } from './common/validators/env.validator';
import { WorkflowsRepositoryModule } from './repositories/workflows/workflows.repository.module';
import { TermsModule } from './features/terms/terms.module';
import { RedisModule } from './gateways/redis/redis.module';
import * as redisStore from 'cache-manager-redis-store';
@Module({
  imports: [
    ServeStaticModule.forRootAsync({
      useFactory: () =>
        process.env.STAGE === 'local'
          ? [
              {
                rootPath: join(__dirname, '..', 'build'),
              },
            ]
          : [],
    }),
    ConfigModule.forRoot({
      envFilePath: ['.env.local', '.env'],
      isGlobal: true,
      validate,
    }),
    AuthModule,
    AdB2cModule,
    AccountsModule,
    UsersModule,
    FilesModule,
    TasksModule,
    UsersModule,
    TemplatesModule,
    SendGridModule,
    LicensesModule,
    WorkflowsModule,
    AccountsRepositoryModule,
    UsersRepositoryModule,
    LicensesRepositoryModule,
    AudioFilesRepositoryModule,
    AudioOptionItemsRepositoryModule,
    TasksRepositoryModule,
    CheckoutPermissionsRepositoryModule,
    UserGroupsRepositoryModule,
    TemplateFilesRepositoryModule,
    WorkflowsRepositoryModule,
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        type: 'mysql',
        host: configService.get('DB_HOST'),
        port: configService.get('DB_PORT'),
        username: configService.get('DB_USERNAME'),
        password: configService.get('DB_PASSWORD'),
        database: configService.get('DB_NAME'),
        autoLoadEntities: true, // forFeature()で登録されたEntityを自動的にロード
        synchronize: false, // trueにすると自動的にmigrationが行われるため注意
      }),
      inject: [ConfigService],
    }),
    CacheModule.registerAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => {
        const host = configService.getOrThrow<string>('REDIS_HOST');
        const port = configService.getOrThrow<number>('REDIS_PORT');
        const password = configService.getOrThrow<string>('REDIS_PASSWORD');
        if (process.env.STAGE === 'local') {
          return {
            store: redisStore,
            host: host,
            port: port,
            password: password,
          };
        }

        return {
          store: redisStore,
          url: `rediss://${host}:${port}`,
          password: password,
          tls: {},
        };
      },
      inject: [ConfigService],
      isGlobal: true,
    }),
    NotificationModule,
    NotificationhubModule,
    BlobstorageModule,
    AuthGuardsModule,
    SortCriteriaRepositoryModule,
    WorktypesRepositoryModule,
    TermsModule,
    RedisModule,
  ],
  controllers: [
    HealthController,
    AuthController,
    AccountsController,
    UsersController,
    FilesController,
    TasksController,
    UsersController,
    LicensesController,
    TemplatesController,
    WorkflowsController,
  ],
  providers: [
    AuthService,
    AccountsService,
    UsersService,
    NotificationhubService,
    FilesService,
    TasksService,
    LicensesService,
    TemplatesService,
    WorkflowsService,
  ],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes('');
  }
}
