<?php

/**
 * Cart Session Manager - PayPal v1 Session Fix
 * 
 * Eliminates session dependency during PayPal redirects by storing
 * cart data in database with PayPal token as key.
 * 
 * Compatible with existing Legacy System and future PayPal v2 integration.
 * 
 * @author PFC Claude
 * @version 1.0
 * @date 2025
 */

class CartSessionManager {
    
    private $db;
    private $base_object;
    private $log_file;
    
    public function __construct($base_object) {
        $this->base_object = $base_object;
        $this->db = $base_object->db;
        
        // Dedicated PayPal log file - easier than Plesk chaos!
        $this->log_file = $_SERVER['DOCUMENT_ROOT'] . '/logs/paypal_session_fix.log';
        
        // Ensure log directory exists
        $log_dir = dirname($this->log_file);
        if (!file_exists($log_dir)) {
            mkdir($log_dir, 0755, true);
        }
    }
    
    /**
     * Store cart data in database before PayPal redirect
     * 
     * @param string $session_key - PayPal token or session_id
     * @param array $cart_data - Complete cart contents
     * @param string $payment_provider - 'paypal', 'stripe', etc.
     * @return bool Success/failure
     */
    public function storeCartSession($session_key, $cart_data, $payment_provider = 'paypal') {
        $session_key_clean = $this->db->real_escape_string($session_key);
        $cart_json = $this->db->real_escape_string(json_encode($cart_data));
        $provider_clean = $this->db->real_escape_string($payment_provider);
        $user_agent = $this->db->real_escape_string($_SERVER['HTTP_USER_AGENT'] ?? '');
        $ip_address = $this->db->real_escape_string($_SERVER['REMOTE_ADDR'] ?? '');
        
        $query = "
            INSERT INTO cart_sessions (
                session_key, 
                cart_data, 
                payment_provider, 
                status, 
                user_agent, 
                ip_address
            ) VALUES (
                '{$session_key_clean}',
                '{$cart_json}',
                '{$provider_clean}',
                'active',
                '{$user_agent}',
                '{$ip_address}'
            ) ON DUPLICATE KEY UPDATE
                cart_data = VALUES(cart_data),
                updated_at = CURRENT_TIMESTAMP,
                status = 'active'
        ";
        
        $result = $this->db->query($query);
        
        if ($this->db->error) {
            $this->writePayPalLog("STORE_ERROR", "Database error: " . $this->db->error);
            return false;
        }
        
        // Dedicated PayPal logging - no more Plesk chaos!
        $this->writePayPalLog("STORE_SUCCESS", "Cart stored for token: {$session_key}", array(
            'cart_items' => count($cart_data['shoppingcart'] ?? []),
            'order_id' => $cart_data['order_id'] ?? 'unknown'
        ));
        
        return $result ? true : false;
    }
    
    /**
     * Retrieve cart data from database after PayPal return
     * 
     * @param string $session_key - PayPal token or session_id
     * @return array|null Cart data or null if not found
     */
    public function retrieveCartSession($session_key) {
        $session_key_clean = $this->db->real_escape_string($session_key);
        
        $query = "
            SELECT 
                cart_data, 
                payment_provider, 
                status,
                created_at,
                updated_at
            FROM cart_sessions 
            WHERE session_key = '{$session_key_clean}' 
            AND expires_at > NOW()
            LIMIT 1
        ";
        
        $result = $this->db->query($query);
        
        if ($this->db->error) {
            $this->writePayPalLog("RETRIEVE_ERROR", "Database error: " . $this->db->error);
            return null;
        }
        
        if ($result && $result->num_rows > 0) {
            $row = $result->fetch_object();
            $cart_data = json_decode($row->cart_data, true);
            
            // Success logging
            $this->writePayPalLog("RETRIEVE_SUCCESS", "Cart retrieved for key: {$session_key}", array(
                'cart_items' => count($cart_data['shoppingcart'] ?? []),
                'status' => $row->status
            ));
            
            return array(
                'cart_data' => $cart_data,
                'payment_provider' => $row->payment_provider,
                'status' => $row->status,
                'created_at' => $row->created_at,
                'updated_at' => $row->updated_at
            );
        }
        
        $this->writePayPalLog("RETRIEVE_FAILED", "No cart found for key: {$session_key}");
        return null;
    }
    
    /**
     * Dedicated PayPal logging system - no more Plesk chaos!
     * 
     * @param string $type - LOG_TYPE (STORE_SUCCESS, RETRIEVE_SUCCESS, ERROR, etc.)
     * @param string $message - Human readable message
     * @param array $context - Additional context data
     */
    private function writePayPalLog($type, $message, $context = array()) {
        $timestamp = date('Y-m-d H:i:s');
        $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
        $user_agent = substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 100);
        
        $log_entry = sprintf(
            "[%s] %s | %s | IP:%s | %s | Context:%s\n",
            $timestamp,
            $type,
            $message,
            $ip,
            $user_agent,
            json_encode($context)
        );
        
        // Write to dedicated PayPal log file
        file_put_contents($this->log_file, $log_entry, FILE_APPEND | LOCK_EX);
        
        // Also write to error_log as fallback
        error_log("PayPal Session Fix [{$type}]: {$message}");
    }
    
    /**
     * Update cart session status (processing, completed, abandoned)
     * 
     * @param string $session_key
     * @param string $status - 'processing', 'completed', 'abandoned'
     * @return bool Success/failure
     */
    public function updateCartStatus($session_key, $status) {
        $session_key_clean = $this->db->real_escape_string($session_key);
        $status_clean = $this->db->real_escape_string($status);
        
        $query = "
            UPDATE cart_sessions 
            SET status = '{$status_clean}', 
                updated_at = CURRENT_TIMESTAMP 
            WHERE session_key = '{$session_key_clean}'
        ";
        
        $result = $this->db->query($query);
        
        if ($this->db->error) {
            $this->writePayPalLog("STATUS_ERROR", "Database error: " . $this->db->error);
            return false;
        }
        
        $this->writePayPalLog("STATUS_UPDATE", "Updated {$session_key} to {$status}");
        return $result ? true : false;
    }
    
    /**
     * Clean up expired or completed cart sessions
     * Should be called via cron job
     * 
     * @param int $older_than_hours - Delete sessions older than X hours
     * @return int Number of deleted records
     */
    public function cleanupExpiredSessions($older_than_hours = 24) {
        $query = "
            DELETE FROM cart_sessions 
            WHERE expires_at < NOW() 
            OR (status = 'completed' AND updated_at < (NOW() - INTERVAL {$older_than_hours} HOUR))
            OR (status = 'abandoned' AND updated_at < (NOW() - INTERVAL {$older_than_hours} HOUR))
        ";
        
        $result = $this->db->query($query);
        $deleted_count = $this->db->affected_rows;
        
        if ($this->db->error) {
            $this->writePayPalLog("CLEANUP_ERROR", "Database error: " . $this->db->error);
            return 0;
        }
        
        $this->writePayPalLog("CLEANUP_SUCCESS", "Deleted {$deleted_count} expired sessions");
        return $deleted_count;
    }
    
    /**
     * Debug helper - get cart session info
     */
    public function getCartSessionInfo($session_key) {
        $session_key_clean = $this->db->real_escape_string($session_key);
        
        $query = "
            SELECT * FROM cart_sessions 
            WHERE session_key = '{$session_key_clean}' 
            LIMIT 1
        ";
        
        $result = $this->db->query($query);
        
        if ($result && $result->num_rows > 0) {
            return $result->fetch_object();
        }
        
        return null;
    }
}
?>