<?php
// M-PESA STK Push callback handler

// Enable debugging for development
ini_set('display_errors', 1);
error_log("M-PESA Callback accessed at: " . date('Y-m-d H:i:s'));

// Database configuration
const DB_HOST = 'localhost';
const DB_USER = 'gnmprime_root'; 
const DB_PASS = 'Moses@4602';
const DB_NAME = 'gnmprime_saveapp';
const DEBUG = true;

// Connect to MySQL
function getDbConnection() {
    $conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
    if ($conn->connect_error) {
        http_response_code(500);
        logError("Database connection failed: " . $conn->connect_error);
        echo json_encode(['ResponseCode' => '1', 'ResponseDesc' => 'System error']);
        exit;
    }
    return $conn;
}

// Helper function for logging
function logError($message) {
    error_log("[M-PESA Callback Error] " . $message);
}

function logInfo($message) {
    error_log("[M-PESA Callback Info] " . $message);
}

// Forward payment to merchant (simulated for now)
function forwardToMerchant($transactionId, $merchantPaybill, $merchantAccount, $amount) {
    // Simulation for initial implementation
    logInfo("Simulating merchant payment for transaction $transactionId: $amount to $merchantPaybill/$merchantAccount");
    
    return [
        'status' => 'success',
        'message' => 'Merchant payment simulated successfully',
        'reference' => 'SIM-' . time() . '-' . $transactionId
    ];
}

// Process the callback
$callbackData = file_get_contents('php://input');
logInfo("Received callback data: " . $callbackData);

// Ensure we have data to process
if (empty($callbackData)) {
    logError("No callback data received");
    http_response_code(400);
    echo json_encode(['ResponseCode' => '1', 'ResponseDesc' => 'No data received']);
    exit;
}

// Parse the JSON data
$callbackJson = json_decode($callbackData, true);
if (json_last_error() !== JSON_ERROR_NONE) {
    logError("Invalid JSON: " . json_last_error_msg());
    http_response_code(400);
    echo json_encode(['ResponseCode' => '1', 'ResponseDesc' => 'Invalid JSON']);
    exit;
}

// Validate callback structure
if (!isset($callbackJson['Body']) || !isset($callbackJson['Body']['stkCallback']) || !isset($callbackJson['Body']['stkCallback']['CheckoutRequestID'])) {
    logError("Invalid callback format: missing required fields");
    http_response_code(400);
    echo json_encode(['ResponseCode' => '1', 'ResponseDesc' => 'Invalid callback format']);
    exit;
}

// Extract the necessary information
$stkCallback = $callbackJson['Body']['stkCallback'];
$checkoutRequestId = $stkCallback['CheckoutRequestID'];
$resultCode = $stkCallback['ResultCode'];
$resultDesc = $stkCallback['ResultDesc'];

logInfo("Processing payment for CheckoutRequestID: $checkoutRequestId, ResultCode: $resultCode");

// Connect to database
$conn = getDbConnection();

// Find the transaction
$stmt = $conn->prepare("SELECT id, merchant_paybill, merchant_account, merchant_amount FROM transactions WHERE checkout_request_id = ?");
if (!$stmt) {
    logError("Prepare statement failed: " . $conn->error);
    http_response_code(500);
    echo json_encode(['ResponseCode' => '1', 'ResponseDesc' => 'System error']);
    $conn->close();
    exit;
}

$stmt->bind_param("s", $checkoutRequestId);
$stmt->execute();
$result = $stmt->get_result();
$transaction = $result->fetch_assoc();
$stmt->close();

if (!$transaction) {
    logError("Transaction not found for CheckoutRequestID: $checkoutRequestId");
    http_response_code(404);
    echo json_encode(['ResponseCode' => '1', 'ResponseDesc' => 'Transaction not found']);
    $conn->close();
    exit;
}

$transactionId = $transaction['id'];
logInfo("Found transaction ID: $transactionId");

// Process based on the result code
if ($resultCode == 0) {
    // Payment successful
    logInfo("Payment successful for transaction ID: $transactionId");
    
    // Extract M-PESA receipt number if available
    $mpesaReceipt = '';
    if (isset($stkCallback['CallbackMetadata']) && isset($stkCallback['CallbackMetadata']['Item'])) {
        foreach ($stkCallback['CallbackMetadata']['Item'] as $item) {
            if ($item['Name'] == 'MpesaReceiptNumber') {
                $mpesaReceipt = $item['Value'];
                break;
            }
        }
    }
    
    // Update transaction status
    $stmt = $conn->prepare("UPDATE transactions SET status = 'completed', mpesa_receipt = ? WHERE id = ?");
    if (!$stmt) {
        logError("Prepare statement failed: " . $conn->error);
        http_response_code(500);
        echo json_encode(['ResponseCode' => '1', 'ResponseDesc' => 'System error']);
        $conn->close();
        exit;
    }
    
    $stmt->bind_param("si", $mpesaReceipt, $transactionId);
    $stmt->execute();
    $stmt->close();
    
    // Forward payment to merchant
    $merchantResponse = forwardToMerchant(
        $transactionId,
        $transaction['merchant_paybill'],
        $transaction['merchant_account'],
        $transaction['merchant_amount']
    );
    
    // Update merchant payment status
    if ($merchantResponse['status'] == 'success') {
        $stmt = $conn->prepare("UPDATE transactions SET merchant_status = 'completed', merchant_reference = ? WHERE id = ?");
        $stmt->bind_param("si", $merchantResponse['reference'], $transactionId);
    } else {
        $stmt = $conn->prepare("UPDATE transactions SET merchant_status = 'failed', merchant_error = ? WHERE id = ?");
        $errorMsg = $merchantResponse['message'];
        $stmt->bind_param("si", $errorMsg, $transactionId);
    }
    
    $stmt->execute();
    $stmt->close();
    
    logInfo("Transaction processing completed for ID: $transactionId");
} else {
    // Payment failed
    logError("Payment failed for transaction ID: $transactionId with code $resultCode: $resultDesc");
    
    $stmt = $conn->prepare("UPDATE transactions SET status = 'failed', error_message = ? WHERE id = ?");
    $stmt->bind_param("si", $resultDesc, $transactionId);
    $stmt->execute();
    $stmt->close();
}

$conn->close();

// Respond to M-PESA with success to acknowledge receipt
echo json_encode(['ResponseCode' => '0', 'ResponseDesc' => 'Success']);