<?php
require_once './includes/session_init.php';
require_once './includes/config.php';
// Enhanced error reporting
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/logs/mpesa_transaction_page_errors.log');

class Logger {
    private $logFile;
    private $maxFileSize = 10485760; // 10MB
    
    public function __construct($logFile = null) {
        $this->logFile = $logFile ?: __DIR__ . '/logs/mpesa_transactions.log';
        $this->ensureLogDirectory();
    }
    
    private function ensureLogDirectory() {
        $logDir = dirname($this->logFile);
        if (!is_dir($logDir)) {
            mkdir($logDir, 0755, true);
        }
    }
    
    public function log($level, $message, $context = []) {
        $timestamp = date('Y-m-d H:i:s');
        $logEntry = "[$timestamp] [$level] $message";
        
        if (!empty($context)) {
            $logEntry .= " " . json_encode($context, JSON_PRETTY_PRINT);
        }
        
        $logEntry .= "\n";
        
        // Check if log rotation is needed
        if (file_exists($this->logFile) && filesize($this->logFile) > $this->maxFileSize) {
            $this->rotateLog();
        }
        
        file_put_contents($this->logFile, $logEntry, FILE_APPEND | LOCK_EX);
        
        // Also output to console if in development
        if (defined('ENVIRONMENT') && ENVIRONMENT === 'development') {
            error_log($logEntry);
        }
    }
    
    private function rotateLog() {
        $backupFile = $this->logFile . '.' . date('Y-m-d_His');
        rename($this->logFile, $backupFile);
        
        // Compress old log if available
        if (function_exists('gzcompress')) {
            $compressedFile = $backupFile . '.gz';
            $data = file_get_contents($backupFile);
            $compressed = gzcompress($data, 9);
            file_put_contents($compressedFile, $compressed);
            unlink($backupFile);
        }
    }
    
    public function debug($message, $context = []) {
        $this->log('DEBUG', $message, $context);
    }
    
    public function info($message, $context = []) {
        $this->log('INFO', $message, $context);
    }
    
    public function warning($message, $context = []) {
        $this->log('WARNING', $message, $context);
    }
    
    public function error($message, $context = []) {
        $this->log('ERROR', $message, $context);
    }
    
    public function critical($message, $context = []) {
        $this->log('CRITICAL', $message, $context);
    }
}

// Initialize logger
$logger = new Logger();

// Log session configuration
$logger->debug('Session configuration', [
    'use_strict_mode' => ini_get('session.use_strict_mode'),
    'use_only_cookies' => ini_get('session.use_only_cookies'),
    'cookie_httponly' => ini_get('session.cookie_httponly'),
    'cookie_secure' => ini_get('session.cookie_secure'),
    'cookie_samesite' => ini_get('session.cookie_samesite'),
    'gc_maxlifetime' => ini_get('session.gc_maxlifetime'),
    'cookie_lifetime' => ini_get('session.cookie_lifetime')
]);

// Log session details
$logger->debug('Session started', [
    'session_id' => session_id(),
    'session_data' => $_SESSION,
    'session_status' => session_status(),
    'session_cookie_params' => session_get_cookie_params(),
    'session_cookie_exists' => isset($_COOKIE[session_name()]),
    'session_cookie_value' => $_COOKIE[session_name()] ?? 'not_set'
]);

// Session regeneration with data preservation - FIXED VERSION
$currentSessionId = session_id();
if (!empty($_SESSION) && empty($_SESSION['created'])) {
    $logger->debug('Session data exists but no created timestamp - preserving data');
    // Preserve existing session data during regeneration
    $existingSessionData = $_SESSION;
    session_regenerate_id(true);
    $_SESSION = $existingSessionData;
    $_SESSION['created'] = time();
    $_SESSION['regenerated_at'] = time();
    $_SESSION['previous_session_id'] = $currentSessionId;
    $logger->debug('Session regenerated with preserved data', [
        'session_data' => $_SESSION,
        'old_session_id' => $currentSessionId,
        'new_session_id' => session_id()
    ]);
} elseif (empty($_SESSION['created'])) {
    $oldSessionId = session_id();
    session_regenerate_id(true);
    $_SESSION['created'] = time();
    $_SESSION['previous_session_id'] = $oldSessionId;
    $logger->debug('New session created with timestamp', [
        'old_session_id' => $oldSessionId,
        'new_session_id' => session_id()
    ]);
}

// Session recovery mechanism
if (empty($_SESSION['member_id']) && !empty($_COOKIE['member_session_data'])) {
    $logger->debug('Attempting session recovery from cookie');
    try {
        $sessionData = json_decode(base64_decode($_COOKIE['member_session_data']), true);
        if ($sessionData && is_array($sessionData)) {
            foreach ($sessionData as $key => $value) {
                if (!isset($_SESSION[$key])) {
                    $_SESSION[$key] = $value;
                }
            }
            $logger->debug('Session data restored from cookie', ['restored_keys' => array_keys($sessionData)]);
        }
    } catch (Exception $e) {
        $logger->error('Failed to restore session from cookie', ['error' => $e->getMessage()]);
    }
}

// Session health check
function checkSessionHealth($logger) {
    $sessionId = session_id();
    $logger->debug('Session health check', [
        'session_id' => $sessionId,
        'session_status' => session_status(),
        'session_data_keys' => array_keys($_SESSION),
        'session_cookie_exists' => isset($_COOKIE[session_name()]),
        'session_cookie_value' => $_COOKIE[session_name()] ?? 'not_set',
        'session_id_match' => (isset($_COOKIE[session_name()]) && $_COOKIE[session_name()] === $sessionId) ? 'match' : 'mismatch'
    ]);
    
    // Check if session is empty except for technical fields
    $technicalKeys = ['created', 'redirect_url', 'toastr', 'form_data', 'regenerated_at', 'previous_session_id'];
    $userKeys = array_diff(array_keys($_SESSION), $technicalKeys);
    
    if (empty($userKeys) && !empty($_COOKIE[session_name()])) {
        $logger->warning('Session appears to be empty of user data', [
            'session_cookie' => $_COOKIE[session_name()],
            'technical_keys' => $technicalKeys,
            'user_keys' => $userKeys
        ]);
        return false;
    }
    
    // Check for session ID mismatch
    if (isset($_COOKIE[session_name()]) && $_COOKIE[session_name()] !== $sessionId) {
        $logger->warning('Session ID mismatch detected', [
            'cookie_session_id' => $_COOKIE[session_name()],
            'current_session_id' => $sessionId
        ]);
        return false;
    }
    
    return count($userKeys) > 0;
}

// Perform session health check
$sessionHealthy = checkSessionHealth($logger);

// Enhanced authentication check with detailed logging
function checkAuthentication($logger) {
    // DEBUG: Log all session data for troubleshooting
    $logger->debug('Full session data in checkAuthentication', ['session' => $_SESSION]);
    
    $logger->debug('Checking authentication status', [
        'session_keys' => array_keys($_SESSION),
        'has_member_id' => isset($_SESSION['member_id']),
        'session_id' => session_id()
    ]);
    
    if (!isset($_SESSION['member_id'])) {
        $logger->warning('User not authenticated', [
            'session_keys' => array_keys($_SESSION),
            'redirect_reason' => 'missing_member_id',
            'session_created' => $_SESSION['created'] ?? 'not_set',
            'current_time' => time(),
            'session_age' => isset($_SESSION['created']) ? time() - $_SESSION['created'] : 'unknown',
            'request_uri' => $_SERVER['REQUEST_URI'],
            'script_name' => $_SERVER['PHP_SELF'],
            'session_id' => session_id()
        ]);
        
        // Check if this is an AJAX request
        if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && 
            strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
            http_response_code(401);
            echo json_encode([
                'status' => 'error',
                'message' => 'Session expired. Please refresh the page.',
                'redirect' => 'login.php'
            ]);
            exit;
        } else {
            // Store the current URL for redirect after login
            $_SESSION['redirect_url'] = $_SERVER['REQUEST_URI'];
            $logger->info('Redirecting to login', [
                'redirect_url' => $_SESSION['redirect_url'],
                'session_id' => session_id()
            ]);
            
            // Add a parameter to track redirects
            $redirectUrl = 'login.php?redirect=' . urlencode($_SERVER['REQUEST_URI']);
            header("Location: $redirectUrl");
            exit;
        }
    }
    
    $logger->debug('User authenticated', [
        'member_id' => $_SESSION['member_id'],
        'session_duration' => time() - ($_SESSION['created'] ?? 0),
        'session_id' => session_id()
    ]);
    
    return true;
}

// Check authentication with error handling
try {
    // DEBUG: Check if we're already on the login page to avoid loops
    if (basename($_SERVER['PHP_SELF']) !== 'login.php') {
        checkAuthentication($logger);
    }
} catch (Exception $e) {
    $logger->critical('Authentication check failed', [
        'error' => $e->getMessage(),
        'trace' => $e->getTraceAsString(),
        'session_status' => session_status(),
        'session_id' => session_id(),
        'session_data' => $_SESSION
    ]);
    
    // Attempt to clear potentially corrupted session
    session_unset();
    session_destroy();
    session_start();
    session_regenerate_id(true);
    
    $_SESSION['auth_error'] = 'Session error occurred. Please login again.';
    header("Location: login.php");
    exit;
}

$title = 'M-Pesa Payments';
$subTitle = 'M-Pesa Payments';

// Include the STK processor
require_once '../cbs.creativewebsolutions.co.ke/STKPushPaymentProcessor.php';

/**
 * Phone Number Formatter Class
 */
class PhoneNumberFormatter {
    public static function formatPhoneNumber($phone) {
        // Remove all non-digit characters
        $phone = preg_replace('/[^0-9]/', '', $phone);
        
        // Handle different formats
        if (strlen($phone) === 9 && substr($phone, 0, 1) === '7') {
            // Format: 712345678 -> 254712345678
            return '254' . $phone;
        } elseif (strlen($phone) === 10 && substr($phone, 0, 1) === '0') {
            // Format: 0712345678 -> 254712345678
            return '254' . substr($phone, 1);
        } elseif (strlen($phone) === 12 && substr($phone, 0, 3) === '254') {
            // Format: 254712345678 -> 254712345678 (already correct)
            return $phone;
        } else {
            // Return as is for validation to handle
            return $phone;
        }
    }
    
    public static function validatePhoneNumber($phone) {
        $formatted = self::formatPhoneNumber($phone);
        return preg_match('/^2547\d{8}$/', $formatted);
    }
    
    public static function getDisplayFormat($phone) {
        $formatted = self::formatPhoneNumber($phone);
        if (preg_match('/^2547(\d{8})$/', $formatted, $matches)) {
            return '0' . $matches[1];
        }
        return $phone;
    }
}

/**
 * M-Pesa Integration Class with enhanced logging
 */
class MpesaIntegration {
    private $consumerKey;
    private $consumerSecret;
    private $env;
    private $baseUrl;
    private $callbackUrl;
    private $initiatorName;
    private $securityCredential;
    private $shortCode;
    private $passKey;
    private $logger;

    public function __construct($logger) {
        $this->consumerKey = MPESA_CONSUMER_KEY;
        $this->consumerSecret = MPESA_CONSUMER_SECRET;
        $this->env = MPESA_ENVIRONMENT;
        $this->baseUrl = $this->env === 'sandbox' 
            ? 'https://sandbox.safaricom.co.ke' 
            : 'https://api.safaricom.co.ke';
        $this->callbackUrl = MPESA_CALLBACK_URL;
        $this->initiatorName = MPESA_INITIATOR_NAME;
        $this->securityCredential = $this->generateSecurityCredential();
        $this->shortCode = MPESA_SHORTCODE;
        $this->passKey = MPESA_PASSKEY;
        $this->logger = $logger;
        
        $this->logger->debug('MpesaIntegration initialized', [
            'environment' => $this->env,
            'base_url' => $this->baseUrl,
            'short_code' => $this->shortCode
        ]);
    }

    private function generateSecurityCredential() {
        $certPath = $this->env === 'sandbox'
            ? './certs/SandboxCertificate.cer'
            : './certs/production_cert.cer';
        
        if (!file_exists($certPath)) {
            $this->logger->critical('Certificate file not found', ['cert_path' => $certPath]);
            throw new Exception("Certificate file not found: " . $certPath);
        }
        
        $publicKey = file_get_contents($certPath);
        if (!$publicKey) {
            $this->logger->critical('Failed to read certificate file', ['cert_path' => $certPath]);
            throw new Exception("Failed to read certificate file");
        }
        
        $encrypted = '';
        $success = openssl_public_encrypt(MPESA_INITIATOR_PASSWORD, $encrypted, $publicKey, OPENSSL_PKCS1_PADDING);
        
        if (!$success) {
            $error = openssl_error_string();
            $this->logger->critical('Failed to encrypt security credential', ['error' => $error]);
            throw new Exception("Failed to encrypt security credential: " . $error);
        }
        
        return base64_encode($encrypted);
    }

    private function getAccessToken() {
        $url = $this->baseUrl . '/oauth/v1/generate?grant_type=client_credentials';
        $credentials = base64_encode($this->consumerKey . ':' . $this->consumerSecret);
        
        $headers = ['Authorization: Basic ' . $credentials];

        $curl = curl_init();
        curl_setopt_array($curl, [
            CURLOPT_URL => $url,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER => false,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
            CURLOPT_TIMEOUT => 30
        ]);

        $this->logger->debug('Requesting access token', ['url' => $url]);
        
        $response = curl_exec($curl);
        $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $error = curl_error($curl);
        curl_close($curl);

        if ($status != 200) {
            $this->logger->error('Failed to get access token', [
                'status' => $status, 
                'error' => $error,
                'response' => $response
            ]);
            throw new Exception('Failed to get access token. Status: ' . $status . ' Error: ' . $error);
        }

        $result = json_decode($response);
        if (!$result || !isset($result->access_token)) {
            $this->logger->error('Invalid response from access token request', ['response' => $response]);
            throw new Exception('Invalid response from access token request');
        }
        
        $this->logger->debug('Access token obtained successfully');
        return $result->access_token;
    }

    public function stkPush($phoneNumber, $amount, $accountReference, $transactionDesc) {
        $timestamp = date('YmdHis');
        $password = base64_encode($this->shortCode . $this->passKey . $timestamp);

        $payload = [
            'BusinessShortCode' => $this->shortCode,
            'Password' => $password,
            'Timestamp' => $timestamp,
            'TransactionType' => 'CustomerPayBillOnline',
            'Amount' => $amount,
            'PartyA' => $phoneNumber,
            'PartyB' => $this->shortCode,
            'PhoneNumber' => $phoneNumber,
            'CallBackURL' => $this->callbackUrl . '/stk_callback.php',
            'AccountReference' => $accountReference,
            'TransactionDesc' => $transactionDesc
        ];

        $url = $this->baseUrl . '/mpesa/stkpush/v1/processrequest';
        
        $this->logger->info('Initiating STK push', [
            'phone_number' => $phoneNumber,
            'amount' => $amount,
            'account_reference' => $accountReference,
            'transaction_desc' => $transactionDesc
        ]);
        
        $response = $this->makeApiRequest($url, $payload);
        
        $this->logger->info('STK push response received', ['response' => $response]);
        
        return [
            'MerchantRequestID' => $response['MerchantRequestID'] ?? '',
            'CheckoutRequestID' => $response['CheckoutRequestID'] ?? '',
            'ResponseCode' => $response['ResponseCode'] ?? '0',
            'ResponseDescription' => $response['ResponseDescription'] ?? 'Success. Request accepted for processing',
            'CustomerMessage' => $response['CustomerMessage'] ?? 'Success. Request accepted for processing'
        ];
    }

    private function makeApiRequest($url, $payload) {
        try {
            $token = $this->getAccessToken();
            $headers = [
                'Authorization: Bearer ' . $token,
                'Content-Type: application/json'
            ];

            $curl = curl_init();
            curl_setopt_array($curl, [
            CURLOPT_URL => $url,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
            CURLOPT_TIMEOUT => 30
        ]);

        $this->logger->debug('Making API request', [
            'url' => $url,
            'payload' => $payload
        ]);
        
        $response = curl_exec($curl);
        $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $error = curl_error($curl);
        curl_close($curl);

        if ($status != 200) {
            $this->logger->error('M-Pesa API request failed', [
                'status' => $status, 
                'error' => $error,
                'response' => $response
            ]);
            throw new Exception('M-Pesa API request failed. Status: ' . $status . ' Error: ' . $error);
        }

        $result = json_decode($response, true);
        if (!$result) {
            $this->logger->error('Invalid JSON response from M-Pesa API', ['response' => $response]);
            throw new Exception('Invalid JSON response from M-Pesa API');
        }

        return $result;
        } catch (Exception $e) {
            $this->logger->error('API request exception', [
                'url' => $url,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            throw $e;
        }
    }
}

/**
 * Notification Helper Class
 */
class NotificationHelper {
    public static function setToast(string $type, string $message, string $title = ''): void {
        $_SESSION['toastr'] = [
            'type' => in_array($type, ['success', 'error', 'warning', 'info']) ? $type : 'info',
            'message' => trim($message),
            'title' => trim($title)
        ];
    }

    public static function getToast(): ?array {
        if (empty($_SESSION['toastr'])) {
            return null;
        }
        $toastr = $_SESSION['toastr'];
        unset($_SESSION['toastr']);
        return $toastr;
    }
}

/**
 * Form Helper Class
 */
class FormHelper {
    public static function preserveFormData(array $data): void {
        $_SESSION['form_data'] = $data;
    }

    public static function repopulateFormData(): void {
        if (!empty($_SESSION['form_data'])) {
            foreach ($_SESSION['form_data'] as $key => $value) {
                if (!isset($_POST[$key])) {
                    $_POST[$key] = $value;
                }
            }
            unset($_SESSION['form_data']);
        }
    }
}

/**
 * Redirect Helper Class
 */
class RedirectHelper {
    public static function safeRedirect(string $url): void {
        header("Location: " . filter_var($url, FILTER_SANITIZE_URL));
        exit;
    }
}

/**
 * Database Wrapper Class with logging
 */
class Database {
    private $pdo;
    private $logger;

    public function __construct($pdo, $logger) {
        $this->pdo = $pdo;
        $this->logger = $logger;
    }

    public function fetchAll($sql, $params = []) {
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute($params);
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $this->logger->error('Database fetchAll error', [
                'sql' => $sql,
                'params' => $params,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    public function fetchOne($sql, $params = []) {
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute($params);
            return $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $this->logger->error('Database fetchOne error', [
                'sql' => $sql,
                'params' => $params,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    public function execute($sql, $params = []) {
        try {
            $stmt = $this->pdo->prepare($sql);
            $result = $stmt->execute($params);
            
            if (!$result) {
                $errorInfo = $stmt->errorInfo();
                $this->logger->error('Database execute error', [
                    'sql' => $sql,
                    'params' => $params,
                    'error' => $errorInfo[2]
                ]);
            }
            
            return $result;
        } catch (Exception $e) {
            $this->logger->error('Database execute exception', [
                'sql' => $sql,
                'params' => $params,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    public function beginTransaction() {
        return $this->pdo->beginTransaction();
    }

    public function commit() {
        return $this->pdo->commit();
    }

    public function rollBack() {
        return $this->pdo->rollBack();
    }

    public function lastInsertId() {
        return $this->pdo->lastInsertId();
    }
}

/**
 * M-Pesa Transaction Handler with enhanced logging
 */
class MpesaTransactionHandler {
    private $db;
    private $stkProcessor;
    private $logger;

    public function __construct(Database $db, $stkProcessor = null, $logger) {
        $this->db = $db;
        $this->stkProcessor = $stkProcessor;
        $this->logger = $logger;
    }

    // Get current member details using member_id from session
    public function fetchCurrentMember($memberId) {
        $this->logger->debug('Fetching current member', ['member_id' => $memberId]);
        
        $member = $this->db->fetchOne(
            "SELECT id, first_name, last_name, personal_number, phone_number FROM members WHERE id = ?", 
            [$memberId]
        );
        
        if (!$member) {
            $this->logger->warning('Member not found', ['member_id' => $memberId]);
        } else {
            $this->logger->debug('Member found', ['member' => $member]);
        }
        
        return $member;
    }

    public function fetchAccountTypes() {
        $this->logger->debug('Fetching account types');
        
        $accountTypes = $this->db->fetchAll("SELECT id, account_name, type_code FROM account_types WHERE is_active = 1");
        
        $this->logger->debug('Account types retrieved', ['count' => count($accountTypes)]);
        
        return $accountTypes;
    }

    public function fetchAccountTypeName($accountTypeId) {
        $this->logger->debug('Fetching account type name', ['account_type_id' => $accountTypeId]);
        
        $result = $this->db->fetchOne(
            "SELECT account_name FROM account_types WHERE id = ?", 
            [$accountTypeId]
        );
        
        $accountName = $result ? $result['account_name'] : null;
        
        $this->logger->debug('Account type name retrieved', [
            'account_type_id' => $accountTypeId,
            'account_name' => $accountName
        ]);
        
        return $accountName;
    }
    
    public function getAccountTypeCode($accountTypeId) {
        $this->logger->debug('Fetching account type code', ['account_type_id' => $accountTypeId]);
        
        $result = $this->db->fetchOne(
            "SELECT type_code FROM account_types WHERE id = ?", 
            [$accountTypeId]
        );
        
        $typeCode = $result ? $result['type_code'] : 'SAV';
        
        $this->logger->debug('Account type code retrieved', [
            'account_type_id' => $accountTypeId,
            'type_code' => $typeCode
        ]);
        
        return $typeCode;
    }

    public function recordMpesaTransaction($data) {
        $this->logger->info('Recording M-Pesa transaction', ['data' => $data]);
        
        if (empty($data['checkout_request_id'])) {
            $this->logger->error('checkout_request_id is required', ['data' => $data]);
            throw new Exception("checkout_request_id is required and cannot be null");
        }

        $transactionType = 'STK';
        $transactionTime = date('Y-m-d H:i:s');

        $result = $this->db->execute(
            "INSERT INTO mpesa_transactions (
                checkout_request_id, 
                merchant_request_id,
                transaction_id,
                transaction_type, 
                amount, 
                phone_number,
                account_reference, 
                transaction_time, 
                status, 
                result_code,
                result_desc, 
                raw_data, 
                processed_at, 
                member_id, 
                account_type_id,
                business_short_code
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
            [
                $data['checkout_request_id'],
                $data['merchant_request_id'] ?? null,
                $data['transaction_id'] ?? null,
                $transactionType,
                $data['amount'],
                $data['phone_number'],
                $data['account_reference'],
                $transactionTime,
                $data['status'] ?? 'pending',
                $data['result_code'] ?? null,
                $data['result_desc'] ?? null,
                $data['raw_data'] ?? null,
                $data['processed_at'] ?? null,
                $data['member_id'] ?? null,
                $data['account_type_id'] ?? null,
                $data['business_short_code'] ?? null
            ]
        );
        
        if ($result) {
            $this->logger->info('M-Pesa transaction recorded successfully', [
                'checkout_request_id' => $data['checkout_request_id']
            ]);
        } else {
            $this->logger->error('Failed to record M-Pesa transaction', [
                'checkout_request_id' => $data['checkout_request_id']
            ]);
        }
        
        return $result;
    }

    // New method to process STK callback using the STKPushPaymentProcessor
    public function processSTKCallback($callbackData) {
        $this->logger->info('Processing STK callback', ['callback_data' => $callbackData]);
        
        if (!$this->stkProcessor) {
            $this->logger->error('STK Processor not initialized');
            throw new Exception("STK Processor not initialized");
        }
        
        return $this->stkProcessor->processSTKPush($callbackData);
    }
}
// Initialize classes
try {
    $db = new Database($pdo, $logger);
    $stkProcessor = new STKPushPaymentProcessor($pdo); // Initialize the STK processor
    $mpesaHandler = new MpesaTransactionHandler($db, $stkProcessor, $logger);
    $mpesa = new MpesaIntegration($logger);
} catch (Exception $e) {
    $logger->critical('Failed to initialize classes', ['error' => $e->getMessage()]);
    die('System initialization error. Please try again later.');
}

// Get current member details using member_id from session
try {
    $currentMember = $mpesaHandler->fetchCurrentMember($_SESSION['member_id']);
    if (!$currentMember) {
        $logger->critical('Member profile not found', ['member_id' => $_SESSION['member_id']]);
        NotificationHelper::setToast('error', 'Member profile not found', 'Error');
        
        // Clear invalid session and redirect to login
        unset($_SESSION['member_id']);
        header("Location: login.php");
        exit;
    }
} catch (Exception $e) {
    $logger->critical('Error fetching member details', [
        'error' => $e->getMessage(),
        'member_id' => $_SESSION['member_id']
    ]);
    die('Error loading member information. Please try again later.');
}

// Handle AJAX STK Push request
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
    $logger->info('POST request received', [
        'action' => $_POST['action'],
        'post_data' => $_POST,
        'session_id' => session_id()
    ]);
    
    if ($_POST['action'] === 'stk_push') {
        header('Content-Type: application/json');
        
        try {
            $logger->debug('Processing STK push request');
            
            if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
                $logger->warning('Invalid CSRF token', [
                    'provided_token' => $_POST['csrf_token'] ?? 'missing',
                    'expected_token' => $_SESSION['csrf_token'],
                    'session_id' => session_id()
                ]);
                throw new Exception("Invalid CSRF token");
            }

            $required = ['account_type_id', 'amount', 'phone'];
            foreach ($required as $field) {
                if (empty($_POST[$field])) {
                    $logger->warning('Missing required field', ['field' => $field]);
                    throw new Exception("$field is required");
                }
            }
            
            $amount = filter_var($_POST['amount'], FILTER_VALIDATE_FLOAT);
            if ($amount === false || $amount <= 0) {
                $logger->warning('Invalid amount', ['amount' => $_POST['amount']]);
                throw new Exception("Invalid amount");
            }
            
            $phone = $_POST['phone'];
            if (!PhoneNumberFormatter::validatePhoneNumber($phone)) {
                $logger->warning('Invalid phone number format', ['phone' => $phone]);
                throw new Exception("Invalid phone number format. Use formats like: 0727576400, 254727576400, +254727576400, or 727576400");
            }
            
            $formattedPhone = PhoneNumberFormatter::formatPhoneNumber($phone);
            
            // Get account type name
            $accountName = $mpesaHandler->fetchAccountTypeName($_POST['account_type_id']);
            if (!$accountName) {
                $logger->warning('Account type not found', ['account_type_id' => $_POST['account_type_id']]);
                throw new Exception("Account type not found");
            }

            // Create proper account reference format for the STK processor
            $accountTypeCode = $mpesaHandler->getAccountTypeCode($_POST['account_type_id']);
            $reference = $currentMember['personal_number'] . '-' . $accountTypeCode . '-1'; // Default sub-account code
            
            $description = $accountName . " payment by " . $currentMember['first_name'];
            
            $response = $mpesa->stkPush($formattedPhone, $amount, $reference, $description);
            
            $mpesaHandler->recordMpesaTransaction([
                'merchant_request_id' => $response['MerchantRequestID'],
                'checkout_request_id' => $response['CheckoutRequestID'],
                'amount' => $amount,
                'phone_number' => $formattedPhone,
                'account_reference' => $reference,
                'result_desc' => $description,
                'member_id' => $currentMember['id'],
                'account_type_id' => $_POST['account_type_id'],
                'raw_data' => json_encode($response),
                'status' => 'pending',
                'business_short_code' => MPESA_SHORTCODE
            ]);
            
            $logger->info('STK push initiated successfully', [
                'merchant_request_id' => $response['MerchantRequestID'],
                'checkout_request_id' => $response['CheckoutRequestID'],
                'session_id' => session_id()
            ]);
            
            echo json_encode([
                'status' => 'success',
                'message' => 'Payment request initiated successfully',
                'mpesa_response' => $response,
                'user_reference' => $reference
            ]);
        } catch (Exception $e) {
            $logger->error('STK push failed', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'session_id' => session_id()
            ]);
            
            http_response_code(400);
            echo json_encode([
                'status' => 'error',
                'message' => $e->getMessage()
            ]);
        }
        exit;
    }
}

// Fetch data for the form
try {
    $accountTypes = $mpesaHandler->fetchAccountTypes();
} catch (Exception $e) {
    $logger->error('Failed to fetch account types', ['error' => $e->getMessage()]);
    $accountTypes = [];
}

// Fetch recent transactions for the current member only
try {
    $recentTransactions = $db->fetchAll(
        "SELECT mt.*, m.first_name, m.last_name, at.account_name 
         FROM mpesa_transactions mt
         LEFT JOIN members m ON mt.member_id = m.id
         LEFT JOIN account_types at ON mt.account_type_id = at.id
         WHERE mt.member_id = ?
         ORDER BY mt.created_at DESC 
         LIMIT 5",
        [$currentMember['id']]
    );
    $logger->debug('Recent transactions fetched', [
        'count' => count($recentTransactions),
        'session_id' => session_id()
    ]);
} catch (Exception $e) {
    $logger->error('Failed to fetch recent transactions', ['error' => $e->getMessage()]);
    $recentTransactions = [];
}

// Get stats for the current member
try {
    $total = $db->fetchOne("SELECT SUM(amount) as total FROM mpesa_transactions WHERE status = 'completed' AND member_id = ?", [$currentMember['id']]);
    $completed = $db->fetchOne("SELECT COUNT(*) as count FROM mpesa_transactions WHERE status = 'completed' AND member_id = ?", [$currentMember['id']]);
    $pending = $db->fetchOne("SELECT COUNT(*) as count FROM mpesa_transactions WHERE status = 'pending' AND member_id = ?", [$currentMember['id']]);
    $failed = $db->fetchOne("SELECT COUNT(*) as count FROM mpesa_transactions WHERE status = 'failed' AND member_id = ?", [$currentMember['id']]);

    $logger->debug('Transaction stats calculated', [
        'total' => $total['total'] ?? 0,
        'completed' => $completed['count'] ?? 0,
        'pending' => $pending['count'] ?? 0,
        'failed' => $failed['count'] ?? 0,
        'session_id' => session_id()
    ]);
} catch (Exception $e) {
    $logger->error('Failed to calculate transaction stats', ['error' => $e->getMessage()]);
    $total = ['total' => 0];
    $completed = ['count' => 0];
    $pending = ['count' => 0];
    $failed = ['count' => 0];
}

// Repopulate form on error
FormHelper::repopulateFormData();

// Generate CSRF token if not set
if (!isset($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    $logger->debug('New CSRF token generated', ['session_id' => session_id()]);
}

// Set session backup cookie for recovery
$sessionBackup = base64_encode(json_encode([
    'member_id' => $_SESSION['member_id'],
    'created' => $_SESSION['created']
]));
setcookie('member_session_data', $sessionBackup, time() + 3600, '/', '', true, true);

$logger->info('Page loaded successfully', [
    'member_id' => $_SESSION['member_id'],
    'session_id' => session_id(),
    'script_name' => $_SERVER['PHP_SELF']
]);

// DEBUG: Final check to ensure we're not redirecting
if (basename($_SERVER['PHP_SELF']) === 'login.php' && isset($_SESSION['member_id'])) {
    $logger->warning('On login page but session has member_id, redirecting to dashboard', [
        'session_id' => session_id()
    ]);
    header("Location: member_dashboard.php");
    exit;
}

// DEBUG: Check for session ID consistency
if (isset($_COOKIE[session_name()]) && $_COOKIE[session_name()] !== session_id()) {
    $logger->critical('Session ID inconsistency detected', [
        'cookie_session_id' => $_COOKIE[session_name()],
        'current_session_id' => session_id()
    ]);
    
    // Attempt to fix the session ID inconsistency
    if (setcookie(session_name(), session_id(), time() + 86400, '/', $_SERVER['HTTP_HOST'], true, true)) {
        $logger->info('Session ID cookie corrected');
    } else {
        $logger->error('Failed to correct session ID cookie');
    }
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php echo htmlspecialchars($title); ?> - SACCO System</title>
    <link rel="stylesheet" href="./assets/css/bootstrap.min.css">
    <link rel="stylesheet" href="./assets/css/toastr.min.css">
    <link rel="stylesheet" href="./assets/css/font-awesome.min.css">
    <link rel="stylesheet" href="./assets/css/styles.css">
    <style>
        :root {
            --primary-color: #4e73df;
            --secondary-color: #6f42c1;
            --success-color: #1cc88a;
            --info-color: #36b9cc;
            --warning-color: #f6c23e;
            --danger-color: #e74a3b;
            --light-bg: #f8f9fc;
            --card-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            --transition: all 0.3s ease;
        }
        
        body {
            background-color: #f8f9fc;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
        }
        
        .main-container {
            padding: 20px;
            max-width: 1400px;
            margin: 0 auto;
        }
        
        /* Improved Loading Overlay */
        .loading-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.7);
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 9999;
            color: white;
            display: none;
        }
        
        .loading-content {
            text-align: center;
            background: white;
            padding: 30px;
            border-radius: 10px;
            color: #333;
            box-shadow: var(--card-shadow);
        }
        
        .spinner-border {
            width: 3rem;
            height: 3rem;
        }
        
        /* Enhanced Cards */
        .card {
            border: none;
            border-radius: 10px;
            box-shadow: var(--card-shadow);
            transition: var(--transition);
            margin-bottom: 20px;
        }
        
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
        }
        
        .card-header {
            background-color: white;
            border-bottom: 1px solid #e3e6f0;
            padding: 15px 20px;
            border-radius: 10px 10px 0 0 !important;
        }
        
        .card-title {
            color: #4e73df;
            font-weight: 600;
            margin: 0;
        }
        
        /* Enhanced Member Info Section */
        .member-info {
            background: linear-gradient(135deg, #4e73df 0%, #6f42c1 100%);
            color: white;
            border-radius: 10px;
            padding: 20px;
            margin-bottom: 25px;
            box-shadow: var(--card-shadow);
        }
        
        .member-info h5 {
            margin-bottom: 15px;
            font-weight: 600;
        }
        
        .member-details {
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
        }
        
        .member-detail {
            display: flex;
            flex-direction: column;
        }
        
        .member-detail strong {
            font-size: 0.85rem;
            opacity: 0.8;
            margin-bottom: 5px;
        }
        
        /* Stats Cards */
        .stats-card {
            text-align: center;
            padding: 20px;
            height: 100%;
            border-left: 4px solid var(--primary-color);
        }
        
        .stats-card:nth-child(2) {
            border-left-color: var(--success-color);
        }
        
        .stats-card:nth-child(3) {
            border-left-color: var(--warning-color);
        }
        
        .stats-card:nth-child(4) {
            border-left-color: var(--danger-color);
        }
        
        .stats-icon {
            font-size: 2rem;
            margin-bottom: 10px;
            color: var(--primary-color);
        }
        
        .stats-card:nth-child(2) .stats-icon {
            color: var(--success-color);
        }
        
        .stats-card:nth-child(3) .stats-icon {
            color: var(--warning-color);
        }
        
        .stats-card:nth-child(4) .stats-icon {
            color: var(--danger-color);
        }
        
        .stats-number {
            font-size: 1.8rem;
            font-weight: 700;
            margin-bottom: 5px;
        }
        
        .stats-label {
            color: #6c757d;
            font-size: 0.9rem;
        }
        
        /* Form Improvements */
        .form-label {
            font-weight: 600;
            margin-bottom: 8px;
            color: #5a5c69;
        }
        
        .form-control, .form-select {
            border-radius: 8px;
            padding: 10px 15px;
            border: 1px solid #d1d3e2;
            transition: var(--transition);
        }
        
        .form-control:focus, .form-select:focus {
            border-color: var(--primary-color);
            box-shadow: 0 0 0 0.2rem rgba(78, 115, 223, 0.25);
        }
        
        .input-group-text {
            background-color: #f8f9fc;
            border: 1px solid #d1d3e2;
        }
        
        .phone-examples {
            font-size: 0.8rem;
            color: #6c757d;
            margin-top: 5px;
        }
        
        /* Buttons */
        .btn {
            border-radius: 8px;
            padding: 10px 20px;
            font-weight: 600;
            transition: var(--transition);
        }
        
        .btn-primary {
            background-color: var(--primary-color);
            border-color: var(--primary-color);
        }
        
        .btn-primary:hover {
            background-color: #3a5ccc;
            border-color: #3a5ccc;
            transform: translateY(-2px);
        }
        
        /* Transaction History */
        .transaction-item {
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 10px;
            border-left: 4px solid #e3e6f0;
            transition: var(--transition);
        }
        
        .transaction-item:hover {
            background-color: #f8f9fc;
        }
        
        .transaction-item.success {
            border-left-color: var(--success-color);
        }
        
        .transaction-item.pending {
            border-left-color: var(--warning-color);
        }
        
        .transaction-item.failed {
            border-left-color: var(--danger-color);
        }
        
        /* Instructions */
        .list-group-item {
            border: none;
            padding: 15px;
            margin-bottom: 10px;
            border-radius: 8px !important;
            background-color: #f8f9fc;
            transition: var(--transition);
        }
        
        .list-group-item:hover {
            background-color: #e9ecef;
        }
        
        /* Progress Steps */
        .progress-steps {
            display: flex;
            justify-content: space-between;
            margin: 30px 0;
            position: relative;
        }
        
        .progress-steps::before {
            content: '';
            position: absolute;
            top: 20px;
            left: 0;
            right: 0;
            height: 3px;
            background-color: #e3e6f0;
            z-index: 1;
        }
        
        .progress-step {
            display: flex;
            flex-direction: column;
            align-items: center;
            position: relative;
            z-index: 2;
        }
        
        .step-icon {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            background-color: #e3e6f0;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-bottom: 10px;
            color: #6c757d;
            font-weight: bold;
        }
        
        .step-label {
            font-size: 0.85rem;
            text-align: center;
            color: #6c757d;
        }
        
        .progress-step.active .step-icon {
            background-color: var(--primary-color);
            color: white;
        }
        
        .progress-step.active .step-label {
            color: var(--primary-color);
            font-weight: 600;
        }
        
        /* Responsive Design */
        @media (max-width: 768px) {
            .main-container {
                padding: 15px;
            }
            
            .member-details {
                flex-direction: column;
                gap: 10px;
            }
            
            .progress-steps {
                flex-wrap: wrap;
                gap: 15px;
            }
            
            .progress-steps::before {
                display: none;
            }
            
            .card-body {
                padding: 15px;
            }
        }
        
        /* Animation for form submission */
        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }
        
        .pulse {
            animation: pulse 1s infinite;
        }
        
        /* Enhanced Modal */
        .modal-content {
            border-radius: 10px;
            border: none;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
        }
        
        .modal-header {
            border-bottom: 1px solid #e3e6f0;
            padding: 20px;
        }
        
        .modal-body {
            padding: 20px;
        }
        
        .modal-footer {
            border-top: 1px solid #e3e6f0;
            padding: 15px 20px;
        }
        
        /* Success Animation */
        .success-animation {
            text-align: center;
            margin: 20px 0;
        }
        
        .checkmark {
            width: 80px;
            height: 80px;
            border-radius: 50%;
            display: block;
            stroke-width: 2;
            stroke: #4bb71b;
            stroke-miterlimit: 10;
            margin: 0 auto;
            box-shadow: inset 0px 0px 0px #4bb71b;
            animation: fill .4s ease-in-out .4s forwards, scale .3s ease-in-out .9s both;
        }
        
        .checkmark__circle {
            stroke-dasharray: 166;
            stroke-dashoffset: 166;
            stroke-width: 2;
            stroke-miterlimit: 10;
            stroke: #4bb71b;
            fill: none;
            animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
        }
        
        .checkmark__check {
            transform-origin: 50% 50%;
            stroke-dasharray: 48;
            stroke-dashoffset: 48;
            animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
        }
        
        @keyframes stroke {
            100% {
                stroke-dashoffset: 0;
            }
        }
        
        @keyframes scale {
            0%, 100% {
                transform: none;
            }
            50% {
                transform: scale3d(1.1, 1.1, 1);
            }
        }
        
        @keyframes fill {
            100% {
                box-shadow: inset 0px 0px 0px 30px #4bb71b;
            }
        }
    </style>
</head>
<body>
    <!-- Enhanced Loading Overlay -->
    <div class="loading-overlay" id="loadingOverlay">
        <div class="loading-content">
            <div class="spinner-border text-primary" role="status">
                <span class="visually-hidden">Loading...</span>
            </div>
            <p class="mt-3">Processing payment request...</p>
            <div class="progress mt-2" style="height: 5px; width: 200px;">
                <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 100%"></div>
            </div>
        </div>
    </div>
    
    <?php include './partials/layouts/layoutTop.php'; ?>
    
    <div class="container-fluid main-container">
        <?php
        $toast = NotificationHelper::getToast();
        if ($toast): ?>
            <div class="alert alert-<?php echo htmlspecialchars($toast['type']); ?> alert-dismissible fade show">
                <strong><?php echo htmlspecialchars($toast['title']); ?></strong>
                <?php echo htmlspecialchars($toast['message']); ?>
                <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
            </div>
        <?php endif; ?>
        
        <!-- Enhanced Member Information Section -->
        <div class="member-info">
            <h5><i class="fa fa-user"></i> Member Information</h5>
            <div class="member-details">
                <div class="member-detail">
                    <strong>Name</strong>
                    <span><?php echo htmlspecialchars($currentMember['first_name'] . ' ' . $currentMember['last_name']); ?></span>
                </div>
                <div class="member-detail">
                    <strong>Member ID</strong>
                    <span><?php echo htmlspecialchars($currentMember['personal_number']); ?></span>
                </div>
                <div class="member-detail">
                    <strong>Phone Number</strong>
                    <span><?php echo !empty($currentMember['phone_number']) ? htmlspecialchars(PhoneNumberFormatter::getDisplayFormat($currentMember['phone_number'])) : 'Not set'; ?></span>
                </div>
            </div>
        </div>
        
        <!-- Payment Progress Steps -->
        <div class="card">
            <div class="card-body">
                <h5 class="card-title mb-4">Payment Process</h5>
                <div class="progress-steps">
                    <div class="progress-step active" id="step1">
                        <div class="step-icon">1</div>
                        <div class="step-label">Enter Details</div>
                    </div>
                    <div class="progress-step" id="step2">
                        <div class="step-icon">2</div>
                        <div class="step-label">Confirm Payment</div>
                    </div>
                    <div class="progress-step" id="step3">
                        <div class="step-icon">3</div>
                        <div class="step-label">Process Payment</div>
                    </div>
                    <div class="progress-step" id="step4">
                        <div class="step-icon">4</div>
                        <div class="step-label">Complete</div>
                    </div>
                </div>
            </div>
        </div>
        
        <div class="row">
            <!-- Stats Cards for current member only -->
            <div class="col-xl-3 col-md-6 mb-4">
                <div class="card stats-card">
                    <div class="stats-icon">
                        <i class="fa fa-money"></i>
                    </div>
                    <div class="stats-number">KES <?php
                        echo number_format($total['total'] ?? 0, 2);
                    ?></div>
                    <div class="stats-label">My Total Payments</div>
                </div>
            </div>
            
            <div class="col-xl-3 col-md-6 mb-4">
                <div class="card stats-card">
                    <div class="stats-icon text-success">
                        <i class="fa fa-check-circle"></i>
                    </div>
                    <div class="stats-number"><?php
                        echo $completed['count'] ?? 0;
                    ?></div>
                    <div class="stats-label">Completed</div>
                </div>
            </div>
            
            <div class="col-xl-3 col-md-6 mb-4">
                <div class="card stats-card">
                    <div class="stats-icon text-warning">
                        <i class="fa fa-clock-o"></i>
                    </div>
                    <div class="stats-number"><?php
                        echo $pending['count'] ?? 0;
                    ?></div>
                    <div class="stats-label">Pending</div>
                </div>
            </div>
            
            <div class="col-xl-3 col-md-6 mb-4">
                <div class="card stats-card">
                    <div class="stats-icon text-danger">
                        <i class="fa fa-times-circle"></i>
                    </div>
                    <div class="stats-number"><?php
                        echo $failed['count'] ?? 0;
                    ?></div>
                    <div class="stats-label">Failed</div>
                </div>
            </div>
        </div>
        
        <div class="row">
            <div class="col-lg-8">
                <div class="card">
                    <div class="card-header">
                        <h5 class="card-title mb-0"><i class="fa fa-mobile"></i> Initiate M-Pesa Payment</h5>
                    </div>
                    <div class="card-body">
                        <form method="post" id="mpesaForm" autocomplete="off">
                            <input type="hidden" name="action" value="stk_push">
                            <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
                            
                            <div class="row mb-3">
                                <div class="col-md-6">
                                    <label for="account_type_id" class="form-label">Account Type</label>
                                    <select class="form-select" id="account_type_id" name="account_type_id" required>
                                        <option value="">Select Account Type</option>
                                        <?php foreach ($accountTypes as $type): ?>
                                            <option value="<?php echo $type['id']; ?>" <?php echo isset($_POST['account_type_id']) && $_POST['account_type_id'] == $type['id'] ? 'selected' : ''; ?>>
                                                <?php echo htmlspecialchars($type['account_name']); ?>
                                            </option>
                                        <?php endforeach; ?>
                                    </select>
                                </div>
                                <div class="col-md-6">
                                    <label for="amount" class="form-label">Amount (KES)</label>
                                    <div class="input-group">
                                        <span class="input-group-text">KES</span>
                                        <input type="number" class="form-control" id="amount" name="amount" 
                                               min="1" step="1" required 
                                               value="<?php echo htmlspecialchars($_POST['amount'] ?? ''); ?>">
                                    </div>
                                    <small class="text-muted">Minimum amount: KES 1</small>
                                </div>
                            </div>
                            
                            <div class="row mb-3">
                                <div class="col-md-6">
                                    <label for="phone" class="form-label">Phone Number</label>
                                    <input type="text" class="form-control" id="phone" name="phone" 
                                           required 
                                           value="<?php echo !empty($currentMember['phone_number']) ? htmlspecialchars(PhoneNumberFormatter::getDisplayFormat($currentMember['phone_number'])) : htmlspecialchars($_POST['phone'] ?? ''); ?>"
                                           placeholder="0727576400, 254727576400, etc.">
                                    <small id="phoneHelp" class="form-text">
                                        Accepts formats: 0727576400, 254727576400, +254727576400, 727576400
                                    </small>
                                    <div class="phone-examples">
                                        Examples: 0727576400, 254727576400, +254727576400, 727576400
                                    </div>
                                </div>
                                <div class="col-md-6">
                                    <label for="description" class="form-label">Payment Description</label>
                                    <textarea class="form-control" id="description" name="description" rows="2"><?php 
                                        echo htmlspecialchars($_POST['description'] ?? 'M-Pesa Payment'); 
                                    ?></textarea>
                                </div>
                            </div>
                            
                            <div class="d-grid gap-2 d-md-flex justify-content-md-end mt-4">
                                <button type="reset" class="btn btn-outline-secondary me-md-2">
                                    <i class="fa fa-undo"></i> Reset
                                </button>
                                <button type="submit" class="btn btn-primary" id="submitBtn">
                                    <i class="fa fa-paper-plane"></i> Initiate Payment
                                </button>
                            </div>
                        </form>
                    </div>
                </div>
                
                <!-- Recent Transactions for current member -->
                <div class="card mt-4">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <h5 class="card-title mb-0"><i class="fa fa-history"></i> My Recent Transactions</h5>
                        <button class="btn btn-sm btn-outline-primary" id="refreshBtn">
                            <i class="fa fa-refresh"></i> Refresh
                        </button>
                    </div>
                    <div class="card-body">
                        <div class="transaction-history">
                            <?php if (empty($recentTransactions)): ?>
                                <div class="alert alert-info">
                                    <i class="fa fa-info-circle"></i> No transactions found.
                                </div>
                            <?php else: ?>
                                <?php foreach ($recentTransactions as $transaction): 
                                    $statusClass = '';
                                    if ($transaction['status'] === 'completed') {
                                        $statusClass = 'success';
                                    } elseif ($transaction['status'] === 'failed') {
                                        $statusClass = 'failed';
                                    } elseif ($transaction['status'] === 'pending') {
                                        $statusClass = 'pending';
                                    }
                                ?>
                                    <div class="transaction-item <?php echo $statusClass; ?>">
                                        <div class="d-flex justify-content-between">
                                            <div>
                                                <strong>KES <?php echo number_format($transaction['amount'], 2); ?></strong>
                                                <div class="text-muted small"><?php echo htmlspecialchars($transaction['account_name']); ?></div>
                                            </div>
                                            <div class="text-end">
                                                <span class="badge bg-<?php 
                                                    echo $transaction['status'] === 'completed' ? 'success' : 
                                                         ($transaction['status'] === 'pending' ? 'warning' : 'danger'); 
                                                ?>">
                                                    <?php echo ucfirst($transaction['status']); ?>
                                                </span>
                                                <div class="text-muted small">
                                                    <?php echo date('M j, Y g:i A', strtotime($transaction['created_at'])); ?>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                <?php endforeach; ?>
                            <?php endif; ?>
                        </div>
                    </div>
                </div>
            </div>
            
            <div class="col-lg-4">
                <!-- Instructions Card -->
                <div class="card">
                    <div class="card-header">
                        <h5 class="card-title mb-0"><i class="fa fa-info-circle"></i> Payment Instructions</h5>
                    </div>
                    <div class="card-body">
                        <ol class="list-group list-group-numbered">
                            <li class="list-group-item d-flex justify-content-between align-items-start">
                                <div class="ms-2 me-auto">
                                    <div class="fw-bold">Enter Amount</div>
                                    Minimum KES 1 required
                                </div>
                            </li>
                            <li class="list-group-item d-flex justify-content-between align-items-start">
                                <div class="ms-2 me-auto">
                                    <div class="fw-bold">Provide Phone</div>
                                    Multiple formats accepted
                                </div>
                            </li>
                            <li class="list-group-item d-flex justify-content-between align-items-start">
                                <div class="ms-2 me-auto">
                                    <div class="fw-bold">Check Phone</div>
                                    You'll receive STK push prompt
                                </div>
                            </li>
                            <li class="list-group-item d-flex justify-content-between align-items-start">
                                <div class="ms-2 me-auto">
                                    <div class="fw-bold">Enter PIN</div>
                                    Complete payment on your phone
                                </div>
                            </li>
                        </ol>
                        <div class="alert alert-warning mt-3">
                            <i class="fa fa-exclamation-triangle"></i> <strong>Note:</strong> Transactions may take a few moments to process.
                        </div>
                    </div>
                </div>
                
                <!-- Status Chart for current member -->
                <div class="card mt-4">
                    <div class="card-header">
                        <h5 class="card-title mb-0"><i class="fa fa-pie-chart"></i> My Payment Status</h5>
                    </div>
                    <div class="card-body">
                        <canvas id="statusChart" height="250"></canvas>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Enhanced Response Modal -->
    <div class="modal fade" id="responseModal" tabindex="-1" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Payment Response</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <div class="success-animation" id="successAnimation" style="display: none;">
                        <svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
                            <circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none"/>
                            <path class="checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/>
                        </svg>
                        <h4 class="mt-3 text-success">Payment Initiated Successfully!</h4>
                    </div>
                    <div class="alert" id="responseAlert">
                        <div id="responseMessage"></div>
                    </div>
                    <div class="mt-3">
                        <h6>Reference Number:</h6>
                        <code id="responseReference" class="bg-light p-2 rounded d-block"></code>
                    </div>
                    <div class="mt-3">
                        <h6>Transaction Details:</h6>
                        <div id="responseDetails" class="bg-light p-3 rounded" style="max-height: 200px; overflow-y: auto;"></div>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                    <button type="button" class="btn btn-primary" id="viewTransactionsBtn">View Transactions</button>
                </div>
            </div>
        </div>
    </div>

    <script src="./assets/js/jquery-3.6.0.min.js"></script>
    <script src="./assets/js/bootstrap.bundle.min.js"></script>
    <script src="./assets/js/toastr.min.js"></script>
    <script src="./assets/js/chart.min.js"></script>
    <script>
        $(document).ready(function() {
            toastr.options = {
                "closeButton": true,
                "progressBar": true,
                "positionClass": "toast-top-right",
                "timeOut": "5000"
            };
            
            // Initialize status chart for current member
            var ctx = document.getElementById('statusChart').getContext('2d');
            var statusChart = new Chart(ctx, {
                type: 'doughnut',
                data: {
                    labels: ['Completed', 'Pending', 'Failed'],
                    datasets: [{
                        data: [
                            <?php echo $completed['count'] ?? 0; ?>,
                            <?php echo $pending['count'] ?? 0; ?>,
                            <?php echo $failed['count'] ?? 0; ?>
                        ],
                        backgroundColor: [
                            '#1cc88a',
                            '#f6c23e',
                            '#e74a3b'
                        ],
                        hoverBackgroundColor: [
                            '#17a673',
                            '#dda20a',
                            '#be2617'
                        ],
                        hoverBorderColor: "rgba(234, 236, 244, 1)",
                    }],
                },
                options: {
                    maintainAspectRatio: false,
                    cutout: '70%',
                    plugins: {
                        legend: {
                            position: 'bottom',
                            labels: {
                                usePointStyle: true,
                                padding: 20
                            }
                        }
                    }
                }
            });
            
            // Form validation and submission
            $('#mpesaForm').submit(function(e) {
                e.preventDefault();
                
                const amount = parseFloat($('#amount').val());
                const phone = $('#phone').val();
                const accountType = $('#account_type_id').val();
                
                // Validate form
                if (!accountType) {
                    toastr.error('Please select an account type');
                    $('#account_type_id').focus();
                    return false;
                }
                
                if (amount < 1) {
                    toastr.error('Minimum payment amount is KES 1');
                    $('#amount').focus();
                    return false;
                }
                
                // Validate phone format
                const phoneRegex = /^(\+?254|0|254)?[17]\d{8}$/;
                if (!phoneRegex.test(phone)) {
                    toastr.error('Invalid phone number format. Use formats like: 0712345678, 254712345678, +25412345678, or 7212345678');
                    $('#phone').focus();
                    return false;
                }
                
                // Update progress steps
                updateProgressSteps(2);
                
                // Show loading overlay
                $('#loadingOverlay').show();
                $('#submitBtn').prop('disabled', true).addClass('pulse');
                
                toastr.info('Initiating M-Pesa payment request...', 'Processing');
                
                $.ajax({
                    url: window.location.href,
                    type: 'POST',
                    data: $(this).serialize(),
                    dataType: 'json',
                    success: function(response) {
                        $('#loadingOverlay').hide();
                        $('#submitBtn').prop('disabled', false).removeClass('pulse');
                        
                        if (response.status === 'success') {
                            updateProgressSteps(4);
                            toastr.success(response.message, 'Success');
                            
                            // Update response modal
                            $('#successAnimation').show();
                            $('#responseMessage').text('Payment request initiated successfully! Check your phone for the M-Pesa prompt.');
                            $('#responseAlert').removeClass('alert-info alert-danger').addClass('alert-success');
                            $('#responseReference').text(response.user_reference);
                            
                            // Format response details
                            const mpesaResponse = response.mpesa_response;
                            let detailsHtml = `
                                <div><strong>Merchant Request ID:</strong> ${mpesaResponse.MerchantRequestID || 'N/A'}</div>
                                <div><strong>Checkout Request ID:</strong> ${mpesaResponse.CheckoutRequestID || 'N/A'}</div>
                                <div><strong>Response Code:</strong> ${mpesaResponse.ResponseCode || 'N/A'}</div>
                                <div><strong>Response Description:</strong> ${mpesaResponse.ResponseDescription || 'N/A'}</div>
                                <div><strong>Customer Message:</strong> ${mpesaResponse.CustomerMessage || 'N/A'}</div>
                            `;
                            $('#responseDetails').html(detailsHtml);
                            
                            $('#responseModal').modal('show');
                            
                            // Reset form
                            $('#mpesaForm')[0].reset();
                            
                            // Refresh page data after a successful transaction
                            setTimeout(function() {
                                $('#refreshBtn').click();
                            }, 3000);
                        } else {
                            updateProgressSteps(1);
                            toastr.error(response.message, 'Error');
                        }
                    },
                    error: function(xhr) {
                        $('#loadingOverlay').hide();
                        $('#submitBtn').prop('disabled', false).removeClass('pulse');
                        updateProgressSteps(1);
                        
                        try {
                            const response = JSON.parse(xhr.responseText);
                            toastr.error(response.message, 'Error');
                        } catch (e) {
                            toastr.error('An unexpected error occurred', 'Error');
                        }
                    }
                });
            });
            
            // Update progress steps
            function updateProgressSteps(step) {
                // Reset all steps
                $('.progress-step').removeClass('active');
                
                // Activate steps up to the current one
                for (let i = 1; i <= step; i++) {
                    $('#step' + i).addClass('active');
                }
            }
            
            // Phone number formatting
            $('#phone').on('input', function() {
                // Remove any non-digit characters except plus sign
                let value = $(this).val().replace(/[^0-9+]/g, '');
                $(this).val(value);
            });
            
            // Auto-format phone number on blur
            $('#phone').on('blur', function() {
                let phone = $(this).val();
                if (phone) {
                    // Format to standard Kenyan format
                    phone = phone.replace(/\s+/g, ''); // Remove spaces
                    
                    if (phone.startsWith('+254')) {
                        phone = phone.substring(1); // Remove + to become 254...
                    } else if (phone.startsWith('0') && phone.length === 10) {
                        phone = '254' + phone.substring(1); // Convert 07... to 2547...
                    } else if (phone.length === 9 && !phone.startsWith('0')) {
                        phone = '254' + phone; // Convert 7... to 2547...
                    }
                    
                    $(this).val(phone);
                }
            });
            
            // Refresh page data
            $('#refreshBtn').click(function() {
                $(this).prop('disabled', true).html('<i class="fa fa-refresh fa-spin"></i> Refreshing...');
                location.reload();
            });
            
            // View transactions button in modal
            $('#viewTransactionsBtn').click(function() {
                $('#responseModal').modal('hide');
                // Scroll to transactions section
                $('html, body').animate({
                    scrollTop: $('.transaction-history').offset().top - 100
                }, 500);
            });
            
            // Session keep-alive for long-running processes
            setInterval(function() {
                $.get('./session_keepalive.php').fail(function() {
                    toastr.error('Session expired. Please refresh the page.', 'Session Error');
                    setTimeout(function() {
                        window.location.href = 'login.php';
                    }, 2000);
                });
            }, 300000); // Ping every 5 minutes
            
            // Initialize progress steps
            updateProgressSteps(1);
        });
    </script>
</body>
<?php include './partials/layouts/layoutBottom.php'; ?>
</html>