<?php
require '../element/connection.php';
require '../config/rewards_config.php';

$rewardsConfig = include '../config/rewards_config.php';
$levelAmounts = $rewardsConfig['level_amounts'];
$maxLevels = $rewardsConfig['max_levels'];

error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);

session_start();
$current_user_id = $_SESSION['user_id'] ?? 0;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $sponsor_id = (int) $_POST['sponsor_id'];
    $name = $conn->real_escape_string($_POST['name']);
    $email = isset($_POST['email']) ? $conn->real_escape_string($_POST['email']) : '';
    $phone = isset($_POST['phone']) ? $conn->real_escape_string($_POST['phone']) : '';

    $conn->begin_transaction();

    try {
        // Check if sponsor exists
        $checkSponsor = $conn->query("SELECT * FROM users WHERE user_id = $sponsor_id");
        if (!$checkSponsor || $checkSponsor->num_rows == 0) {
            throw new Exception("❌ Sponsor ID not found.");
        }

        // Get the TOP ROOT user (user_id = 12345678)
        $topRootQuery = $conn->query("SELECT user_id FROM users WHERE user_id = 12345678");
        if (!$topRootQuery || $topRootQuery->num_rows == 0) {
            throw new Exception("❌ Top root user not found.");
        }
        $topRoot = $topRootQuery->fetch_assoc();
        $root_id = $topRoot['user_id'];

        // Generate unique 8-digit user_id
        do {
            $new_user_id = rand(10000000, 99999999);
            $check = $conn->query("SELECT 1 FROM users WHERE user_id = $new_user_id");
        } while ($check && $check->num_rows > 0);

        // Find the correct placement using level-wise round-robin from TOP ROOT
        $placement = findGlobalLevelWisePlacement($conn, $root_id);
        
        if (!$placement['success']) {
            throw new Exception($placement['message']);
        }

        $placement_id = $placement['placement_id'];
        $position = $placement['position'];

        // Insert the new user
        $conn->query("INSERT INTO users (
            user_id, name, email, phone, sponsor_id, placement_id,
            left_1_id, left_2_id, right_1_id, right_2_id, wallet, rank, joining_date, status
        ) VALUES (
            $new_user_id, '$name', '$email', '$phone', $sponsor_id, $placement_id,
            0, 0, 0, 0, 0, '{$rewardsConfig['level_names'][1]}', NOW(), 1
        )");

        // Update the parent's position
        $conn->query("UPDATE users SET $position = $new_user_id WHERE user_id = $placement_id");

        $conn->commit();
        
        // Check for level completions and process rewards
        $rewardsGiven = checkAndProcessRewards($conn, $sponsor_id, $levelAmounts, $maxLevels);
        
        // Redirect back to tree.php with success message
        $encoded_name = urlencode($name);
        header("Location: ../tree.php?success=1&new_id=$new_user_id&new_name=$encoded_name&new_phone=$phone&placement=$placement_id&position=$position");
        exit();

    } catch (Exception $e) {
        $conn->rollback();
        header("Location: ../tree.php?error=" . urlencode($e->getMessage()));
        exit();
    }
} else {
    header("Location: ../tree.php");
    exit();
}

/**
 * Find placement using level-wise round-robin distribution from GLOBAL ROOT
 * This uses the perfect algorithm that distributes users evenly across all nodes at the same level
 */
function findGlobalLevelWisePlacement($conn, $root_id) {
    
    $positions = ['left_1_id', 'left_2_id', 'right_1_id', 'right_2_id'];
    
    // First, check if root has empty slots directly under them
    $root = $conn->query("SELECT left_1_id, left_2_id, right_1_id, right_2_id FROM users WHERE user_id = $root_id")->fetch_assoc();
    
    // Check root's direct slots first (Level 0)
    foreach ($positions as $pos) {
        if ($root[$pos] == 0) {
            return [
                'success' => true,
                'placement_id' => $root_id,
                'position' => $pos,
                'level' => 0
            ];
        }
    }
    
    // Get all nodes organized by level starting from global root
    $treeByLevel = getGlobalTreeByLevel($conn, $root_id);
    
    // Start from Level 1 and go deeper
    $currentLevel = 1;
    
    while ($currentLevel <= 25) {
        
        // If this level doesn't exist yet, we need to create it
        if (!isset($treeByLevel[$currentLevel]) || empty($treeByLevel[$currentLevel])) {
            
            // Find the first node at previous level that has an empty slot
            $prevLevel = $currentLevel - 1;
            
            if (isset($treeByLevel[$prevLevel])) {
                foreach ($treeByLevel[$prevLevel] as $nodeId) {
                    $node = $conn->query("SELECT left_1_id, left_2_id, right_1_id, right_2_id FROM users WHERE user_id = $nodeId")->fetch_assoc();
                    
                    foreach ($positions as $pos) {
                        if ($node[$pos] == 0) {
                            return [
                                'success' => true,
                                'placement_id' => $nodeId,
                                'position' => $pos,
                                'level' => $prevLevel
                            ];
                        }
                    }
                }
            }
            
            $currentLevel++;
            continue;
        }
        
        // Get all nodes at current level
        $levelNodes = $treeByLevel[$currentLevel];
        
        // Check how many children each node has
        $nodeFillCounts = [];
        foreach ($levelNodes as $nodeId) {
            $node = $conn->query("SELECT left_1_id, left_2_id, right_1_id, right_2_id FROM users WHERE user_id = $nodeId")->fetch_assoc();
            
            $filledCount = 0;
            foreach ($positions as $pos) {
                if ($node[$pos] != 0) {
                    $filledCount++;
                }
            }
            
            // Only consider nodes that aren't full yet
            if ($filledCount < 4) {
                $nodeFillCounts[$nodeId] = $filledCount;
            }
        }
        
        // If all nodes at this level are full, move to next level
        if (empty($nodeFillCounts)) {
            $currentLevel++;
            continue;
        }
        
        // Find the minimum fill count at this level
        $minFill = min($nodeFillCounts);
        
        // Get all nodes with the minimum fill count (these need users next)
        $candidateNodes = [];
        foreach ($nodeFillCounts as $nodeId => $fillCount) {
            if ($fillCount == $minFill) {
                $candidateNodes[] = $nodeId;
            }
        }
        
        // For each candidate node in order, find an empty slot
        foreach ($candidateNodes as $nodeId) {
            $node = $conn->query("SELECT left_1_id, left_2_id, right_1_id, right_2_id FROM users WHERE user_id = $nodeId")->fetch_assoc();
            
            // Check positions in order (left_1, left_2, right_1, right_2)
            foreach ($positions as $pos) {
                if ($node[$pos] == 0) {
                    return [
                        'success' => true,
                        'placement_id' => $nodeId,
                        'position' => $pos,
                        'level' => $currentLevel
                    ];
                }
            }
        }
        
        $currentLevel++;
    }
    
    return [
        'success' => false,
        'message' => 'Maximum tree depth reached. No positions available.'
    ];
}

/**
 * Get tree organized by level starting from GLOBAL ROOT
 */
function getGlobalTreeByLevel($conn, $root_id) {
    $treeByLevel = [];
    $queue = [[$root_id, 0]]; // [user_id, level]
    $visited = [];
    $positions = ['left_1_id', 'left_2_id', 'right_1_id', 'right_2_id'];
    
    while (!empty($queue)) {
        list($current_id, $level) = array_shift($queue);
        
        if (in_array($current_id, $visited)) {
            continue;
        }
        $visited[] = $current_id;
        
        // Add to tree by level
        if (!isset($treeByLevel[$level])) {
            $treeByLevel[$level] = [];
        }
        $treeByLevel[$level][] = $current_id;
        
        // Get children
        $user = $conn->query("SELECT user_id, left_1_id, left_2_id, right_1_id, right_2_id FROM users WHERE user_id = $current_id")->fetch_assoc();
        
        if ($user) {
            // Add children to queue in order
            foreach ($positions as $pos) {
                if (!empty($user[$pos]) && $user[$pos] != 0) {
                    $queue[] = [$user[$pos], $level + 1];
                }
            }
        }
    }
    
    return $treeByLevel;
}

/**
 * Count direct referrals for a user (users with this sponsor_id)
 */
function countDirectReferrals($conn, $user_id) {
    $result = $conn->query("SELECT COUNT(*) as count FROM users WHERE sponsor_id = $user_id");
    $row = $result->fetch_assoc();
    return (int)$row['count'];
}

/**
 * Check if a user is "green" (has 4 direct referrals)
 */
function isUserGreen($conn, $user_id) {
    $directCount = countDirectReferrals($conn, $user_id);
    return $directCount >= 4;
}

/**
 * Check if a specific level is complete for a user
 * A level is complete when ALL users at that level are "green" (have 4 directs)
 */
function isLevelComplete($conn, $user_id, $level) {
    $currentLevelUsers = [$user_id];
    $currentDepth = 1;
    
    while ($currentDepth <= $level && !empty($currentLevelUsers)) {
        $nextLevelUsers = [];
        
        foreach ($currentLevelUsers as $uid) {
            $user = $conn->query("SELECT left_1_id, left_2_id, right_1_id, right_2_id FROM users WHERE user_id = $uid")->fetch_assoc();
            
            if (!$user) {
                return false;
            }
            
            if ($currentDepth == $level) {
                if (!isUserGreen($conn, $uid)) {
                    return false;
                }
            }
            
            if ($currentDepth < $level) {
                if ($user['left_1_id'] != 0) $nextLevelUsers[] = $user['left_1_id'];
                if ($user['left_2_id'] != 0) $nextLevelUsers[] = $user['left_2_id'];
                if ($user['right_1_id'] != 0) $nextLevelUsers[] = $user['right_1_id'];
                if ($user['right_2_id'] != 0) $nextLevelUsers[] = $user['right_2_id'];
            }
        }
        
        $currentLevelUsers = $nextLevelUsers;
        $currentDepth++;
    }
    
    return true;
}

/**
 * Check if a user has personally qualified for a level
 */
function hasUserQualifiedForLevel($conn, $user_id, $level) {
    if (!isUserGreen($conn, $user_id)) {
        return false;
    }
    
    if ($level == 1) {
        return true;
    }
    
    for ($i = 1; $i < $level; $i++) {
        if (!isLevelComplete($conn, $user_id, $i)) {
            return false;
        }
    }
    
    return true;
}

/**
 * Check if a user has completed any new levels and process rewards
 */
function checkAndProcessRewards($conn, $user_id, $levelAmounts, $maxLevels) {
    $rewardsGiven = [];
    
    for ($level = 1; $level <= $maxLevels; $level++) {
        
        $check = $conn->prepare("SELECT 1 FROM level_rewards WHERE user_id = ? AND level = ?");
        $check->bind_param("ii", $user_id, $level);
        $check->execute();
        $result = $check->get_result();
        
        if ($result->num_rows > 0) {
            continue;
        }
        
        if (!hasUserQualifiedForLevel($conn, $user_id, $level)) {
            break;
        }
        
        if (isLevelComplete($conn, $user_id, $level)) {
            $amount = processLevelReward($conn, $user_id, $level, $levelAmounts);
            if ($amount > 0) {
                $rewardsGiven[] = [
                    'user_id' => $user_id,
                    'level' => $level,
                    'amount' => $amount
                ];
            }
        } else {
            break;
        }
    }
    
    return $rewardsGiven;
}

/**
 * Process level reward for a user with income history tracking
 */
function processLevelReward($conn, $user_id, $completed_level, $levelAmounts) {
    $amount = $levelAmounts[$completed_level] ?? 0;
    
    if ($amount <= 0) {
        return 0;
    }
    
    $tds_percentage = 10;
    $tds_amount = ($amount * $tds_percentage) / 100;
    $net_amount = $amount - $tds_amount;
    
    $conn->begin_transaction();
    
    try {
        $check = $conn->prepare("SELECT 1 FROM level_rewards WHERE user_id = ? AND level = ?");
        $check->bind_param("ii", $user_id, $completed_level);
        $check->execute();
        $result = $check->get_result();
        
        if ($result->num_rows == 0) {
            
            $update = $conn->prepare("UPDATE users SET wallet = wallet + ? WHERE user_id = ?");
            $update->bind_param("di", $amount, $user_id);
            $update->execute();
            
            $insert = $conn->prepare("INSERT INTO level_rewards (user_id, level, amount, paid, paid_at) VALUES (?, ?, ?, 1, NOW())");
            $insert->bind_param("iid", $user_id, $completed_level, $amount);
            $insert->execute();
            
            $description = "Level $completed_level completion reward";
            $credit_debit = 1;
            $admin_charges = 0;
            
            $history = $conn->prepare("INSERT INTO income_history (user_id, amount, description, credit_debit, admin_charges, tds) VALUES (?, ?, ?, ?, ?, ?)");
            $history->bind_param("idsiss", $user_id, $net_amount, $description, $credit_debit, $admin_charges, $tds_amount);
            $history->execute();
            
            updateUserRank($conn, $user_id, $completed_level);
            
            $conn->commit();
            return $amount;
        } else {
            $conn->rollback();
            return 0;
        }
    } catch (Exception $e) {
        $conn->rollback();
        error_log("Error processing reward: " . $e->getMessage());
        return 0;
    }
}

/**
 * Update user's rank based on completed level
 */
function updateUserRank($conn, $user_id, $completed_level) {
    global $rewardsConfig;
    $rank = $rewardsConfig['level_names'][$completed_level] ?? 'Bronze';
    $update = $conn->prepare("UPDATE users SET rank = ? WHERE user_id = ?");
    $update->bind_param("si", $rank, $user_id);
    $update->execute();
}
?>