import { InvoiceStatus, PaymentMethod, PaymentStatus } from '@prisma/client';
import { prisma } from '../../config/database';
import { logger } from '../../utils/logger';
import { AppError } from '../../middleware/error-handler';
import type { BridgeRecordDonationInput } from './donation-bridge.schemas';

export const donationBridgeService = {
  async recordFromJsn(input: BridgeRecordDonationInput): Promise<{
    paymentId: number;
    invoiceId: number;
    created: boolean;
  }> {
    const email = input.email.trim().toLowerCase();
    const user = await prisma.user.findUnique({
      where: { email },
      select: { id: true },
    });
    if (!user) {
      throw new AppError(
        404,
        'No cmlite user for this email — provision via /api/auth/bridge/users first',
        'NO_CMLITE_USER',
      );
    }

    // Idempotency: keyed on stripePaymentIntentId (@unique on Payment).
    const existing = await prisma.payment.findUnique({
      where: { stripePaymentIntentId: input.stripePaymentIntentId },
      select: { id: true, invoiceId: true },
    });
    if (existing) {
      return { paymentId: existing.id, invoiceId: existing.invoiceId, created: false };
    }

    const succeededAt = new Date(input.succeededAt);
    const metadata = {
      source: 'jsn',
      externalId: input.externalId,
      isRecurring: input.isRecurring,
      stripeSubscriptionId: input.stripeSubscriptionId ?? null,
    };

    const result = await prisma.$transaction(async (tx) => {
      const invoice = await tx.invoice.create({
        data: {
          userId: user.id,
          amountCAD: input.amountCents,
          status: InvoiceStatus.paid,
          issuedAt: succeededAt,
          paidAt: succeededAt,
          dueDate: succeededAt,
          description: input.isRecurring
            ? 'JSN recurring donation'
            : 'JSN one-time donation',
          type: 'donation',
          metadata,
        },
        select: { id: true },
      });
      const payment = await tx.payment.create({
        data: {
          invoiceId: invoice.id,
          userId: user.id,
          amountCAD: input.amountCents,
          method: PaymentMethod.stripe,
          status: PaymentStatus.succeeded,
          externalId: input.externalId,
          stripePaymentIntentId: input.stripePaymentIntentId,
          processedAt: succeededAt,
          metadata,
        },
        select: { id: true, invoiceId: true },
      });
      return payment;
    });

    logger.info('Recorded JSN donation in cmlite', {
      userId: user.id,
      paymentId: result.id,
      externalId: input.externalId,
    });

    return { paymentId: result.id, invoiceId: result.invoiceId, created: true };
  },
};
