/**
 * Payments Controllers
 * Request handlers for payment operations
 */

// Import payment service functions
const paymentService = require('../services');
// Import async handler wrapper
const asyncHandler = require('../../../middlewares/asyncHandler');
// Import response helpers
const { success: successResponse } = require('../../../utils/response');
// Import logger
const logger = require('../../../utils/logger');

/**
 * Create payment (Cash or Bank)
 * Creates a payment record for cash or bank payments
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const createPayment = asyncHandler(async (req, res) => {
  // Extract payment data from request body
  const paymentData = req.body; // Get payment data
  // Get user ID from request (from authentication middleware)
  const userId = req.user.id; // Get authenticated user ID
  
  // Create payment using service
  const payment = await paymentService.createPayment(paymentData, userId); // Create payment
  
  // Log payment creation
  logger.info('Payment created', {
    paymentId: payment.id,
    saleId: payment.sale_id,
    provider: payment.provider,
    amount: payment.amount,
    userId, // Log user ID
  });
  
  // Return success response with payment data
  return successResponse(res, payment, 'Payment created successfully', 201); // Return success response
});

/**
 * Process Paystack payment
 * Initializes Paystack payment and returns authorization URL
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const processPaystackPayment = asyncHandler(async (req, res) => {
  // Extract payment data from request body
  const paymentData = req.body; // Get payment data
  // Get user ID from request (from authentication middleware)
  const userId = req.user.id; // Get authenticated user ID
  
  // Process Paystack payment using service
  const result = await paymentService.processPaystackPayment(paymentData, userId); // Process payment
  
  // Log Paystack payment initialization
  logger.info('Paystack payment initialized', {
    paymentId: result.payment.id,
    saleId: paymentData.sale_id,
    amount: paymentData.amount,
    reference: result.payment.reference,
    userId, // Log user ID
  });
  
  // Return success response with payment and authorization URL
  return successResponse(res, {
    payment: result.payment, // Payment record
    authorization_url: result.paystack.data?.authorization_url, // Authorization URL for redirect
  }, 'Paystack payment initialized successfully', 201); // Return success response
});

/**
 * Verify Paystack payment
 * Verifies payment status with Paystack and updates payment record
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const verifyPaystackPayment = asyncHandler(async (req, res) => {
  // Extract payment reference from request params
  const { reference } = req.params; // Get payment reference
  
  // Verify Paystack payment using service
  const payment = await paymentService.verifyPaystackPayment(reference); // Verify payment
  
  // Log payment verification
  logger.info('Paystack payment verified', {
    paymentId: payment.id,
    reference: payment.reference,
    status: payment.status,
    saleId: payment.sale_id,
  });
  
  // Return success response with payment data
  return successResponse(res, payment, 'Payment verified successfully'); // Return success response
});

/**
 * Process mobile money payment
 * Processes mobile money payment (mock/stub implementation)
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const processMobileMoneyPayment = asyncHandler(async (req, res) => {
  // Extract payment data from request body
  const paymentData = req.body; // Get payment data
  // Get user ID from request (from authentication middleware)
  const userId = req.user.id; // Get authenticated user ID
  
  // Process mobile money payment using service
  const payment = await paymentService.processMobileMoneyPayment(paymentData, userId); // Process payment
  
  // Log mobile money payment
  logger.info('Mobile money payment processed', {
    paymentId: payment.id,
    saleId: paymentData.sale_id,
    amount: paymentData.amount,
    phoneNumber: paymentData.phone_number,
    userId, // Log user ID
  });
  
  // Return success response with payment data
  return successResponse(res, payment, 'Mobile money payment processed successfully', 201); // Return success response
});

/**
 * Get payment by ID
 * Retrieves a payment with details
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const getPayment = asyncHandler(async (req, res) => {
  // Extract payment ID from request params
  const { id } = req.params; // Get payment ID
  
  // Get payment using service
  const payment = await paymentService.getPayment(id); // Get payment
  
  // Return success response with payment data
  return successResponse(res, payment, 'Payment retrieved successfully'); // Return success response
});

/**
 * List payments
 * Retrieves paginated list of payments with filters
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const listPayments = asyncHandler(async (req, res) => {
  // Extract query parameters
  const {
    page = 1, // Page number (default: 1)
    limit = 10, // Items per page (default: 10)
    sale_id, // Filter by sale ID
    provider, // Filter by provider
    status, // Filter by status
    start_date, // Filter by start date
    end_date, // Filter by end date
  } = req.query; // Extract query parameters
  
  // Build options object
  const options = {
    page: parseInt(page), // Convert to integer
    limit: parseInt(limit), // Convert to integer
    saleId: sale_id ? parseInt(sale_id) : null, // Convert to integer if provided
    provider: provider || null, // Provider filter
    status: status || null, // Status filter
    startDate: start_date || null, // Start date filter
    endDate: end_date || null, // End date filter
  };
  
  // List payments using service
  const result = await paymentService.listPayments(options); // List payments
  
  // Return success response with payments and pagination
  return successResponse(res, result, 'Payments retrieved successfully'); // Return success response
});

/**
 * Get payments for a sale
 * Retrieves all payments for a specific sale
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const getSalePayments = asyncHandler(async (req, res) => {
  // Extract sale ID from request params
  const { saleId } = req.params; // Get sale ID
  
  // Get sale payments using service
  const result = await paymentService.getSalePayments(parseInt(saleId)); // Get sale payments
  
  // Return success response with payments and summary
  return successResponse(res, result, 'Sale payments retrieved successfully'); // Return success response
});

/**
 * Handle Paystack webhook
 * Handles Paystack webhook events (payment verification)
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const handlePaystackWebhook = asyncHandler(async (req, res) => {
  // Extract webhook data from request body
  const webhookData = req.body; // Get webhook data
  // Extract event type
  const eventType = webhookData.event; // Get event type
  
  // Log webhook received
  logger.info('Paystack webhook received', {
    event: eventType,
    data: webhookData.data,
  });
  
  // Handle charge.success event (payment successful)
  if (eventType === 'charge.success') {
    // Extract payment reference from webhook data
    const reference = webhookData.data?.reference; // Get payment reference
    
    // If reference exists, verify payment
    if (reference) {
      // Verify payment using service
      await paymentService.verifyPaystackPayment(reference); // Verify payment
      
      // Log webhook processing
      logger.info('Paystack webhook processed - payment verified', {
        reference, // Payment reference
      });
    }
  }
  
  // Return 200 OK to Paystack (acknowledge webhook)
  return res.status(200).json({ received: true }); // Return acknowledgment
});

/**
 * Query M-Pesa STK Push status
 * Queries the status of an STK Push payment
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const querySTKPushStatus = asyncHandler(async (req, res) => {
  // Extract checkout request ID from request params
  const { checkoutRequestID } = req.params; // Get checkout request ID
  
  // Query STK Push status using service
  const result = await paymentService.querySTKPushStatus(checkoutRequestID); // Query status
  
  // Log status query
  logger.info('M-Pesa STK Push status queried', {
    checkoutRequestID,
    status: result.queryResult.resultCode,
    isComplete: result.queryResult.isComplete,
  });
  
  // Return success response with payment and query result
  return successResponse(res, result, 'STK Push status queried successfully'); // Return success response
});

/**
 * Handle M-Pesa callback/webhook
 * Handles M-Pesa callback and updates payment status
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const handleMPesaCallback = asyncHandler(async (req, res) => {
  // Extract callback data from request body
  const callbackData = req.body; // Get callback data
  
  // Log callback received
  logger.info('M-Pesa callback received', {
    checkoutRequestID: callbackData.Body?.stkCallback?.CheckoutRequestID,
    resultCode: callbackData.Body?.stkCallback?.ResultCode,
  });
  
  // Handle callback using service
  const result = await paymentService.handleMPesaCallback(callbackData); // Handle callback
  
  // Log callback processing
  logger.info('M-Pesa callback processed', {
    paymentId: result.payment.id,
    checkoutRequestID: result.callbackInfo.checkoutRequestID,
    isSuccess: result.callbackInfo.isSuccess,
  });
  
  // Return 200 OK to M-Pesa (acknowledge callback)
  return res.status(200).json({
    ResultCode: 0,
    ResultDesc: 'Callback processed successfully',
  }); // Return acknowledgment
});

/**
 * Manually confirm M-Pesa payment (manager/admin only)
 * Allows manager/admin to manually confirm M-Pesa payment with transaction code
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const manuallyConfirmMPesaPayment = asyncHandler(async (req, res) => {
  // Extract payment ID and transaction code from request body
  const { payment_id, mpesa_transaction_code } = req.body; // Get payment data
  // Get user ID from request (from authentication middleware)
  const managerId = req.user.id; // Get authenticated user ID

  // Manually confirm M-Pesa payment using service
  const payment = await paymentService.manuallyConfirmMPesaPayment(payment_id, mpesa_transaction_code, managerId); // Confirm payment

  // Log manual confirmation
  logger.info('M-Pesa payment manually confirmed', {
    paymentId: payment.id,
    saleId: payment.sale_id,
    mpesaTransactionCode: mpesa_transaction_code,
    managerId,
  });

  // Return success response with payment data
  return successResponse(res, payment, 'M-Pesa payment manually confirmed successfully'); // Return success response
});

// Export controllers
module.exports = {
  createPayment, // Create payment controller
  processPaystackPayment, // Process Paystack payment controller
  verifyPaystackPayment, // Verify Paystack payment controller
  processMobileMoneyPayment, // Process mobile money payment controller
  querySTKPushStatus, // Query STK Push status controller
  handleMPesaCallback, // Handle M-Pesa callback controller
  manuallyConfirmMPesaPayment, // Manually confirm M-Pesa payment controller
  getPayment, // Get payment controller
  listPayments, // List payments controller
  getSalePayments, // Get sale payments controller
  handlePaystackWebhook, // Handle Paystack webhook controller
};
