const { Payment, ChitGroup, GroupMember, User, PaymentAuditEvent } = require('../models');
const { Op } = require('sequelize');
const crypto = require('node:crypto');

/**
 * Payment Reconciliation Service
 * Handles automatic payment matching and updates when members pay directly via UPI
 */
class PaymentReconciliationService {
  /**
   * Generate unique UPI reference for a payment
   * Format: CHITFUND-GROUPID-USERID-MONTH-YEAR
   */
  static generateUPIReference(groupId, userId, month, year) {
    const shortGroupId = groupId.split('-')[0].toUpperCase();
    const shortUserId = userId.split('-')[0].toUpperCase();
    return `CHIT-${shortGroupId}-${shortUserId}-${month.toString().padStart(2, '0')}${year}`;
  }

  /**
   * Parse UPI reference to extract payment details
   */
  static parseUPIReference(reference) {
    const parts = reference.split('-');
    if (parts.length !== 5 || parts[0] !== 'CHIT') {
      return null;
    }

    try {
      const monthYear = parts[4];
      const month = Number.parseInt(monthYear.substring(0, 2), 10);
      const year = Number.parseInt(monthYear.substring(2), 10);

      return {
        groupIdPrefix: parts[1],
        userIdPrefix: parts[2],
        month,
        year,
      };
    } catch (error) {
      console.error('Error parsing UPI reference:', error);
      return null;
    }
  }

  /**
   * Match payment to a group member
   */
  static async matchPaymentToMember(paymentDetails) {
    const { groupIdPrefix, userIdPrefix, month, year } = paymentDetails;

    try {
      // Find matching payment record
      const payment = await Payment.findOne({
        where: {
          month,
          year,
          status: {
            [Op.in]: ['pending', 'failed'],
          },
        },
        include: [
          {
            model: ChitGroup,
            where: {
              id: {
                [Op.like]: `${groupIdPrefix}%`,
              },
            },
          },
          {
            model: User,
            where: {
              id: {
                [Op.like]: `${userIdPrefix}%`,
              },
            },
          },
        ],
      });

      if (payment) {
        return {
          success: true,
          payment,
        };
      }

      // If no pending payment found, search for the group and user
      const groups = await ChitGroup.findAll({
        where: {
          id: {
            [Op.like]: `${groupIdPrefix}%`,
          },
        },
      });

      if (groups.length === 0) {
        return { success: false, message: 'Group not found' };
      }

      const users = await User.findAll({
        where: {
          id: {
            [Op.like]: `${userIdPrefix}%`,
          },
        },
      });

      if (users.length === 0) {
        return { success: false, message: 'User not found' };
      }

      return {
        success: true,
        payment: null,
        group: groups[0],
        user: users[0],
        month,
        year,
      };
    } catch (error) {
      console.error('Error matching payment:', error);
      return { success: false, message: error.message };
    }
  }

  /**
   * Process external PhonePe payment notification
   */
  static async processExternalPayment(webhookData) {
    try {
      const {
        transactionId,
        amount,
        status,
        payerVPA,
        remarks,
      } = webhookData;

      console.log('Processing external payment:', {
        transactionId,
        amount,
        status,
        remarks,
      });

      // Extract reference from remarks or transaction ID
      const reference = remarks || transactionId;
      const paymentDetails = this.parseUPIReference(reference);

      if (!paymentDetails) {
        console.log('Could not parse payment reference:', reference);
        return {
          success: false,
          message: 'Invalid payment reference format',
        };
      }

      // Match to member
      const matchResult = await this.matchPaymentToMember(paymentDetails);

      if (!matchResult.success) {
        return matchResult;
      }

      const amountInRupees = amount / 100; // Convert from paise

      if (matchResult.payment) {
        // Update existing payment record
        const before = matchResult.payment.toJSON();
        await matchResult.payment.update({
          status: status === 'SUCCESS' ? 'success' : 'failed',
          transaction_id: transactionId,
          amount: amountInRupees,
          payment_method: 'upi',
          paid_at: new Date(),
          notes: `External PhonePe payment - ${payerVPA || 'N/A'}`,
          source: 'direct_upi_webhook',
        });
        await PaymentAuditEvent.create({
          payment_id: matchResult.payment.id,
          actor_user_id: null,
          action: 'webhook_update',
          reason: 'External webhook update',
          before,
          after: matchResult.payment.toJSON()
        });

        return {
          success: true,
          message: 'Payment updated successfully',
          payment: matchResult.payment,
        };
      } else {
        // Create new payment record
        const newPayment = await Payment.create({
          group_id: matchResult.group.id,
          user_id: matchResult.user.id,
          month: matchResult.month,
          year: matchResult.year,
          amount: amountInRupees,
          payment_method: 'upi',
          transaction_id: transactionId,
          status: status === 'SUCCESS' ? 'success' : 'failed',
          paid_at: status === 'SUCCESS' ? new Date() : null,
          notes: `External PhonePe payment - ${payerVPA || 'N/A'}`,
          source: 'direct_upi_webhook',
        });
        await PaymentAuditEvent.create({
          payment_id: newPayment.id,
          actor_user_id: null,
          action: 'webhook_update',
          reason: 'External webhook create',
          before: null,
          after: newPayment.toJSON()
        });

        return {
          success: true,
          message: 'Payment recorded successfully',
          payment: newPayment,
        };
      }
    } catch (error) {
      console.error('Error processing external payment:', error);
      return {
        success: false,
        message: error.message,
      };
    }
  }

  /**
   * Generate payment intent (for creating pending payment with UPI reference)
   */
  static async createPaymentIntent(groupId, userId, month, year, amount) {
    try {
      // Check if payment already exists
      let payment = await Payment.findOne({
        where: { group_id: groupId, user_id: userId, month, year },
      });

      const upiReference = this.generateUPIReference(groupId, userId, month, year);

      if (payment) {
        // Update existing payment
        await payment.update({
          transaction_id: upiReference,
          status: 'pending',
          notes: `Payment intent created - UPI Ref: ${upiReference}`,
          source: 'member_upi_claim',
        });
      } else {
        // Create new payment
        payment = await Payment.create({
          group_id: groupId,
          user_id: userId,
          month,
          year,
          amount,
          payment_method: 'upi',
          transaction_id: upiReference,
          status: 'pending',
          notes: `Payment intent created - UPI Ref: ${upiReference}`,
          source: 'member_upi_claim',
        });
      }

      return {
        success: true,
        payment,
        upiReference,
      };
    } catch (error) {
      console.error('Error creating payment intent:', error);
      return {
        success: false,
        message: error.message,
      };
    }
  }

  /**
   * Get payment QR code data
   */
  static getQRCodeData(upiId, amount, name, reference) {
    // UPI URL format for QR codes
    return `upi://pay?pa=${upiId}&pn=${encodeURIComponent(name)}&am=${amount}&cu=INR&tn=${encodeURIComponent(reference)}`;
  }

  /**
   * Reconcile all pending payments
   * Check with PhonePe for status updates
   */
  static async reconcileAllPendingPayments() {
    try {
      const pendingPayments = await Payment.findAll({
        where: {
          status: 'pending',
          created_at: {
            [Op.gt]: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // Last 7 days
          },
        },
        include: [
          { model: ChitGroup },
          { model: User },
        ],
      });

      console.log(`Reconciling ${pendingPayments.length} pending payments...`);

      const results = {
        total: pendingPayments.length,
        updated: 0,
        failed: 0,
        stillPending: 0,
      };

      for (const payment of pendingPayments) {
        // Here you would call PhonePe API to check status
        // For now, we'll just log
        console.log(`Checking payment ${payment.transaction_id}...`);
        results.stillPending++;
      }

      return results;
    } catch (error) {
      console.error('Error reconciling payments:', error);
      throw error;
    }
  }

  /**
   * Send payment reminder with UPI details
   */
  static async sendPaymentReminder(groupId, userId, month, year) {
    try {
      const group = await ChitGroup.findByPk(groupId);
      const user = await User.findByPk(userId);

      if (!group || !user) {
        return { success: false, message: 'Group or user not found' };
      }

      const upiReference = this.generateUPIReference(groupId, userId, month, year);
      
      // Get or create payment intent
      const intent = await this.createPaymentIntent(
        groupId,
        userId,
        month,
        year,
        group.monthly_installment
      );

      return {
        success: true,
        upiReference,
        amount: group.monthly_installment,
        paymentIntent: intent.payment,
      };
    } catch (error) {
      console.error('Error sending payment reminder:', error);
      return {
        success: false,
        message: error.message,
      };
    }
  }
}

module.exports = PaymentReconciliationService;

