import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Between } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { Payment } from '../entities/payment.entity';
import { Order } from '../entities/order.entity';
import { Receipt } from '../entities/receipt.entity';
import { EmailService } from './email.service';

@Injectable()
export class ReconciliationService {
  constructor(
    @InjectRepository(Payment)
    private paymentRepository: Repository<Payment>,
    @InjectRepository(Order)
    private orderRepository: Repository<Order>,
    @InjectRepository(Receipt)
    private receiptRepository: Repository<Receipt>,
    private emailService: EmailService,
    private configService: ConfigService,
  ) {}

  async generateDailyReport(date: Date): Promise<any> {
    const startOfDay = new Date(date);
    startOfDay.setHours(0, 0, 0, 0);
    const endOfDay = new Date(date);
    endOfDay.setHours(23, 59, 59, 999);

    const payments = await this.paymentRepository.find({
      where: {
        createdAt: Between(startOfDay, endOfDay),
      },
      relations: ['order', 'receipts'],
    });

    const report = {
      date: date.toISOString(),
      totalPayments: payments.length,
      totalAmount: payments.reduce((sum, p) => sum + p.amount, 0),
      successfulPayments: payments.filter((p) => p.status === 'completed').length,
      failedPayments: payments.filter((p) => p.status === 'failed').length,
      pendingPayments: payments.filter((p) => p.status === 'pending').length,
      details: payments.map((p) => ({
        orderId: p.orderId,
        amount: p.amount,
        status: p.status,
        paymentMethod: p.paymentMethod,
        receiptNumber: p.receipts[0]?.receiptNumber,
      })),
    };

    // Send daily report email
    // Placeholder: Use sendReceiptEmail as a generic sender for now
    await this.emailService.sendReceiptEmail(
      this.configService.get('ACCOUNTING_EMAIL'),
      { report },
      'Daily Payment Report',
    );

    return report;
  }

  async reconcilePayment(paymentId: string): Promise<any> {
    const payment = await this.paymentRepository.findOne({
      where: { id: paymentId },
      relations: ['order', 'receipts'],
    });

    if (!payment) {
      throw new Error('Payment not found');
    }

    // Verify payment status
    if (payment.status !== 'completed') {
      throw new Error('Payment is not completed');
    }

    // Verify receipt exists
    if (!payment.receipts?.[0]) {
      throw new Error('No receipt found for this payment');
    }

    // Verify order status
    if (payment.order.status !== 'completed') {
      throw new Error('Order status mismatch');
    }

    // Generate reconciliation record
    const reconciliation = {
      paymentId,
      orderId: payment.orderId,
      amount: payment.amount,
      paymentMethod: payment.paymentMethod,
      receiptNumber: payment.receipts[0].receiptNumber,
      status: 'reconciled',
      timestamp: new Date(),
    };

    // Send reconciliation confirmation email
    // Placeholder: Use sendReceiptEmail as a generic sender for now
    await this.emailService.sendReceiptEmail(
      payment.order.customer.email,
      { reconciliation },
      'Payment Reconciliation Confirmation',
    );

    return reconciliation;
  }

  async processRefund(
    paymentId: string,
    refundAmount: number,
    reason: string,
  ): Promise<any> {
    const payment = await this.paymentRepository.findOne({
      where: { id: paymentId },
      relations: ['order', 'receipts'],
    });

    if (!payment) {
      throw new Error('Payment not found');
    }

    if (payment.status !== 'completed') {
      throw new Error('Cannot refund incomplete payment');
    }

    if (refundAmount > payment.amount) {
      throw new Error('Refund amount exceeds original payment');
    }

    // Update payment status
    payment.status = 'refunded';
    payment.refundAmount = refundAmount;
    payment.refundReason = reason;
    payment.refundDate = new Date();

    await this.paymentRepository.save(payment);

    // Generate refund receipt
    const refundReceipt = await this.receiptRepository.save({
      receiptNumber: `REFUND-${Date.now()}`,
      amount: refundAmount,
      description: `Refund for order ${payment.orderId}: ${reason}`,
      order: payment.order,
      payment,
    });

    // Send refund confirmation email
    await this.emailService.sendRefundEmail(
      payment.order.customer.email,
      {
        amount: refundAmount,
        orderId: payment.orderId,
        reason,
        receiptNumber: refundReceipt.receiptNumber,
      },
      'Refund Confirmation',
    );

    return {
      refundReceipt,
      status: 'success',
      message: 'Refund processed successfully',
    };
  }
}
