import { Module, Scope } from '@nestjs/common';
import { RefreshTokenInterceptor, SessionModule } from './core/sessions';
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
import { HttpExceptionFilter, TransformInterceptor } from './core/response';
import { ApmModule } from './core/apm';
import { CONNECTION_NAME } from './core/strings/constants/base.constants';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from '@nestjs/config';
import { UserPrivilegeModule } from './modules/user-related/user-privilege/user-privilege.module';
import { CqrsModule } from '@nestjs/cqrs';
import { CouchModule } from './modules/configuration/couch/couch.module';
import { UserPrivilegeModels } from './modules/user-related/user-privilege/constants';
import { RolesGuard } from './core/guards/domain/roles.guard';
import { PrivilegeService } from './core/guards/domain/services/privilege.service';
import { UserModel } from './modules/user-related/user/data/models/user.model';
import { AuthModule } from './modules/configuration/auth/auth.module';
import { UserModule } from './modules/user-related/user/user.module';
import { LogModel } from './modules/configuration/log/data/models/log.model';
import { ErrorLogModel } from './modules/configuration/log/data/models/error-log.model';
import { LogModule } from './modules/configuration/log/log.module';
import { TenantModule } from './modules/user-related/tenant/tenant.module';
import { ItemCategoryModule } from './modules/item-related/item-category/item-category.module';
import { ItemCategoryModel } from './modules/item-related/item-category/data/models/item-category.model';
import { ConstantModule } from './modules/configuration/constant/constant.module';
import { VipCategoryModule } from './modules/transaction/vip-category/vip-category.module';
import { VipCategoryModel } from './modules/transaction/vip-category/data/models/vip-category.model';
import { VipCodeModule } from './modules/transaction/vip-code/vip-code.module';
import { VipCodeModel } from './modules/transaction/vip-code/data/models/vip-code.model';
import { ItemModule } from './modules/item-related/item/item.module';
import { ItemModel } from './modules/item-related/item/data/models/item.model';
import { SeasonTypeModule } from './modules/season-related/season-type/season-type.module';
import { SeasonTypeModel } from './modules/season-related/season-type/data/models/season-type.model';
import { TaxModule } from './modules/transaction/tax/tax.module';
import { TaxModel } from './modules/transaction/tax/data/models/tax.model';
import { SalesPriceFormulaModule } from './modules/transaction/sales-price-formula/sales-price-formula.module';
import {
  SalesPriceFormulaModel,
  TransactionSettingModel,
} from './modules/transaction/sales-price-formula/data/models/sales-price-formula.model';
import { ProfitShareFormulaModule } from './modules/transaction/profit-share-formula/profit-share-formula.module';
import { PaymentMethodModule } from './modules/transaction/payment-method/payment-method.module';
import { PaymentMethodModel } from './modules/transaction/payment-method/data/models/payment-method.model';
import { SeasonPeriodModule } from './modules/season-related/season-period/season-period.module';
import { SeasonPeriodModel } from './modules/season-related/season-period/data/models/season-period.model';
import { ItemRateModule } from './modules/item-related/item-rate/item-rate.module';
import { ItemRateModel } from './modules/item-related/item-rate/data/models/item-rate.model';
import { GoogleCalendarModule } from './modules/configuration/google-calendar/google-calendar.module';
import { TransactionModule } from './modules/transaction/transaction/transaction.module';
import { TransactionModel } from './modules/transaction/transaction/data/models/transaction.model';
import {
  TransactionBreakdownTaxModel,
  TransactionItemBreakdownModel,
  TransactionItemModel,
  TransactionItemTaxModel,
} from './modules/transaction/transaction/data/models/transaction-item.model';
import { TransactionTaxModel } from './modules/transaction/transaction/data/models/transaction-tax.model';
import { ReconciliationModule } from './modules/transaction/reconciliation/reconciliation.module';
import { ReportModule } from './modules/reports/report/report.module';
import { ReportBookmarkModule } from './modules/reports/report-bookmark/report-bookmark.module';
import { ReportExportModule } from './modules/reports/report-export/report-export.module';
import { ReportBookmarkModel } from './modules/reports/shared/models/report-bookmark.model';
import { ExportReportHistoryModel } from './modules/reports/shared/models/export-report-history.model';
import { CronModule } from './modules/configuration/cron/cron.module';
import { MidtransModule } from './modules/configuration/midtrans/midtrans.module';
import { RefundModule } from './modules/transaction/refund/refund.module';
import { RefundModel } from './modules/transaction/refund/data/models/refund.model';
import { RefundItemModel } from './modules/transaction/refund/data/models/refund-item.model';
import { GateModule } from './modules/web-information/gate/gate.module';
import { GateModel } from './modules/web-information/gate/data/models/gate.model';
import { TermConditionModule } from './modules/web-information/term-condition/term-condition.module';
import { TermConditionModel } from './modules/web-information/term-condition/data/models/term-condition.model';
import { FaqModel } from './modules/web-information/faq/data/models/faq.model';
import { FaqModule } from './modules/web-information/faq/faq.module';
import { UploadModule } from './modules/configuration/upload/upload.module';
import { NewsModule } from './modules/web-information/news/news.module';
import { NewsModel } from './modules/web-information/news/data/models/news.model';
import { BannerModule } from './modules/web-information/banner/banner.module';
import { BannerModel } from './modules/web-information/banner/data/models/banner.model';
import { MailModule } from './modules/configuration/mail/mail.module';
import { PosLogModel } from './modules/configuration/log/data/models/pos-log.model';
import { ExportModule } from './modules/configuration/export/export.module';
import { TransactionDemographyModel } from './modules/transaction/transaction/data/models/transaction-demography.model';
import { SupersetModule } from './modules/configuration/superset/superset.module';
import { GateScanModule } from './modules/gates/gate.module';
import { UserLoginModel } from './modules/user-related/user/data/models/user-login.model';
import { LogUserLoginModel } from './modules/configuration/log/data/models/log-user-login.model';
import { AuthService } from './core/guards/domain/services/auth.service';
import { ReportSummaryModule } from './modules/reports/report-summary/report-summary.module';
import { QueueModule } from './modules/queue/queue.module';
import {
  QueueOrderModel,
  QueueTicketModel,
  QueueItemModel,
  QueueModel,
} from './modules/queue/data/models/queue.model';
import { ItemQueueModule } from './modules/item-related/item-queue/item-queue.module';
import { ItemQueueModel } from './modules/item-related/item-queue/data/models/item-queue.model';
import { QueueBucketModel } from './modules/queue/data/models/queue-bucket.model';
import { VerificationModel } from './modules/booking-online/authentication/data/models/verification.model';
import { BookingOnlineAuthModule } from './modules/booking-online/authentication/auth.module';
import { BookingOrderModule } from './modules/booking-online/order/order.module';
import { TimeGroupModule } from './modules/item-related/time-group/time-group.module';
import { TimeGroupModel } from './modules/item-related/time-group/data/models/time-group.model';

import { OtpVerificationModule } from './modules/configuration/otp-verification/otp-verification.module';
import { OtpVerificationModel } from './modules/configuration/otp-verification/data/models/otp-verification.model';
import { OtpVerifierModel } from './modules/configuration/otp-verification/data/models/otp-verifier.model';
import { RescheduleVerificationModel } from './modules/booking-online/order/data/models/reschedule-verification.model';
import { OtpCheckerGuard } from './core/guards/domain/otp-checker.guard';
import { DataSchedulingModel } from './modules/configuration/data-scheduling/data/models/data-scheduling.model';
import { DataSchedulingModule } from './modules/configuration/data-scheduling/data-scheduling.module';
import { DataSchedulingDefaultModel } from './modules/configuration/data-scheduling/data/models/data-scheduling-default.model';

@Module({
  imports: [
    ApmModule.register(),
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    TypeOrmModule.forRoot({
      name: CONNECTION_NAME.DEFAULT,
      type: 'postgres',
      host: process.env.DEFAULT_DB_HOST,
      port: parseInt(process.env.DEFAULT_DB_PORT),
      username: process.env.DEFAULT_DB_USER,
      password: process.env.DEFAULT_DB_PASS,
      database: process.env.DEFAULT_DB_NAME,
      entities: [
        ...UserPrivilegeModels,
        BannerModel,
        ErrorLogModel,
        FaqModel,
        GateModel,
        ItemModel,
        ItemCategoryModel,
        ItemRateModel,
        ItemQueueModel,
        TimeGroupModel,
        LogModel,
        LogUserLoginModel,
        NewsModel,
        PaymentMethodModel,
        PosLogModel,
        RefundModel,
        RefundItemModel,
        SalesPriceFormulaModel,
        SeasonPeriodModel,
        SeasonTypeModel,
        TaxModel,
        TermConditionModel,
        TransactionModel,
        TransactionItemModel,
        TransactionTaxModel,
        TransactionDemographyModel,
        TransactionItemBreakdownModel,
        TransactionItemTaxModel,
        TransactionBreakdownTaxModel,
        TransactionSettingModel,
        UserModel,
        UserLoginModel,

        VipCategoryModel,
        VipCodeModel,

        // report
        ReportBookmarkModel,
        ExportReportHistoryModel,

        // Queue
        QueueOrderModel,
        QueueTicketModel,
        QueueItemModel,
        QueueModel,
        QueueBucketModel,

        // Booking Online
        VerificationModel,
        RescheduleVerificationModel,

        OtpVerificationModel,
        OtpVerifierModel,

        // Data Scheduling
        DataSchedulingModel,
        DataSchedulingDefaultModel,
      ],
      synchronize: false,
    }),
    AuthModule,
    ConstantModule,
    CqrsModule,
    CouchModule,
    CronModule,
    ExportModule,
    GoogleCalendarModule,
    LogModule,
    MailModule,
    MidtransModule,
    SessionModule,
    UploadModule,

    // user
    TenantModule,
    UserModule,
    UserPrivilegeModule,

    // Item
    ItemCategoryModule,
    ItemModule,
    ItemRateModule,
    ItemQueueModule,
    TimeGroupModule,

    // transaction
    PaymentMethodModule,
    ProfitShareFormulaModule,
    ReconciliationModule,
    RefundModule,
    SalesPriceFormulaModule,
    TaxModule,
    TransactionModule,
    VipCategoryModule,
    VipCodeModule,

    // session
    SeasonTypeModule,
    SeasonPeriodModule,

    // web information
    BannerModule,
    FaqModule,
    GateModule,
    NewsModule,
    TermConditionModule,

    // report
    ReportModule,
    ReportBookmarkModule,
    ReportExportModule,
    ReportSummaryModule,

    // superset
    SupersetModule,

    GateScanModule,

    QueueModule,

    BookingOnlineAuthModule,
    BookingOrderModule,
    OtpVerificationModule,
    DataSchedulingModule,
  ],
  controllers: [],
  providers: [
    AuthService,
    PrivilegeService,
    OtpCheckerGuard,

    /**
     * By default all request from client will protect by JWT
     * if there is some endpoint/function that does'nt require authentication
     * please add `@Unprotected()` decorator to the function
     */
    {
      provide: APP_GUARD,
      scope: Scope.REQUEST,
      useClass: RolesGuard,
    },
    {
      provide: APP_INTERCEPTOR,
      scope: Scope.REQUEST,
      useClass: RefreshTokenInterceptor,
    },
    {
      provide: APP_INTERCEPTOR,
      scope: Scope.REQUEST,
      useClass: TransformInterceptor,
    },
    {
      provide: APP_FILTER,
      scope: Scope.REQUEST,
      useClass: HttpExceptionFilter,
    },
  ],
})
export class AppModule {}
