import { Injectable, Logger } from '@nestjs/common';
import { TelebirrDto } from '../dto/telebirr.dto';
import { PaymentRepository } from '../../payment.repository';
import { DataSource } from 'typeorm';
import { Booking } from '../../../bookings/entities/booking.entity';
import { TelebirrProvider, ProviderPaymentStatus } from '@edr/payment-providers';

@Injectable()
export class TelebirrWebhookService {
    private readonly logger = new Logger(TelebirrWebhookService.name);

    constructor(
        private readonly datasource: DataSource,
        private readonly paymentRepo: PaymentRepository,
        private readonly telebirrProvider: TelebirrProvider,
    ) { }

    verifyTelebirrNotification(payload: TelebirrDto) {
        return this.telebirrProvider.verifyWebhookSignature(payload as unknown as Record<string, unknown>);
    }

    async handle(payload: TelebirrDto): Promise<void> {
        const payment = await this.paymentRepo.findOneBy({ merchantOrderId: payload.merch_order_id })
        if (!payment) {
            this.logger.warn(`Webhook received for unknown merchantOrderId: ${payload.merch_order_id}`);
            return;
        }

        const mapped = this.telebirrProvider.mapWebhookTradeStatus(payload.trade_status);

        switch (mapped) {
            case ProviderPaymentStatus.SUCCEEDED:
                await this.paymentRepo.update(
                    { id: payment.id },
                    { status: "success", paidAt: new Date() },
                );
                if (payment.type === "booking") {
                    await this.datasource.manager.update(
                        Booking,
                        { id: payment.refId },
                        { paymentStatus: "PAID" },
                    );
                }
                break;
            case ProviderPaymentStatus.FAILED:
                await this.paymentRepo.update({ id: payment.id }, { status: "failed" });
                break;
            case ProviderPaymentStatus.PROCESSING:
                await this.paymentRepo.update({ id: payment.id }, { status: "processing" });
                break;
        }
    }
}