<?php
/**
 * Paystack DVA Webhook Handler
 * Receives transfer notifications and credits user wallets.
 * 
 * Set this URL in your Paystack dashboard:
 * https://yourdomain.com/user/paystack-dva-webhook
 * 
 * Events handled:
 * - dedicatedaccount.assign.success (DVA created)
 * - charge.success (payment received on DVA)
 */

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

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

// Read raw body
$raw_body = file_get_contents('php://input');
error_log('[Paystack DVA Webhook] Incoming | Body: ' . substr($raw_body, 0, 2000));

// Verify Paystack signature
$secret_key = trim($site_data['paystack_secret_key'] ?? '');
$signature  = $_SERVER['HTTP_X_PAYSTACK_SIGNATURE'] ?? '';

if (empty($secret_key)) {
    http_response_code(401);
    error_log('[Paystack DVA Webhook] No secret key configured.');
    exit('Unauthorized');
}

$computed_hash = hash_hmac('sha512', $raw_body, $secret_key);
if (!hash_equals($computed_hash, $signature)) {
    http_response_code(401);
    error_log('[Paystack DVA Webhook] Invalid signature. Expected: ' . $computed_hash . ' Got: ' . $signature);
    exit('Unauthorized');
}

// Decode payload
$event = json_decode($raw_body, true);
if (!$event || json_last_error() !== JSON_ERROR_NONE) {
    http_response_code(400);
    exit('Bad Request');
}

$event_type = $event['event'] ?? '';

error_log('[Paystack Webhook] Event received: ' . $event_type);

// ── Handle Transfer events (withdrawals) ────────────────────────
if ($event_type === 'transfer.success' || $event_type === 'transfer.failed' || $event_type === 'transfer.reversed') {
    $data = $event['data'] ?? [];
    $reference = $data['reference'] ?? '';
    $status_map = [
        'transfer.success'  => 'successful',
        'transfer.failed'   => 'failed',
        'transfer.reversed' => 'failed',
    ];
    $new_status = $status_map[$event_type] ?? 'failed';

    error_log('[Paystack Webhook] Transfer ' . $event_type . ' | ref=' . $reference . ' | amount=' . ($data['amount'] ?? 0));

    if (!empty($reference)) {
        try {
            // Update transaction status
            $stmt = $pdo->prepare("UPDATE transactions SET status = :status, updated_at = NOW() WHERE transaction_ref = :ref AND transaction_type = 'withdrawal'");
            $stmt->execute(['status' => $new_status, 'ref' => $reference]);

            // If transfer failed/reversed, refund the user
            if ($new_status === 'failed') {
                $txn = $pdo->prepare("SELECT user_id, amount FROM transactions WHERE transaction_ref = :ref AND transaction_type = 'withdrawal' LIMIT 1");
                $txn->execute(['ref' => $reference]);
                $row = $txn->fetch(PDO::FETCH_ASSOC);
                if ($row) {
                    // Get fee from metadata
                    $meta_stmt = $pdo->prepare("SELECT metadata FROM transactions WHERE transaction_ref = :ref LIMIT 1");
                    $meta_stmt->execute(['ref' => $reference]);
                    $meta_raw = $meta_stmt->fetchColumn();
                    $meta = json_decode($meta_raw ?: '{}', true);
                    $fee = floatval($meta['fee'] ?? 0);
                    $refund_amount = (float)$row['amount'] + $fee;

                    $pdo->prepare("UPDATE users SET main_balance = main_balance + :amt WHERE id = :uid")
                        ->execute(['amt' => $refund_amount, 'uid' => $row['user_id']]);

                    error_log('[Paystack Webhook] Refunded user ' . $row['user_id'] . ' amount=' . $refund_amount . ' (transfer failed)');
                }
            }
        } catch (PDOException $e) {
            error_log('[Paystack Webhook] DB error processing transfer event: ' . $e->getMessage());
        }
    }

    http_response_code(200);
    echo json_encode(['status' => 'processed', 'event' => $event_type]);
    exit();
}

// We only care about successful charges (transfers received) for DVA
if ($event_type !== 'charge.success') {
    http_response_code(200);
    echo json_encode(['status' => 'ignored', 'event' => $event_type]);
    exit();
}

$data = $event['data'] ?? [];

// Check if this is a DVA payment (channel = dedicated_nuban)
$channel = $data['channel'] ?? '';
if ($channel !== 'dedicated_nuban') {
    http_response_code(200);
    echo json_encode(['status' => 'not_dva']);
    exit();
}

// Extract payment details
$amount_kobo    = intval($data['amount'] ?? 0);
$amount_ngn     = $amount_kobo / 100;
$gateway_ref    = $data['reference'] ?? '';
$customer_code  = $data['customer']['customer_code'] ?? '';
$customer_email = $data['customer']['email'] ?? '';
$paid_at        = $data['paid_at'] ?? date('Y-m-d H:i:s');

// DVA details from authorization
$dva_account    = $data['authorization']['receiver_bank_account_number'] ?? '';
$dva_bank       = $data['authorization']['receiver_bank'] ?? '';

// Fees
$fees_kobo      = intval($data['fees'] ?? 0);
$fees_ngn       = $fees_kobo / 100;

error_log('[Paystack DVA Webhook] charge.success | amount=NGN' . $amount_ngn
    . ' fees=NGN' . $fees_ngn
    . ' ref=' . $gateway_ref
    . ' customer=' . $customer_code
    . ' dva_account=' . $dva_account);

// Sanity checks
if ($amount_ngn <= 0 || empty($gateway_ref)) {
    http_response_code(400);
    error_log('[Paystack DVA Webhook] Invalid amount or reference.');
    exit('Bad Request');
}

// Find user by customer_code or DVA account number
$user = null;
try {
    if (!empty($customer_code)) {
        $stmt = $pdo->prepare("SELECT * FROM users WHERE paystack_customer_code = :code LIMIT 1");
        $stmt->execute(['code' => $customer_code]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
    }
    if (!$user && !empty($dva_account)) {
        $stmt = $pdo->prepare("SELECT * FROM users WHERE paystack_dva_account_number = :acct LIMIT 1");
        $stmt->execute(['acct' => $dva_account]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
    }
    if (!$user && !empty($customer_email)) {
        $stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email LIMIT 1");
        $stmt->execute(['email' => $customer_email]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
    }
} catch (PDOException $e) {
    http_response_code(500);
    error_log('[Paystack DVA Webhook] DB lookup error: ' . $e->getMessage());
    exit('Server Error');
}

if (!$user) {
    http_response_code(200);
    error_log('[Paystack DVA Webhook] No user found. customer_code=' . $customer_code . ' dva_account=' . $dva_account);
    echo json_encode(['status' => 'no_user']);
    exit();
}

// Idempotency check
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('[Paystack DVA Webhook] Duplicate ref: ' . $gateway_ref);
        echo json_encode(['status' => 'already_processed']);
        exit();
    }
} catch (PDOException $e) {
    http_response_code(500);
    exit('Server Error');
}

// Platform fee (optional — configure in settings)
$fee_type  = trim($site_data['paystack_dva_fee_type']  ?? 'none');
$fee_value = floatval($site_data['paystack_dva_fee_value'] ?? 0);
$fee_max   = floatval($site_data['paystack_dva_fee_max']   ?? 0);

$platform_fee = 0;
if ($fee_type !== 'none' && $fee_value > 0) {
    if ($fee_type === 'flat') {
        $platform_fee = $fee_value;
    } else {
        $platform_fee = ($amount_ngn * $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($amount_ngn - $platform_fee, 2);
if ($amount_to_credit <= 0) {
    http_response_code(200);
    echo json_encode(['status' => 'fee_exceeds_amount']);
    exit();
}

// Credit the user
try {
    $pdo->beginTransaction();

    // Check if first deposit
    $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 = 'PDVA_' . strtoupper(uniqid()) . '_' . time();

    // 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, 'paystack_dva', :amount, 'NGN',
             'successful', 'bank_transfer', :gref, :gresp,
             :ip, :is_first, NOW(), NOW())"
    )->execute([
        'uid'      => $user['id'],
        'ref'      => $transaction_ref,
        'amount'   => $amount_to_credit,
        'gref'     => $gateway_ref,
        'gresp'    => $raw_body,
        'ip'       => $_SERVER['REMOTE_ADDR'] ?? '',
        'is_first' => $is_first_deposit,
    ]);

    $new_txn_id = $pdo->lastInsertId();

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

    // 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']]);
            }
        }
    }

    $pdo->commit();

    error_log('[Paystack DVA Webhook] SUCCESS | user=' . $user['id'] . ' credited=NGN' . $amount_to_credit . ' ref=' . $gateway_ref);

    http_response_code(200);
    echo json_encode(['status' => 'success', 'credited' => $amount_to_credit]);
    exit();

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