<?php
if (!defined('SECURE_ACCESS')) {
    exit('Direct access not permitted.');
}

/**
 * Award welcome signup bonus and distribute level referral sponsor commissions
 *
 * @param int $new_user_id
 * @param int|null $referrer_id
 */
function awardSignupAndReferralBonuses($new_user_id, $referrer_id = null) {
    global $pdo;
    if (!$pdo || !$new_user_id) {
        return;
    }

    try {
        $started_transaction = false;
        if (!$pdo->inTransaction()) {
            $pdo->beginTransaction();
            $started_transaction = true;
        }

        // Retrieve Settings
        $stmt_settings = $pdo->query("SELECT \"key\", value FROM system_settings");
        $sys_cfg = $stmt_settings->fetchAll(PDO::FETCH_KEY_PAIR) ?: [];

        $signup_bonus = (float)($sys_cfg['signup_bonus'] ?? 1000);
        $referral_bonus = (float)($sys_cfg['referral_bonus'] ?? 500);
        $referral_bonus_levels = (int)($sys_cfg['referral_bonus_levels'] ?? 5);
        $referral_bonus_cap = (float)($sys_cfg['referral_bonus_cap'] ?? 4000);

        // Resolve default referrer if none is provided or if user's referrer is not set in the DB
        $stmt_user = $pdo->prepare("SELECT referrer_id, parent_id FROM users WHERE id = ?");
        $stmt_user->execute([$new_user_id]);
        $u_info = $stmt_user->fetch();

        if ($u_info && empty($u_info['referrer_id'])) {
            $ref_to_use = $referrer_id;
            $default_ref = null;
            if (empty($ref_to_use)) {
                $default_ref_code = $sys_cfg['default_referrer_code'] ?? 'REPLUS123456789';
                $stmt_ref = $pdo->prepare("SELECT id, designation_id FROM users WHERE employee_code = ? OR username = ?");
                $stmt_ref->execute([$default_ref_code, $default_ref_code]);
                $default_ref = $stmt_ref->fetch();
                if ($default_ref) {
                    $ref_to_use = $default_ref['id'];
                }
            } else {
                $stmt_ref = $pdo->prepare("SELECT id, designation_id FROM users WHERE id = ?");
                $stmt_ref->execute([$ref_to_use]);
                $default_ref = $stmt_ref->fetch();
            }

            // Prevent self-referrals (a user cannot refer or be placed under themselves)
            if ($ref_to_use == $new_user_id) {
                $ref_to_use = null;
                $default_ref = null;
            }
            
            if (!empty($ref_to_use) && $default_ref) {
                $resolved_ref_id = $ref_to_use;

                // Fetch matrix configuration to calculate parent placement with spillover
                $m_width = 4;
                $m_depth = 4;
                if ($default_ref['designation_id']) {
                    $stmt_m = $pdo->prepare("SELECT matrix_width, matrix_depth FROM designations WHERE id = ?");
                    $stmt_m->execute([$default_ref['designation_id']]);
                    $des = $stmt_m->fetch();
                    if ($des) {
                        $m_width = (int)$des['matrix_width'];
                        $m_depth = (int)$des['matrix_depth'];
                    }
                }

                // Place in the matrix
                require_once __DIR__ . '/auth.php';
                $resolved_par_id = findMatrixPlacement($resolved_ref_id, $m_width, $m_depth);

                // Update the user's referrer and parent
                $stmt_upd = $pdo->prepare("UPDATE users SET referrer_id = ?, parent_id = ? WHERE id = ?");
                $stmt_upd->execute([$resolved_ref_id, $resolved_par_id, $new_user_id]);

                if (empty($referrer_id)) {
                    $referrer_id = $resolved_ref_id;
                }
            }
        }

        // A. Credit Signup Bonus
        if ($signup_bonus > 0) {
            $stmt_signup = $pdo->prepare("
                INSERT INTO earnings (user_id, amount, level, percentage, type) 
                VALUES (?, ?, 0, 0.00, 'signup_bonus')
            ");
            $stmt_signup->execute([$new_user_id, $signup_bonus]);
        }

        // B. Distribute Referral Bonus up the matrix parent chain
        // Fetch new user's parent_id (since they could have been placed by spillover under the matrix tree)
        $stmt_user_parent = $pdo->prepare("SELECT parent_id FROM users WHERE id = ?");
        $stmt_user_parent->execute([$new_user_id]);
        $parent_id = $stmt_user_parent->fetchColumn() ?: null;

        if ($referral_bonus > 0 && $parent_id) {
            try {
                // Fetch the parent chain and current accumulated earnings for each parent in a single query
                $stmt_chain = $pdo->prepare("
                    WITH RECURSIVE parent_chain AS (
                        SELECT id, parent_id, 1 AS level
                        FROM users
                        WHERE id = ?
                        
                        UNION ALL
                        
                        SELECT u.id, u.parent_id, p.level + 1
                        FROM users u
                        INNER JOIN parent_chain p ON u.id = p.parent_id
                        WHERE p.level < ?
                    )
                    SELECT pc.parent_id AS user_id, pc.level, COALESCE(SUM(e.amount), 0.00) AS earned_so_far
                    FROM parent_chain pc
                    LEFT JOIN earnings e ON pc.parent_id = e.user_id AND e.type = 'referral_bonus'
                    WHERE pc.parent_id IS NOT NULL
                    GROUP BY pc.parent_id, pc.level
                    ORDER BY pc.level ASC
                ");
                $stmt_chain->execute([$new_user_id, $referral_bonus_levels]);
                $parents = $stmt_chain->fetchAll(PDO::FETCH_ASSOC);
            } catch (PDOException $e) {
                $parents = [];
            }

            if (!empty($parents)) {
                $stmt_ref_credit = $pdo->prepare("
                    INSERT INTO earnings (user_id, buyer_id, amount, level, percentage, type) 
                    VALUES (?, ?, ?, ?, 0.00, 'referral_bonus')
                ");

                foreach ($parents as $p) {
                    $p_id = (int)$p['user_id'];
                    $lvl = (int)$p['level'];
                    $earned_so_far = (float)$p['earned_so_far'];
                    
                    $remaining_cap = max(0.00, $referral_bonus_cap - $earned_so_far);
                    
                    if ($remaining_cap > 0.00) {
                        $credit_amount = min($referral_bonus, $remaining_cap);
                        $stmt_ref_credit->execute([
                            $p_id,
                            $new_user_id,
                            $credit_amount,
                            $lvl
                        ]);
                    }
                }
            }
        }

        // Evaluate promotions for referrer and parents in the matrix chain
        require_once __DIR__ . '/auth.php';
        if (!empty($referrer_id)) {
            checkAndApplyDesignationPromotion($referrer_id, $pdo);
        }
        if (!empty($parents)) {
            foreach ($parents as $p) {
                $p_id = (int)$p['user_id'];
                checkAndApplyDesignationPromotion($p_id, $pdo);
            }
        }
        
        if ($started_transaction) {
            $pdo->commit();
        }
    } catch (PDOException $e) {
        if (isset($started_transaction) && $started_transaction && $pdo->inTransaction()) {
            $pdo->rollBack();
        }
        error_log("Bonus distribution error: " . $e->getMessage());
    }
}
