<?php
/**
 * User/ajaxCalls/processRegister.php
 *
 * Always returns JSON. Never produces HTTP 500.
 *
 * POST action=precheck  → validate sponsor + create shell user → return IDs
 * POST step=register    → complete activation after on-chain TX confirmed
 */

// ── Catch PHP fatal errors before any output ──────────────────────────────────
ob_start();
ini_set('display_errors', '0');
error_reporting(E_ALL);

// Shutdown handler catches fatal/parse errors that try{}catch{} misses
register_shutdown_function(function () {
    $err = error_get_last();
    if ($err && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) {
        ob_end_clean();
        header('Content-Type: application/json');
        echo json_encode([
            'status'  => 'error',
            'message' => 'Server error: ' . $err['message'] .
                         ' (in ' . basename($err['file']) . ':' . $err['line'] . ')',
        ]);
    } else {
        ob_end_flush();
    }
});

header('Content-Type: application/json');

// ── Load files using absolute paths (immune to working-dir issues) ───────────
$base = dirname(__DIR__, 2);  // gainmoney/
require_once $base . '/connection/db.php';
require_once $base . '/connection/MatrixEngine.php';

// ── POST only ─────────────────────────────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['status' => 'error', 'message' => 'POST only']); exit;
}

// ── Test DB connection FIRST — give a clear message if it fails ───────────────
try {
    $db = getDB();
} catch (Throwable $dbErr) {
    echo json_encode([
        'status'  => 'error',
        'message' => 'Database connection failed: ' . $dbErr->getMessage() .
                     '. Please check DB_NAME, DB_USER, DB_PASS in connection/db.php',
    ]); exit;
}

// =============================================================================
// ACTION = precheck
// =============================================================================
$action = trim($_POST['action'] ?? '');

if ($action === 'precheck') {
    $myWallet  = trim($_POST['my_wallet']  ?? '');
    $refWallet = trim($_POST['ref_wallet'] ?? '');

    if (!$myWallet)  { echo json_encode(['status'=>'error','message'=>'Your wallet address is required']); exit; }
    if (!$refWallet) { echo json_encode(['status'=>'error','message'=>'Sponsor wallet address is required']); exit; }
    if ($myWallet === $refWallet) {
        echo json_encode(['status'=>'error','message'=>'Your wallet and sponsor wallet cannot be the same']); exit;
    }

    try {
        // Is this wallet already fully active?
        $chk = $db->prepare('SELECT member_id, topup_flag FROM meddolic_user_details WHERE walletAddress=? LIMIT 1');
        $chk->execute([$myWallet]);
        $existing = $chk->fetch();

        if ($existing && (int)$existing['topup_flag'] === 1) {
            echo json_encode(['status'=>'error','message'=>'This wallet is already registered. Please login instead.']); exit;
        }

        // Find sponsor (must be active)
        $sQ = $db->prepare('SELECT member_id FROM meddolic_user_details WHERE walletAddress=? AND topup_flag=1 LIMIT 1');
        $sQ->execute([$refWallet]);
        $sponsor = $sQ->fetch();

        if (!$sponsor) {
            echo json_encode(['status'=>'error','message'=>'Sponsor wallet not found or not yet active. Ask your referrer for their correct TRX wallet address.']); exit;
        }
        $sponsorId = (int)$sponsor['member_id'];

        $db->beginTransaction();

        if ($existing) {
            // Shell user already exists from a previous failed attempt — reuse it
            $memberId   = (int)$existing['member_id'];
            $uidQ       = $db->prepare('SELECT user_id FROM meddolic_user_details WHERE member_id=? LIMIT 1');
            $uidQ->execute([$memberId]);
            $tempUserId = (string)($uidQ->fetchColumn() ?: 'GM' . $memberId);
        } else {
            // Create new shell user (inactive, topup_flag=0)
            $tempUserId = generateUserId();
            $ins = $db->prepare('
                INSERT INTO meddolic_user_details
                    (user_id, walletAddress, sponser_id, topup_flag,
                     date_time, user_type, account_status,
                     currentPackage, poolEntry, wallet, fundWallet)
                VALUES (?, ?, ?, 0, NOW(), 2, 1, 0, 0, 0.00000, 0.00)
            ');
            $ins->execute([$tempUserId, $myWallet, $sponsorId]);
            $memberId = (int)$db->lastInsertId();

            if (!$memberId) {
                $db->rollBack();
                echo json_encode(['status'=>'error','message'=>'Failed to create user record. Check DB permissions.']); exit;
            }

            // Log in pending_reg (if table exists)
            try {
                $db->prepare('
                    INSERT INTO gm_pending_reg (temp_user_id, sponser_wallet, my_wallet, reg_status, created_at)
                    VALUES (?, ?, ?, 0, NOW())
                    ON DUPLICATE KEY UPDATE temp_user_id=VALUES(temp_user_id), reg_status=0
                ')->execute([$tempUserId, $refWallet, $myWallet]);
            } catch (Throwable $ignore) { /* table may not exist yet */ }
        }

        $db->commit();

        echo json_encode([
            'status'       => 'ok',
            'temp_user_id' => $tempUserId,
            'member_id'    => $memberId,
            'sponsor_id'   => $sponsorId,
        ]);

    } catch (Throwable $e) {
        if ($db->inTransaction()) $db->rollBack();
        echo json_encode(['status' => 'error', 'message' => 'Precheck failed: ' . $e->getMessage()]);
    }
    exit;
}

// =============================================================================
// STEP = register  (called after on-chain TX is confirmed)
// =============================================================================
$step = trim($_POST['step'] ?? '');

if ($step !== 'register') {
    echo json_encode(['status'=>'error','message'=>'Invalid request. Expected action=precheck or step=register']); exit;
}

// Read POST params
$myWallet      = trim($_POST['my_wallet']         ?? '');
$refWallet     = trim($_POST['ref_wallet']        ?? '');
$txHash        = trim($_POST['tx_hash']           ?? '');
$tempUserId    = trim($_POST['temp_user_id']      ?? '');
$memberId      = (int)($_POST['member_id']        ?? 0);
$pkg1Id        = (int)($_POST['pkg1_id']          ?? 1);
$pkg2Id        = (int)($_POST['pkg2_id']          ?? 2);
$pkg1Price     = (float)($_POST['pkg1_price']     ?? 30);
$pkg2Price     = (float)($_POST['pkg2_price']     ?? 40);
$totalUsd      = (float)($_POST['total_usd']      ?? 70);
$sponsorIncome = (float)($_POST['sponsor_income'] ?? 15);
$trxAmt        = (float)($_POST['trx_amount']     ?? 0);
$trxPrice      = (float)($_POST['trx_price']      ?? 3.48);

if (!$myWallet || !$txHash || $memberId <= 0) {
    echo json_encode(['status'=>'error','message'=>'Missing required fields: my_wallet, tx_hash, member_id']); exit;
}

try {
    // Duplicate TX guard
    try {
        $txChk = $db->prepare('SELECT id FROM gm_package_purchases WHERE trx_hash=? LIMIT 1');
        $txChk->execute([$txHash]);
        if ($txChk->fetch()) {
            echo json_encode(['status'=>'ok','message'=>'Transaction already processed. Account is active.']); exit;
        }
    } catch (Throwable $ignore) { /* table may not exist */ }

    // Load user
    $uQ = $db->prepare('SELECT * FROM meddolic_user_details WHERE member_id=? LIMIT 1');
    $uQ->execute([$memberId]);
    $user = $uQ->fetch();

    if (!$user) {
        echo json_encode(['status'=>'error','message'=>'User not found (member_id=' . $memberId . '). Please start registration again.']); exit;
    }
    if ((int)$user['topup_flag'] === 1) {
        echo json_encode(['status'=>'ok','message'=>'Account already active!','member_id'=>$memberId,'temp_user_id'=>$tempUserId]); exit;
    }

    $sponsorId = (int)$user['sponser_id'];
    $adminPct  = (float)(getMiscSetting()['adminCharge'] ?? 5.0);

    $db->beginTransaction();

    // ── 1. Activation records for both packages ───────────────────────────────
    $db->prepare('
        INSERT INTO meddolic_user_activation_details
            (member_id, sponser_id, packageId, investPrice, transHash, walletAddress, date_time, status, activate_by, buyType)
        VALUES (?, ?, ?, ?, ?, ?, NOW(), 1, ?, 1)
    ')->execute([$memberId, $sponsorId, $pkg1Id, $pkg1Price, $txHash, $myWallet, $memberId]);

    $db->prepare('
        INSERT INTO meddolic_user_activation_details
            (member_id, sponser_id, packageId, investPrice, transHash, walletAddress, date_time, status, activate_by, buyType)
        VALUES (?, ?, ?, ?, ?, ?, NOW(), 1, ?, 1)
    ')->execute([$memberId, $sponsorId, $pkg2Id, $pkg2Price, $txHash . '_p2', $myWallet, $memberId]);

    // ── 2. Purchase log (if table exists) ─────────────────────────────────────
    try {
        $db->prepare('
            INSERT INTO gm_package_purchases
                (member_id, sponser_id, package_id, package_price, trx_amount, trx_hash, wallet_address, buy_type, purchase_date, status)
            VALUES (?, ?, ?, ?, ?, ?, ?, 1, NOW(), 1)
        ')->execute([$memberId, $sponsorId, $pkg1Id, $pkg1Price, $trxAmt, $txHash, $myWallet]);

        $db->prepare('
            INSERT INTO gm_package_purchases
                (member_id, sponser_id, package_id, package_price, trx_amount, trx_hash, wallet_address, buy_type, purchase_date, status)
            VALUES (?, ?, ?, ?, 0, ?, ?, 1, NOW(), 1)
        ')->execute([$memberId, $sponsorId, $pkg2Id, $pkg2Price, $txHash . '_p2', $myWallet]);
    } catch (Throwable $ignore) { /* gm_package_purchases may not exist yet */ }

    // ── 3. Sponsor income $15 (contract already sent on-chain) ───────────────
    if ($sponsorId > 0 && $sponsorIncome > 0) {
        $db->prepare('
            INSERT INTO meddolic_user_referral_income
                (memberId, childId, referralIncome, packagePrice, adminCharge, netIncome, packageId, dateTime, referralPercent)
            VALUES (?, ?, ?, ?, 0, ?, ?, NOW(), ?)
        ')->execute([
            $sponsorId, $memberId,
            $sponsorIncome, $totalUsd,
            $sponsorIncome,  // net = gross (no admin — already split by contract)
            $pkg1Id,
            round($sponsorIncome / max($totalUsd, 1) * 100, 2),
        ]);

        $db->prepare('UPDATE meddolic_user_details SET wallet = wallet + ? WHERE member_id=?')
           ->execute([$sponsorIncome, $sponsorId]);

        $db->prepare('
            INSERT INTO meddolic_user_wallet_statement (member_id, wallet_statement_id, deb_cr, amount, date_time, trn_id)
            VALUES (?, 1, 2, ?, NOW(), ?)
        ')->execute([$sponsorId, $sponsorIncome, $memberId]);
    }

    // ── 4. Activate user — set currentPackage to pkg2 (highest purchased) ────
    $db->prepare('
        UPDATE meddolic_user_details
        SET topup_flag=1, activation_date=NOW(), currentPackage=?
        WHERE member_id=?
    ')->execute([$pkg2Id, $memberId]);

    // ── 5. Build 10-level ancestor chain ──────────────────────────────────────
    $engine = new MatrixEngine();
    $engine->buildChildChain($memberId, $sponsorId);

    // ── 6. Mark pending_reg complete (if table exists) ────────────────────────
    try {
        $db->prepare('
            UPDATE gm_pending_reg
            SET step1_hash=?, step2_hash=?, step1_trx=?, reg_status=1
            WHERE my_wallet=?
        ')->execute([$txHash, $txHash, $trxAmt, $myWallet]);
    } catch (Throwable $ignore) {}

    $db->commit();

    // ── 7. Post-commit: check if sponsor qualifies for auto-upgrade ───────────
    try {
        $engine->checkAutoUpgrade($sponsorId);
    } catch (Throwable $autoErr) {
        error_log('[processRegister] auto-upgrade check error: ' . $autoErr->getMessage());
    }

    echo json_encode([
        'status'         => 'ok',
        'message'        => 'Account activated! Both packages registered.',
        'member_id'      => $memberId,
        'temp_user_id'   => $tempUserId,
        'sponsor_income' => $sponsorIncome,
    ]);

} catch (Throwable $e) {
    if (isset($db) && $db->inTransaction()) $db->rollBack();
    error_log('[processRegister/register] ' . $e->getMessage() . ' | ' . $e->getFile() . ':' . $e->getLine());
    echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
}
