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

/**
 * Pocketfi.ng Webhook / IPN Handler
 * File: user/pocketfi-webhook.php
 *
 * Confirmed live payload structure:
 * {
 *   "order": {
 *     "amount": 500,
 *     "settlement_amount": 495.5,
 *     "fee": 4.5,
 *     "description": "7000600267 received 500 from DANIEL MAIGONA RIDAN ..."
 *   },
 *   "transaction": { "reference": "PFI|2603112348027" },
 *   "account_number": "7000600267",
 *   "customer": {
 *     "id": 60821, "first_name": "Daniel", "last_name": "Ridan",
 *     "phone": "09065236144", "email": "dannybreed@proton.me", "businessId": "29812"
 *   }
 * }
 *
 * NOTE: Pocketfi does NOT send a signature header. The signature check in
 * verifyPocketfiWebhookSignature() handles this gracefully — when no signature
 * is present it allows the request through and logs a notice.
 */

if (session_status() === PHP_SESSION_NONE) { session_start(); }
require_once '../include/config.php';
require_once '../include/pocketfi.php';

// ── Only accept POST ───────────────────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    exit('Method Not Allowed');
}

// ── Read raw body & log everything for debugging ───────────────────────────
$raw_body = file_get_contents('php://input');

$all_headers = [];
foreach ($_SERVER as $key => $value) {
    if (strpos($key, 'HTTP_') === 0) {
        $all_headers[$key] = $value;
    }
}
error_log('[Pocketfi Webhook] Incoming | Headers: ' . json_encode($all_headers) . ' | Body: ' . $raw_body);

// ── Collect signature from any possible header ─────────────────────────────
$signature = $_SERVER['HTTP_X_POCKETFI_SIGNATURE']
          ?? $_SERVER['HTTP_X_POCKETFI_HASH']
          ?? $_SERVER['HTTP_X_WEBHOOK_SIGNATURE']
          ?? $_SERVER['HTTP_X_SIGNATURE']
          ?? $_SERVER['HTTP_SIGNATURE']
          ?? '';

// ── Verify (or bypass) signature ──────────────────────────────────────────
$webhook_secret = trim($site_data['pocketfi_webhook_secret'] ?? '');

if (!verifyPocketfiWebhookSignature($raw_body, $signature, $webhook_secret)) {
    http_response_code(401);
    error_log('[Pocketfi Webhook] Signature verification failed. sig=' . $signature);
    exit('Unauthorized');
}

// ── Decode confirmed payload structure ────────────────────────────────────
$event = json_decode($raw_body, true);

if (!$event || json_last_error() !== JSON_ERROR_NONE) {
    http_response_code(400);
    error_log('[Pocketfi Webhook] Invalid JSON: ' . $raw_body);
    exit('Bad Request');
}

// ── Extract fields from confirmed Pocketfi payload ────────────────────────

// Top-level account number
$account_number = $event['account_number'] ?? '';

// Order block — use settlement_amount (Pocketfi's fee already deducted)
$original_amount   = floatval($event['order']['amount']             ?? 0);
$settlement_amount = floatval($event['order']['settlement_amount']  ?? $original_amount);
$pocketfi_fee      = floatval($event['order']['fee']                ?? 0);
$description       = $event['order']['description']                 ?? '';

// Transaction reference
$gateway_ref = $event['transaction']['reference'] ?? '';

// Currency & payment method
$currency       = 'NGN';
$payment_method = 'bank_transfer';

// ── Sanity checks ──────────────────────────────────────────────────────────
if (empty($account_number) || $settlement_amount <= 0 || empty($gateway_ref)) {
    http_response_code(400);
    error_log('[Pocketfi Webhook] Missing required fields.'
        . ' acct=' . $account_number
        . ' settlement=' . $settlement_amount
        . ' ref=' . $gateway_ref);
    exit('Bad Request');
}

// ── Platform fee on top of Pocketfi's own fee (optional) ──────────────────
// Configure in settings table:
//   pocketfi_fee_type  : 'none' | 'percent' | 'flat'
//   pocketfi_fee_value : e.g. 1.5 for 1.5%, or 50 for flat ₦50
//   pocketfi_fee_max   : NGN cap for percent type (0 = no cap)
$fee_type  = trim($site_data['pocketfi_fee_type']  ?? 'none');
$fee_value = floatval($site_data['pocketfi_fee_value'] ?? 0);
$fee_max   = floatval($site_data['pocketfi_fee_max']   ?? 0);

$platform_fee = 0;
if ($fee_type !== 'none' && $fee_value > 0) {
    if ($fee_type === 'flat') {
        $platform_fee = $fee_value;
    } else {
        // percent
        $platform_fee = ($settlement_amount * $fee_value) / 100;
        if ($fee_max > 0 && $platform_fee > $fee_max) {
            $platform_fee = $fee_max;
        }
    }
    $platform_fee = round($platform_fee, 2);
}

$amount_to_credit = round($settlement_amount - $platform_fee, 2);

if ($amount_to_credit <= 0) {
    http_response_code(200);
    error_log('[Pocketfi Webhook] Amount after platform fee is zero or negative.'
        . ' settlement=' . $settlement_amount . ' platform_fee=' . $platform_fee);
    echo json_encode(['status' => 'fee_exceeds_amount']);
    exit();
}

error_log('[Pocketfi Webhook] Payment breakdown:'
    . ' original=₦'      . $original_amount
    . ' pocketfi_fee=₦'  . $pocketfi_fee
    . ' settlement=₦'    . $settlement_amount
    . ' platform_fee=₦'  . $platform_fee
    . ' to_credit=₦'     . $amount_to_credit
    . ' acct='           . $account_number
    . ' ref='            . $gateway_ref
    . ' desc="'          . $description . '"');

// ── Find user by virtual account number ───────────────────────────────────
try {
    $stmt = $pdo->prepare("SELECT * FROM users WHERE pocketfi_account_number = :acct LIMIT 1");
    $stmt->execute(['acct' => $account_number]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    http_response_code(500);
    error_log('[Pocketfi Webhook] DB lookup error: ' . $e->getMessage());
    exit('Server Error');
}

if (!$user) {
    http_response_code(200);
    error_log('[Pocketfi Webhook] No user found for account: ' . $account_number);
    echo json_encode(['status' => 'no_user']);
    exit();
}

// ── Idempotency: prevent double-crediting ─────────────────────────────────
try {
    $dup = $pdo->prepare(
        "SELECT id FROM transactions WHERE gateway_reference = :gref AND status = 'successful' LIMIT 1"
    );
    $dup->execute(['gref' => $gateway_ref]);
    if ($dup->fetch()) {
        http_response_code(200);
        error_log('[Pocketfi Webhook] Duplicate — already processed ref: ' . $gateway_ref);
        echo json_encode(['status' => 'already_processed']);
        exit();
    }
} catch (PDOException $e) {
    http_response_code(500);
    error_log('[Pocketfi Webhook] Idempotency check error: ' . $e->getMessage());
    exit('Server Error');
}

// ── Process the credit ─────────────────────────────────────────────────────
try {
    $pdo->beginTransaction();

    // Is this the user's first successful deposit? (for referral commission)
    $first_stmt = $pdo->prepare(
        "SELECT COUNT(*) AS cnt FROM transactions WHERE user_id = :uid AND status = 'successful'"
    );
    $first_stmt->execute(['uid' => $user['id']]);
    $is_first_deposit = ($first_stmt->fetch(PDO::FETCH_ASSOC)['cnt'] == 0) ? 1 : 0;

    $transaction_ref = 'VACT_' . strtoupper(uniqid()) . '_' . time();

    // ── 1. Insert transaction ──────────────────────────────────────────────
    $pdo->prepare(
        "INSERT INTO transactions
            (user_id, transaction_ref, payment_gateway, amount, currency,
             status, payment_method, gateway_reference, gateway_response,
             ip_address, is_first_deposit, created_at, updated_at)
         VALUES
            (:uid, :ref, 'virtual_account', :amount, :currency,
             'successful', :pm, :gref, :gresp,
             :ip, :is_first, NOW(), NOW())"
    )->execute([
        'uid'      => $user['id'],
        'ref'      => $transaction_ref,
        'amount'   => $amount_to_credit,
        'currency' => $currency,
        'pm'       => $payment_method,
        'gref'     => $gateway_ref,
        'gresp'    => $raw_body,
        'ip'       => $_SERVER['REMOTE_ADDR'] ?? '',
        'is_first' => $is_first_deposit,
    ]);

    $new_txn_id = $pdo->lastInsertId();

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

    // ── 3. Referral commission on first deposit ────────────────────────────
    if ($is_first_deposit === 1) {
        $ref_stmt = $pdo->prepare(
            "SELECT * FROM referrals WHERE referred_user_id = :uid AND status = 'pending' LIMIT 1"
        );
        $ref_stmt->execute(['uid' => $user['id']]);
        $referral = $ref_stmt->fetch(PDO::FETCH_ASSOC);

        if ($referral) {
            $refer_percent     = floatval($site_data['refer_percent'] ?? 0);
            $commission_amount = round(($amount_to_credit * $refer_percent) / 100, 2);

            if ($commission_amount > 0) {
                $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' => $user['id'],
                    'tid' => $new_txn_id,
                    'dep' => $amount_to_credit,
                    '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' => $new_txn_id]);

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

                error_log('[Pocketfi Webhook] Referral commission ₦' . $commission_amount
                    . ' → referrer ' . $referral['referrer_id']);
            }
        }
    }

    $pdo->commit();

    error_log('[Pocketfi Webhook] SUCCESS → user ' . $user['id']
        . ' | original=₦'     . $original_amount
        . ' pocketfi_fee=₦'   . $pocketfi_fee
        . ' settlement=₦'     . $settlement_amount
        . ' platform_fee=₦'   . $platform_fee
        . ' credited=₦'       . $amount_to_credit
        . ' ref='              . $gateway_ref);

    http_response_code(200);
    echo json_encode([
        'status'          => 'success',
        'user_id'         => $user['id'],
        'original_amount' => $original_amount,
        'pocketfi_fee'    => $pocketfi_fee,
        'settlement'      => $settlement_amount,
        'platform_fee'    => $platform_fee,
        'credited'        => $amount_to_credit,
        'currency'        => $currency,
        'reference'       => $gateway_ref,
    ]);
    exit();

} catch (Exception $e) {
    $pdo->rollBack();
    http_response_code(500);
    error_log('[Pocketfi Webhook] Transaction error: ' . $e->getMessage());
    echo json_encode(['status' => 'error', 'message' => 'Internal server error']);
    exit();
}