<?php
//Developer: core tech web designTechnology
//Whatsapp: +2349162671360
//Telegram: @jeditech

// ── Cryptomus IPN (Instant Payment Notification) Webhook Handler ──────────
// Register this URL in your Cryptomus dashboard as the callback URL:
//   https://yourdomain.com/user/cryptomus-ipn.php
//
// This handles ASYNC crypto confirmations — blockchain confirmations can take
// minutes to hours depending on the coin, so this fires when Cryptomus
// detects a confirmed payment, independent of the user's browser session.
// ─────────────────────────────────────────────────────────────────────────

// No session needed for server-to-server webhook
require_once '../include/config.php';

// ── Read raw POST body ────────────────────────────────────────────────────
$raw_body = file_get_contents('php://input');
$data     = json_decode($raw_body, true);

if (!$data) {
    http_response_code(400);
    echo 'Bad Request';
    exit();
}

// ── Verify Cryptomus signature ────────────────────────────────────────────
// Cryptomus signs IPN by: md5( base64_encode(json without "sign" key) + payment_key )
$cryptomus_payment_key = $site_data['cryptomus_payment_key'];

$received_sign = $data['sign'] ?? '';
unset($data['sign']); // remove sign before re-computing

$computed_sign = md5(base64_encode(json_encode($data)) . $cryptomus_payment_key);

if (!hash_equals($computed_sign, $received_sign)) {
    http_response_code(403);
    echo 'Forbidden: Invalid signature';
    exit();
}

// ── Extract fields from IPN payload ──────────────────────────────────────
$order_id       = $data['order_id']  ?? '';
$ipn_status     = $data['status']    ?? '';
$uuid           = $data['uuid']      ?? '';
$pay_currency   = $data['currency']  ?? 'crypto';

if (empty($order_id)) {
    http_response_code(400);
    echo 'Missing order_id';
    exit();
}

// ── Statuses we treat as paid ─────────────────────────────────────────────
$paid_statuses = ['paid', 'paid_over', 'confirm_check'];

if (!in_array($ipn_status, $paid_statuses, true)) {
    // Not a paid status — log but respond 200 so Cryptomus stops retrying
    // (for statuses like 'cancel', 'fail', 'process', 'check', etc.)
    http_response_code(200);
    echo 'OK (not a paid status, ignored)';
    exit();
}

// ── Look up the transaction ───────────────────────────────────────────────
try {
    $stmt = $pdo->prepare("SELECT * FROM transactions WHERE transaction_ref = :ref FOR UPDATE");
    $pdo->beginTransaction();
    $stmt->execute(['ref' => $order_id]);
    $transaction = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$transaction) {
        $pdo->rollBack();
        http_response_code(404);
        echo 'Transaction not found';
        exit();
    }

    // Idempotency — already processed
    if ($transaction['status'] === 'successful') {
        $pdo->rollBack();
        http_response_code(200);
        echo 'OK (already credited)';
        exit();
    }

    $amount         = floatval($transaction['amount']); // NGN amount stored at invoice creation
    $payment_method = 'crypto_' . strtolower($pay_currency);
    $gateway_ref    = $uuid;

    // ── 1. Mark transaction successful ────────────────────────────────
    $pdo->prepare(
        "UPDATE transactions
         SET status             = 'successful',
             payment_method     = :pm,
             gateway_reference  = :gref,
             gateway_response   = :gresp,
             updated_at         = NOW()
         WHERE transaction_ref  = :ref"
    )->execute([
        'pm'    => $payment_method,
        'gref'  => $gateway_ref,
        'gresp' => json_encode($data),
        'ref'   => $order_id,
    ]);

    // ── 2. Credit user's main_balance ─────────────────────────────────
    $pdo->prepare(
        "UPDATE users SET main_balance = main_balance + :amount WHERE id = :uid"
    )->execute([
        'amount' => $amount,
        'uid'    => $transaction['user_id'],
    ]);

    // ── 3. Referral commission on first deposit ───────────────────────
    if ($transaction['is_first_deposit'] == 1 && !$transaction['referral_awarded']) {

        $referral_stmt = $pdo->prepare(
            "SELECT * FROM referrals WHERE referred_user_id = :uid AND status = 'pending'"
        );
        $referral_stmt->execute(['uid' => $transaction['user_id']]);
        $referral = $referral_stmt->fetch(PDO::FETCH_ASSOC);

        if ($referral) {
            $refer_percent     = floatval($site_data['refer_percent']);
            $commission_amount = ($amount * $refer_percent) / 100;

            $pdo->prepare(
                "INSERT INTO referral_earnings
                    (referral_id, referrer_id, referred_user_id, transaction_id,
                     deposit_amount, commission_percent, commission_amount, status, credited_at, created_at)
                 VALUES
                    (:rid, :rer, :red, :tid, :dep, :pct, :com, 'credited', NOW(), NOW())"
            )->execute([
                'rid'  => $referral['id'],
                'rer'  => $referral['referrer_id'],
                'red'  => $transaction['user_id'],
                'tid'  => $transaction['id'],
                'dep'  => $amount,
                'pct'  => $refer_percent,
                'com'  => $commission_amount,
            ]);

            $pdo->prepare(
                "UPDATE users
                 SET referral_balance = referral_balance + :com,
                     total_earnings   = total_earnings   + :com
                 WHERE id = :rid"
            )->execute([
                'com' => $commission_amount,
                'rid' => $referral['referrer_id'],
            ]);

            $pdo->prepare(
                "UPDATE referrals SET status = 'active', earnings = :com, updated_at = NOW() WHERE id = :rid"
            )->execute(['com' => $commission_amount, 'rid' => $referral['id']]);

            $pdo->prepare(
                "UPDATE transactions SET referral_awarded = 1 WHERE id = :tid"
            )->execute(['tid' => $transaction['id']]);

            $pdo->prepare(
                "UPDATE users SET first_activation = 1 WHERE id = :uid"
            )->execute(['uid' => $transaction['user_id']]);
        }
    }

    $pdo->commit();

    http_response_code(200);
    echo 'OK';

} catch (Exception $e) {
    if ($pdo->inTransaction()) $pdo->rollBack();
    http_response_code(500);
    echo 'Server Error';
    exit();
}
?>