import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../../../common/prisma.service';
import { PaymentsService } from '../payments.service';
import { WaafiProvider } from '../providers/waafi.provider';
import { PaymentIntentStatus, PaymentMethodType } from '@prisma/client';

interface WaafiWebhookPayload {
  schemaVersion: string;
  requestId: string;
  timestamp: string;
  eventType: string;
  params: {
    state: string;
    referenceId: string;
    transactionId: string;
    amount: number;
    currency: string;
    description?: string;
  };
  signature?: string;
}

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

  constructor(
    private prisma: PrismaService,
    private paymentsService: PaymentsService,
    private waafiProvider: WaafiProvider,
  ) {}

  async handleWebhook(payload: WaafiWebhookPayload): Promise<{ received: boolean }> {
    this.logger.log(
      `Waafi webhook received: event=${payload.eventType} ref=${payload.params?.referenceId}`,
    );

    const signatureValid = this.waafiProvider.verifyWebhookSignature(
      payload as unknown as Record<string, unknown>,
    );

    const merchantOrderId = payload.params?.referenceId;
    const transactionId = payload.params?.transactionId;
    const state = payload.params?.state;

    await this.prisma.paymentWebhookEvent.create({
      data: {
        provider: PaymentMethodType.WAAFI,
        externalEventId: payload.requestId,
        merchantOrderId,
        providerTxnId: transactionId,
        signatureValid,
        status: state || 'UNKNOWN',
        payload: payload as any,
      },
    });

    if (!signatureValid) {
      this.logger.warn(`Waafi webhook signature invalid for ref=${merchantOrderId}`);
      return { received: true };
    }

    if (!merchantOrderId) {
      this.logger.error('Waafi webhook missing referenceId');
      return { received: true };
    }

    const intent = await this.prisma.paymentIntent.findFirst({
      where: { merchantOrderId },
    });

    if (!intent) {
      this.logger.warn(`No PaymentIntent found for merchantOrderId=${merchantOrderId}`);
      return { received: true };
    }

    const mappedStatus = this.waafiProvider.mapState(state);

    if (mappedStatus === PaymentIntentStatus.SUCCEEDED) {
      await this.paymentsService.finalizePaymentSuccess({
        intentId: intent.id,
        providerTxnId: transactionId,
      });
      this.logger.log(`Waafi payment succeeded: intent=${intent.id} txn=${transactionId}`);
    } else if (mappedStatus === PaymentIntentStatus.FAILED) {
      await this.paymentsService.markPaymentFailed({
        intentId: intent.id,
        failureCode: state,
        failureMessage: payload.params?.description,
      });
      this.logger.log(`Waafi payment failed: intent=${intent.id} state=${state}`);
    } else {
      await this.prisma.paymentIntent.update({
        where: { id: intent.id },
        data: {
          status: mappedStatus,
          providerTxnId: transactionId,
        },
      });
      this.logger.log(`Waafi payment status updated: intent=${intent.id} status=${mappedStatus}`);
    }

    return { received: true };
  }
}
