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

// PhonePe Configuration
const PHONEPE_CONFIG = {
  merchantId: process.env.PHONEPE_MERCHANT_ID || 'YOUR_MERCHANT_ID',
  saltKey: process.env.PHONEPE_SALT_KEY || 'YOUR_SALT_KEY',
  saltIndex: process.env.PHONEPE_SALT_INDEX || '1',
  apiEndpoint: process.env.PHONEPE_ENV === 'production'
    ? 'https://api.phonepe.com/apis/hermes'
    : 'https://api-preprod.phonepe.com/apis/pg-sandbox',
  redirectUrl: process.env.PHONEPE_REDIRECT_URL || 'https://chitfund.deepteklabs.com/payment/callback',
  callbackUrl: process.env.PHONEPE_CALLBACK_URL || 'https://chitfund.deepteklabs.com/api/payments/phonepe/callback',
};

/**
 * Generate checksum for PhonePe API
 */
function generateChecksum(payload, endpoint) {
  const base64Payload = Buffer.from(JSON.stringify(payload)).toString('base64');
  const string = base64Payload + endpoint + PHONEPE_CONFIG.saltKey;
  const sha256 = crypto.createHash('sha256').update(string).digest('hex');
  return sha256 + '###' + PHONEPE_CONFIG.saltIndex;
}

/**
 * Verify checksum from PhonePe callback
 */
function verifyChecksum(base64Response, checksumHeader) {
  const [checksum] = checksumHeader.split('###');
  const string = base64Response + PHONEPE_CONFIG.saltKey;
  const calculatedChecksum = crypto.createHash('sha256').update(string).digest('hex');
  return checksum === calculatedChecksum;
}

/**
 * Initiate PhonePe payment
 */
const initiatePayment = async (req, res) => {
  try {
    const {
      group_id,
      user_id,
      month,
      year,
      amount,
      transaction_id,
      user_mobile,
    } = req.body;

    // Validate input
    if (!group_id || !user_id || !month || !year || !amount || !transaction_id) {
      return res.status(400).json({
        success: false,
        message: 'Missing required fields',
      });
    }

    // Check if chit group exists
    const chitGroup = await ChitGroup.findByPk(group_id);
    if (!chitGroup) {
      return res.status(404).json({
        success: false,
        message: 'Chit group not found',
      });
    }

    // Check if user is a member
    const groupMember = await GroupMember.findOne({
      where: { group_id, user_id, status: 'active' },
    });

    if (!groupMember) {
      return res.status(400).json({
        success: false,
        message: 'User is not an active member of this group',
      });
    }

    // Check if payment already exists
    const existingPayment = await Payment.findOne({
      where: { group_id, user_id, month, year },
    });

    if (existingPayment?.status === 'success') {
      return res.status(400).json({
        success: false,
        message: 'Payment for this month already completed',
      });
    }

    // Create/Update payment record with pending status
    const paymentData = {
      group_id,
      user_id,
      month,
      year,
      amount,
      payment_method: 'upi',
      transaction_id,
      status: 'pending',
      notes: 'PhonePe payment initiated',
    };

    if (existingPayment) {
      await existingPayment.update(paymentData);
    } else {
      await Payment.create(paymentData);
    }

    // Create PhonePe payment request
    const paymentPayload = {
      merchantId: PHONEPE_CONFIG.merchantId,
      merchantTransactionId: transaction_id,
      merchantUserId: user_id,
      amount: Math.round(amount * 100), // Convert to paise
      redirectUrl: `${PHONEPE_CONFIG.redirectUrl}?transactionId=${transaction_id}`,
      redirectMode: 'POST',
      callbackUrl: PHONEPE_CONFIG.callbackUrl,
      mobileNumber: user_mobile?.replaceAll(/\D/g, '').slice(-10) || '9999999999',
      paymentInstrument: {
        type: 'PAY_PAGE',
      },
    };

    // Generate checksum
    const endpoint = '/pg/v1/pay';
    const checksum = generateChecksum(paymentPayload, endpoint);

    // Encode payload
    const base64Payload = Buffer.from(JSON.stringify(paymentPayload)).toString('base64');

    // Make request to PhonePe
    const phonePeResponse = await axios.post(
      `${PHONEPE_CONFIG.apiEndpoint}${endpoint}`,
      {
        request: base64Payload,
      },
      {
        headers: {
          'Content-Type': 'application/json',
          'X-VERIFY': checksum,
        },
      }
    );

    if (phonePeResponse.data.success) {
      const paymentUrl = phonePeResponse.data.data.instrumentResponse.redirectInfo.url;

      return res.json({
        success: true,
        message: 'Payment initiated successfully',
        data: {
          payment_url: paymentUrl,
          transaction_id: transaction_id,
          checksum: checksum,
          amount: amount,
        },
      });
    } else {
      // Update payment status to failed
      await Payment.update(
        { status: 'failed', notes: phonePeResponse.data.message },
        { where: { transaction_id } }
      );

      return res.status(400).json({
        success: false,
        message: phonePeResponse.data.message || 'Failed to initiate payment',
      });
    }
  } catch (error) {
    console.error('PhonePe initiate payment error:', error);
    return res.status(500).json({
      success: false,
      message: error?.response?.data?.message || error.message || 'Failed to initiate payment',
    });
  }
};

/**
 * PhonePe payment callback
 */
const paymentCallback = async (req, res) => {
  try {
    const { transactionId, code, merchantId } = req.body;

    console.log('PhonePe callback received:', { transactionId, code, merchantId });

    // Verify payment status
    const verificationResult = await verifyPaymentStatus(transactionId);

    if (verificationResult.success) {
      return res.json({
        success: true,
        message: 'Payment successful',
      });
    } else {
      return res.json({
        success: false,
        message: verificationResult.message || 'Payment verification failed',
      });
    }
  } catch (error) {
    console.error('PhonePe callback error:', error);
    return res.status(500).json({
      success: false,
      message: 'Failed to process callback',
    });
  }
};

/**
 * Verify payment status with PhonePe
 */
async function verifyPaymentStatus(transactionId) {
  try {
    const endpoint = `/pg/v1/status/${PHONEPE_CONFIG.merchantId}/${transactionId}`;
    const checksum = generateChecksum({}, endpoint);

    const response = await axios.get(
      `${PHONEPE_CONFIG.apiEndpoint}${endpoint}`,
      {
        headers: {
          'Content-Type': 'application/json',
          'X-VERIFY': checksum,
          'X-MERCHANT-ID': PHONEPE_CONFIG.merchantId,
        },
      }
    );

    if (response.data.success && response.data.code === 'PAYMENT_SUCCESS') {
      // Update payment status
      const payment = await Payment.findOne({
        where: { transaction_id: transactionId },
      });

      if (payment) {
        const before = payment.toJSON();
        await payment.update({
          status: 'success',
          paid_at: new Date(),
          notes: 'PhonePe payment successful',
          source: 'gateway_phonepe',
        });
        await PaymentAuditEvent.create({
          payment_id: payment.id,
          actor_user_id: null,
          action: 'gateway_update',
          reason: 'PhonePe verification update',
          before,
          after: payment.toJSON()
        });

        return {
          success: true,
          message: 'Payment verified successfully',
          data: payment,
        };
      }
    } else {
      // Update payment status to failed
      await Payment.update(
        { 
          status: 'failed', 
          notes: response.data.message || 'Payment failed',
        },
        { where: { transaction_id: transactionId } }
      );

      return {
        success: false,
        message: response.data.message || 'Payment failed',
      };
    }
  } catch (error) {
    console.error('Payment verification error:', error);
    return {
      success: false,
      message: error.response?.data?.message || error.message || 'Verification failed',
    };
  }
}

/**
 * Verify payment endpoint (called from frontend)
 */
const verifyPayment = async (req, res) => {
  try {
    const { transaction_id } = req.body;

    if (!transaction_id) {
      return res.status(400).json({
        success: false,
        message: 'Transaction ID is required',
      });
    }

    const result = await verifyPaymentStatus(transaction_id);

    if (result.success) {
      return res.json({
        success: true,
        message: 'Payment verified successfully',
        data: result.data,
      });
    } else {
      return res.status(400).json({
        success: false,
        message: result.message,
      });
    }
  } catch (error) {
    console.error('Verify payment error:', error);
    return res.status(500).json({
      success: false,
      message: 'Failed to verify payment',
    });
  }
};

/**
 * Get payment status
 */
const getPaymentStatus = async (req, res) => {
  try {
    const { transactionId } = req.params;

    const payment = await Payment.findOne({
      where: { transaction_id: transactionId },
      include: [
        {
          model: User,
          attributes: ['id', 'full_name', 'mobile_number'],
        },
      ],
    });

    if (!payment) {
      return res.status(404).json({
        success: false,
        message: 'Payment not found',
      });
    }

    return res.json({
      success: true,
      data: {
        status: payment.status,
        amount: payment.amount,
        payment_method: payment.payment_method,
        paid_at: payment.paid_at,
        notes: payment.notes,
      },
    });
  } catch (error) {
    console.error('Get payment status error:', error);
    return res.status(500).json({
      success: false,
      message: 'Failed to get payment status',
    });
  }
};

/**
 * Initiate refund
 */
const initiateRefund = async (req, res) => {
  try {
    const { transaction_id, amount, reason } = req.body;
    const managerId = req.user.id;

    // Find payment
    const payment = await Payment.findOne({
      where: { transaction_id },
      include: [{
        model: ChitGroup,
        where: { manager_id: managerId },
      }],
    });

    if (!payment) {
      return res.status(404).json({
        success: false,
        message: 'Payment not found or access denied',
      });
    }

    if (payment.status !== 'success') {
      return res.status(400).json({
        success: false,
        message: 'Only successful payments can be refunded',
      });
    }

    // Create refund request payload
    const refundId = `REFUND_${Date.now()}`;
    const refundPayload = {
      merchantId: PHONEPE_CONFIG.merchantId,
      merchantTransactionId: transaction_id,
      originalTransactionId: transaction_id,
      amount: Math.round(amount * 100),
      callbackUrl: PHONEPE_CONFIG.callbackUrl,
    };

    const endpoint = '/pg/v1/refund';
    const checksum = generateChecksum(refundPayload, endpoint);
    const base64Payload = Buffer.from(JSON.stringify(refundPayload)).toString('base64');

    // Make refund request to PhonePe
    const response = await axios.post(
      `${PHONEPE_CONFIG.apiEndpoint}${endpoint}`,
      { request: base64Payload },
      {
        headers: {
          'Content-Type': 'application/json',
          'X-VERIFY': checksum,
        },
      }
    );

    if (response.data.success) {
      // Update payment status
      await payment.update({
        status: 'cancelled',
        notes: `Refund initiated: ${reason || 'No reason provided'}`,
      });

      return res.json({
        success: true,
        message: 'Refund initiated successfully',
        data: {
          refund_id: refundId,
          status: 'processing',
        },
      });
    } else {
      return res.status(400).json({
        success: false,
        message: response.data.message || 'Refund failed',
      });
    }
  } catch (error) {
    console.error('Refund error:', error);
    return res.status(500).json({
      success: false,
      message: error?.response?.data?.message || 'Failed to initiate refund',
    });
  }
};

/**
 * Handle external payment webhook (when member pays directly via UPI)
 */
const externalPaymentWebhook = async (req, res) => {
  try {
    const PaymentReconciliationService = require('../services/payment-reconciliation-service');
    
    console.log('External payment webhook received:', req.body);

    if (process.env.NODE_ENV === 'production') {
      const expected = process.env.EXTERNAL_WEBHOOK_SECRET;
      const provided = req.headers['x-webhook-secret']?.toString() || '';
      if (!expected) {
        return res.status(500).json({
          success: false,
          message: 'EXTERNAL_WEBHOOK_SECRET not configured'
        });
      }
      if (provided !== expected) {
        return res.status(401).json({
          success: false,
          message: 'Unauthorized webhook'
        });
      }
    }

    const result = await PaymentReconciliationService.processExternalPayment(req.body);

    if (result.success) {
      return res.json({
        success: true,
        message: result.message,
      });
    } else {
      return res.status(400).json({
        success: false,
        message: result.message,
      });
    }
  } catch (error) {
    console.error('External payment webhook error:', error);
    return res.status(500).json({
      success: false,
      message: 'Failed to process external payment',
    });
  }
};

/**
 * Generate payment intent with QR code
 */
const generatePaymentIntent = async (req, res) => {
  try {
    const PaymentReconciliationService = require('../services/payment-reconciliation-service');
    const { group_id, user_id, month, year } = req.body;
    const userId = req.user.id;

    // Validate input
    if (!group_id || !user_id || !month || !year) {
      return res.status(400).json({
        success: false,
        message: 'Group ID, user ID, month, and year are required',
      });
    }

    // Check if user is requesting their own payment or is the manager
    if (user_id !== userId) {
      const chitGroup = await ChitGroup.findOne({
        where: { id: group_id, manager_id: userId },
      });

      if (!chitGroup) {
        return res.status(403).json({
          success: false,
          message: 'Access denied',
        });
      }
    }

    // Get group details
    const group = await ChitGroup.findByPk(group_id);
    if (!group) {
      return res.status(404).json({
        success: false,
        message: 'Group not found',
      });
    }

    // Create payment intent
    const result = await PaymentReconciliationService.createPaymentIntent(
      group_id,
      user_id,
      month,
      year,
      Number.parseFloat(group.monthly_installment)
    );

    if (result.success) {
      // Generate UPI QR code data
      const upiId = process.env.PHONEPE_UPI_ID || 'merchant@paytm'; // Your business UPI ID
      const qrData = PaymentReconciliationService.getQRCodeData(
        upiId,
        group.monthly_installment,
        'LuckyChit Payment',
        result.upiReference
      );

      return res.json({
        success: true,
        message: 'Payment intent created',
        data: {
          upi_reference: result.upiReference,
          qr_code_data: qrData,
          upi_id: upiId,
          amount: group.monthly_installment,
          payment_intent: result.payment,
        },
      });
    } else {
      return res.status(400).json({
        success: false,
        message: result.message,
      });
    }
  } catch (error) {
    console.error('Generate payment intent error:', error);
    return res.status(500).json({
      success: false,
      message: 'Failed to generate payment intent',
    });
  }
};

/**
 * Get payment QR code
 */
const getPaymentQRCode = async (req, res) => {
  try {
    const PaymentReconciliationService = require('../services/payment-reconciliation-service');
    const { groupId, month, year } = req.params;
    const userId = req.user.id;

    // Get group
    const group = await ChitGroup.findByPk(groupId);
    if (!group) {
      return res.status(404).json({
        success: false,
        message: 'Group not found',
      });
    }

    // Check membership
    const member = await GroupMember.findOne({
      where: { group_id: groupId, user_id: userId, status: 'active' },
    });

    if (!member && group.manager_id !== userId) {
      return res.status(403).json({
        success: false,
        message: 'Access denied',
      });
    }

    // Generate UPI reference
    const upiReference = PaymentReconciliationService.generateUPIReference(
      groupId,
      userId,
      Number.parseInt(month, 10),
      Number.parseInt(year, 10)
    );

    // Generate QR code data
    const upiId = process.env.PHONEPE_UPI_ID || 'merchant@paytm';
    const qrData = PaymentReconciliationService.getQRCodeData(
      upiId,
      group.monthly_installment,
      'LuckyChit Payment',
      upiReference
    );

    return res.json({
      success: true,
      data: {
        upi_reference: upiReference,
        qr_code_data: qrData,
        upi_id: upiId,
        amount: group.monthly_installment,
        group_name: group.name,
        month: Number.parseInt(month, 10),
        year: Number.parseInt(year, 10),
      },
    });
  } catch (error) {
    console.error('Get payment QR code error:', error);
    return res.status(500).json({
      success: false,
      message: 'Failed to get payment QR code',
    });
  }
};

/**
 * Get UPI settings (for settings screen)
 */
const getUPISettings = async (req, res) => {
  try {
    const upiId = process.env.PHONEPE_UPI_ID;
    const isConfigured = !!upiId && upiId !== 'merchant@paytm' && upiId.length > 5;

    return res.json({
      success: true,
      data: {
        upi_id: upiId || 'Not configured',
        is_configured: isConfigured,
        provider: isConfigured ? upiId.split('@')[1] : null,
        transaction_fee: 0,
        transaction_fee_percentage: '0%',
        setup_status: isConfigured ? 'active' : 'pending',
      },
    });
  } catch (error) {
    console.error('Get UPI settings error:', error);
    return res.status(500).json({
      success: false,
      message: 'Failed to get UPI settings',
    });
  }
};

module.exports = {
  initiatePayment,
  paymentCallback,
  verifyPayment,
  getPaymentStatus,
  initiateRefund,
  externalPaymentWebhook,
  generatePaymentIntent,
  getPaymentQRCode,
  getUPISettings,
};

