import { DynamicModule, forwardRef, Module } from "@nestjs/common";
import { HttpModule } from "@nestjs/axios";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { RabbitMQModule } from "@golevelup/nestjs-rabbitmq";
import { TypeOrmModule } from "@nestjs/typeorm";
import {
    PAYMENT_EVENTS_DLX,
    PAYMENT_EVENTS_EXCHANGE,
    PAYMENT_QUEUES,
    PaymentService as PaymentServiceEnum,
    paymentServiceBindingPattern,
} from "@edr/types";

import { ServiceAuthGuard } from "../../common/guards/service-auth.guard";
import { BillingModule } from "../billing/billing.module";
// import { FirstMileModule } from "../first-mile/first-mile.module";
// import { TrainSchedulingModule } from "../train-scheduling/train-scheduling.module";
import { PaymentRefundEntity } from "./entities/payment-refund.entity";
import { PaymentWebhookEventEntity } from "./entities/payment-webhook-event.entity";
import { PaymentEntity } from "./entities/payment.entity";
import { InternalPaymentController } from "./internal-payment.controller";
import { PaymentClientService } from "./payment-client.service";
import { PaymentController } from "./payment.controller";
import { PaymentEventsConsumer } from "./payment-events.consumer";
import { PaymentRepository } from "./payment.repository";
import { PaymentService } from "./payment.service";

const FREIGHT_QUEUE = PAYMENT_QUEUES[PaymentServiceEnum.FREIGHT];

function rabbitMQImport(): DynamicModule[] {
    if (!process.env.PAYMENT_RABBITMQ_URL) return [];

    return [
        RabbitMQModule.forRootAsync({
            inject: [ConfigService],
            useFactory: (config: ConfigService) => ({
                uri: config.get<string>("rabbitmq.url") ?? process.env.PAYMENT_RABBITMQ_URL ?? "",
                exchanges: [
                    { name: PAYMENT_EVENTS_EXCHANGE, type: "topic", options: { durable: true } },
                    { name: PAYMENT_EVENTS_DLX, type: "topic", options: { durable: true } },
                ],
                queues: [
                    {
                        name: FREIGHT_QUEUE.dlq,
                        exchange: PAYMENT_EVENTS_DLX,
                        routingKey: paymentServiceBindingPattern(PaymentServiceEnum.FREIGHT),
                        options: { durable: true },
                    },
                ],
                prefetchCount: config.get<number>("rabbitmq.prefetch") ?? 10,
                connectionInitOptions: { wait: false },
            }),
        }),
    ];
}

@Module({
    imports: [
        HttpModule.register({ timeout: 10_000 }),
        ConfigModule,
        forwardRef(() => BillingModule),
        // forwardRef(() => TrainSchedulingModule),
        // FirstMileModule,
        TypeOrmModule.forFeature([
            PaymentEntity,
            PaymentWebhookEventEntity,
            PaymentRefundEntity,
        ]),
        ...rabbitMQImport(),
    ],
    providers: [
        PaymentRepository,
        PaymentService,
        PaymentClientService,
        PaymentEventsConsumer,
        ServiceAuthGuard,
    ],
    controllers: [PaymentController, InternalPaymentController],
    exports: [PaymentService],
})
export class PaymentModule {}
