<?php
// Define TONSUI_LOADED constant to prevent direct access to session_init.php
define('TONSUI_LOADED', true);

// Set headers for JSON response
header("Content-Type: application/json; charset=utf-8");
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization, X-API-Key, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: DENY');
header('X-XSS-Protection: 1; mode=block');

// Handle preflight OPTIONS request
if ($_SERVER["REQUEST_METHOD"] === "OPTIONS") {
    http_response_code(204); // No Content
    exit;
}

// Only allow POST requests
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
    http_response_code(405); // Method Not Allowed
    echo json_encode([
        'status' => 'error',
        'message' => 'Method not allowed. Use POST.'
    ]);
    exit;
}

/**
 * process_investments.php: Processes active investments for ROI calculation and plan expiry
 * This should be run by a scheduled task (cron job) daily
 * Part of Ton Sui Mining investment workflow
 */

require_once 'config.php';
require_once 'db.php';

// Security check - only allow this script to be run with a valid API key or from command line
$isCommandLine = (php_sapi_name() === 'cli');
$apiKeyValid = false;

// Check for API key in the request if not run from command line
if (!$isCommandLine) {
    $headers = function_exists('getallheaders') ? getallheaders() : [];
    $apiKey = '';
    
    // Try to get API key from headers
    if (isset($headers['X-API-Key'])) {
        $apiKey = $headers['X-API-Key'];
    } elseif (isset($headers['x-api-key'])) {
        $apiKey = $headers['x-api-key'];
    } elseif (isset($_SERVER['HTTP_X_API_KEY'])) {
        $apiKey = $_SERVER['HTTP_X_API_KEY'];
    }
    
    // Validate against the config API key using constant-time comparison
    if (!isset($config['cron_api_key']) || empty($config['cron_api_key'])) {
        http_response_code(500);
        echo json_encode(['error' => 'Server misconfiguration: Missing cron_api_key in config']);
        exit(1);
    }
    
    if (empty($apiKey) || !hash_equals($config['cron_api_key'], $apiKey)) {
        http_response_code(403);
        echo json_encode(['error' => 'Unauthorized. Invalid or missing API key.']);
        exit(1);
    }
}

// Define constants
define('LOG_FILE', __DIR__ . '/investment_processing.log');

// Enhanced logging function that also captures logs for API response
function log_message($message, $include_in_response = false) {
    $timestamp = date('[Y-m-d H:i:s]');
    $log_entry = "$timestamp $message";
    
    // Always log to file
    file_put_contents(LOG_FILE, "$log_entry\n", FILE_APPEND);
    
    // Store log for API response if needed
    if ($include_in_response) {
        global $api_logs;
        $api_logs[] = $log_entry;
    }
    
    return $log_entry;
}

// Initialize response array
$response = [
    'status' => 'success',
    'message' => 'Investment processing completed successfully',
    'timestamp' => date('c'),
    'data' => [
        'processed' => 0,
        'roi_distributed' => 0,
        'capital_returned' => 0,
        'users_affected' => 0,
        'errors' => []
    ],
    'logs' => []
];

// Initialize logs array for API response
$api_logs = [];

// Log start of processing
$log_message = log_message('Starting investment processing...', true);
$response['logs'][] = $log_message;

try {
    // 1. HANDLE ROI DISTRIBUTION
    // Get all active investments
    $log_message = log_message('Fetching active investments...', true);
    $response['logs'][] = $log_message;
    
    $stmt = $pdo->query("
        SELECT 
            i.id, 
            i.user_id, 
            i.amount, 
            i.roi, 
            i.status, 
            i.start_date, 
            i.end_date,
            p.roi_percentage,
            p.duration_days,
            u.email as user_email
        FROM investments i
        JOIN investment_plans p ON i.plan_id = p.id
        JOIN users u ON i.user_id = u.id
        WHERE i.status = 'active'
        AND i.end_date >= CURDATE()
    ");
    
    $investments = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $stats = [
        'processed' => 0,
        'roi_distributed' => 0,
        'capital_returned' => 0,
        'users_affected' => []
    ];
    
    $log_message = log_message('Found ' . count($investments) . ' active investments to process.', true);
    $response['logs'][] = $log_message;
    
    $today = date('Y-m-d H:i:s');
    
    foreach ($investments as $investment) {
        $investment_id = $investment['id'];
        $user_id = $investment['user_id'];
        $user_email = $investment['user_email'];
        
        try {
            // Calculate daily ROI (total ROI divided by duration)
            $total_roi = floatval($investment['amount']) * (floatval($investment['roi_percentage']) / 100);
            $daily_roi = $total_roi / intval($investment['duration_days']);
            $daily_roi = round($daily_roi, 8); // Round to 8 decimal places
            
            // Track unique users
            if (!in_array($user_id, $stats['users_affected'])) {
                $stats['users_affected'][] = $user_id;
            }
            
            $log_message = log_message("Processing investment #$investment_id for user #$user_id ($user_email): Daily ROI = $daily_roi", true);
            $response['logs'][] = $log_message;
            
            // Check if investment is expired (end_date is in the past)
            $today = date('Y-m-d');
            $is_expired = strtotime($investment['end_date']) < strtotime($today);
            
            // Start transaction for this investment
            $pdo->beginTransaction();
            
            if ($is_expired) {
                // HANDLE EXPIRED INVESTMENT
                $log_message = log_message("Investment #$investment_id has expired. Processing capital return.", true);
                $response['logs'][] = $log_message;
                
                // Return capital to user
                $returnCapitalStmt = $pdo->prepare('UPDATE users SET balance = balance + ? WHERE id = ?');
                $returnCapitalStmt->execute([$investment['amount'], $user_id]);
                
                // Update investment status
                $updateInvestmentStmt = $pdo->prepare('UPDATE investments SET status = ?, updated_at = NOW() WHERE id = ?');
                $updateInvestmentStmt->execute(['completed', $investment_id]);
                
                // Insert transaction
                $transactionStmt = $pdo->prepare('INSERT INTO transactions (user_id, type, amount, status, details, reference, created_at) VALUES (?, ?, ?, ?, ?, ?, NOW())');
                $transactionStmt->execute([
                    $user_id, 
                    'capital_return', 
                    $investment['amount'], 
                    'completed', 
                    "Capital return for completed investment #$investment_id", 
                    'CAP-RETURN-' . time() . '-' . $investment_id
                ]);
                
                // Only process if not in test mode
                if (!empty($_POST['test_mode'])) {
                    $pdo->rollBack();
                    $log_message = log_message("Test mode - rolling back all changes", true);
                    $response['logs'][] = $log_message;
                } else {
                    $pdo->commit();
                }
                
                // Update stats
                $stats['capital_returned'] += $investment['amount'];
                $stats['processed']++;
                
                $log_message = log_message("Successfully returned capital of " . $investment['amount'] . " for expired investment #$investment_id", true);
                $response['logs'][] = $log_message;
                
            } else {
                // HANDLE DAILY ROI FOR ACTIVE INVESTMENT
                
                // 1. Update user balance with daily ROI
                $updateBalanceStmt = $pdo->prepare('UPDATE users SET balance = balance + ?, total_earned = COALESCE(total_earned, 0) + ? WHERE id = ?');
                $updateBalanceStmt->execute([$daily_roi, $daily_roi, $user_id]);
                
                // Update investment ROI
                $updateInvestmentStmt = $pdo->prepare('UPDATE investments SET roi = COALESCE(roi, 0) + ?, updated_at = NOW() WHERE id = ?');
                $updateInvestmentStmt->execute([$daily_roi, $investment_id]);
                
                // Insert transaction
                $transactionStmt = $pdo->prepare('INSERT INTO transactions (user_id, type, amount, status, details, reference, created_at) VALUES (?, ?, ?, ?, ?, ?, NOW())');
                $transactionStmt->execute([
                    $user_id, 
                    'profit', 
                    $daily_roi, 
                    'completed', 
                    "Daily ROI for investment #$investment_id", 
                    'ROI-' . time() . '-' . $investment_id
                ]);
                
                // Only process if not in test mode
                if (!empty($_POST['test_mode'])) {
                    $pdo->rollBack();
                    $log_message = log_message("Test mode - rolling back all changes", true);
                    $response['logs'][] = $log_message;
                } else {
                    $pdo->commit();
                }
                
                // Update stats
                $stats['processed']++;
                $stats['roi_distributed'] += $daily_roi;
                
                $log_message = log_message("Successfully processed ROI of $daily_roi for investment #$investment_id", true);
                $response['logs'][] = $log_message;
                
            }
            
        } catch (Exception $e) {
            $pdo->rollBack();
            $error_message = "Error processing investment #$investment_id: " . $e->getMessage();
            $log_message = log_message($error_message, true);
            $response['logs'][] = $log_message;
            $response['data']['errors'][] = [
                'investment_id' => $investment_id,
                'user_id' => $user_id,
                'error' => $e->getMessage()
            ];
            continue; // Skip to next investment on error
        }
    }
    
    // Update response with final stats
    $response['data']['processed'] = $stats['processed'];
    $response['data']['roi_distributed'] = round($stats['roi_distributed'], 8);
    $response['data']['capital_returned'] = round($stats['capital_returned'], 8);
    $response['data']['users_affected'] = count($stats['users_affected']);
    
    // Add completion log
    $log_message = log_message('Investment processing completed successfully.', true);
    $response['logs'][] = $log_message;
    
    // If there were errors, update status to partial
    if (!empty($response['data']['errors'])) {
        $response['status'] = 'partial';
        $response['message'] = 'Investment processing completed with some errors';
    }
    
    // Output the final JSON response
    echo json_encode($response, JSON_PRETTY_PRINT);
    
} catch (Exception $e) {
    // Rollback transaction if in progress
    if (isset($pdo) && $pdo->inTransaction()) {
        try {
            $pdo->rollBack();
        } catch (Exception $rollbackEx) {
            // Log rollback error but don't override the original exception
            log_message('Error during rollback: ' . $rollbackEx->getMessage());
        }
    }
    
    // Prepare error response
    $error_message = 'An error occurred while processing investments: ' . $e->getMessage();
    $log_message = log_message($error_message, true);
    
    $error_response = [
        'status' => 'error',
        'message' => 'An error occurred while processing investments',
        'error' => $e->getMessage(),
        'file' => $e->getFile(),
        'line' => $e->getLine(),
        'timestamp' => date('c'),
        'logs' => isset($api_logs) ? $api_logs : []
    ];
    
    // Add the error log to the response
    $error_response['logs'][] = $log_message;
    
    // Output JSON response
    http_response_code(500);
    echo json_encode($error_response, JSON_PRETTY_PRINT);
}

// Exit with success
exit(0);
