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

// ============================================================================
// FLUTTERWAVE WEBHOOK HANDLER
// ============================================================================
// This endpoint receives asynchronous payment notifications from Flutterwave
// More reliable than redirect-only verification
// ============================================================================

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

// ── Logging helper ─────────────────────────────────────────────────────────
function log_webhook($message, $data = null) {
    $log_file = __DIR__ . '/logs/flutterwave_webhook.log';
    $log_dir  = dirname($log_file);
    
    if (!is_dir($log_dir)) {
        @mkdir($log_dir, 0755, true);
    }
    
    $timestamp = date('Y-m-d H:i:s');
    $log_entry = "[{$timestamp}] {$message}";
    
    if ($data !== null) {
        $log_entry .= "\n" . json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
    }
    
    $log_entry .= "\n" . str_repeat('-', 80) . "\n";
    
    @file_put_contents($log_file, $log_entry, FILE_APPEND);
}

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

log_webhook('Webhook received', [
    'headers' => getallheaders(),
    'payload' => $webhook_data,
    'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
]);

// ── Verify webhook signature ───────────────────────────────────────────────
$flutterwave_webhook_secret = $site_data['flutterwave_webhook_secret'] ?? '';
$signature = $_SERVER['HTTP_VERIF_HASH'] ?? '';

// If webhook secret is configured, verify signature
if (!empty($flutterwave_webhook_secret)) {
    if ($signature !== $flutterwave_webhook_secret) {
        log_webhook('ERROR: Invalid webhook signature', [
            'expected' => $flutterwave_webhook_secret,
            'received' => $signature,
        ]);
        
        http_response_code(401);
        echo json_encode(['status' => 'error', 'message' => 'Invalid signature']);
        exit();
    }
    log_webhook('Signature verified successfully');
} else {
    log_webhook('WARNING: No webhook secret configured - signature check skipped');
}

// ── Validate webhook data ──────────────────────────────────────────────────
if (empty($webhook_data) || !is_array($webhook_data)) {
    log_webhook('ERROR: Invalid webhook data');
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'Invalid payload']);
    exit();
}

// ── Extract event type ─────────────────────────────────────────────────────
$event_type = $webhook_data['event'] ?? '';

log_webhook('Processing event', ['event_type' => $event_type]);

// ── Handle different event types ───────────────────────────────────────────
switch ($event_type) {
    
    case 'charge.completed':
        // Payment successful
        handle_charge_completed($webhook_data, $pdo, $site_data);
        break;
    
    case 'transfer.completed':
        // Transfer/payout completed (not used for deposits)
        log_webhook('Transfer completed event - skipping', $webhook_data);
        http_response_code(200);
        echo json_encode(['status' => 'success', 'message' => 'Event acknowledged']);
        exit();
        break;
    
    default:
        log_webhook('Unhandled event type', ['event' => $event_type]);
        http_response_code(200);
        echo json_encode(['status' => 'success', 'message' => 'Event type not processed']);
        exit();
}

// ── Handle charge.completed event ──────────────────────────────────────────
function handle_charge_completed($webhook_data, $pdo, $site_data) {
    try {
        // Extract payment data
        $data = $webhook_data['data'] ?? [];
        
        $tx_ref          = $data['tx_ref'] ?? '';
        $flw_ref         = $data['flw_ref'] ?? '';
        $transaction_id  = $data['id'] ?? '';
        $amount_charged  = floatval($data['charged_amount'] ?? 0);
        $currency        = strtoupper($data['currency'] ?? 'NGN');
        $status          = strtolower($data['status'] ?? '');
        $payment_type    = $data['payment_type'] ?? 'card';
        $customer_email  = $data['customer']['email'] ?? '';
        
        log_webhook('Processing charge.completed', [
            'tx_ref' => $tx_ref,
            'flw_ref' => $flw_ref,
            'amount' => $amount_charged,
            'currency' => $currency,
            'status' => $status,
        ]);
        
        // Validate required fields
        if (empty($tx_ref)) {
            log_webhook('ERROR: Missing tx_ref in webhook data');
            http_response_code(400);
            echo json_encode(['status' => 'error', 'message' => 'Missing tx_ref']);
            exit();
        }
        
        // Check if payment is successful
        if (!in_array($status, ['successful', 'completed'], true)) {
            log_webhook('Payment not successful', ['status' => $status]);
            
            // Update transaction as failed
            try {
                $stmt = $pdo->prepare(
                    "UPDATE transactions 
                     SET status = 'failed', 
                         gateway_response = :webhook_data,
                         updated_at = NOW()
                     WHERE transaction_ref = :tx_ref
                     AND status = 'pending'"
                );
                $stmt->execute([
                    'webhook_data' => json_encode($webhook_data),
                    'tx_ref' => $tx_ref,
                ]);
            } catch (PDOException $e) {
                log_webhook('ERROR: Failed to update transaction', ['error' => $e->getMessage()]);
            }
            
            http_response_code(200);
            echo json_encode(['status' => 'success', 'message' => 'Payment not successful']);
            exit();
        }
        
        // ── Verify transaction with Flutterwave API (double-check) ────────
        $flutterwave_secret_key = $site_data['flutterwave_secret_key'];
        
        $curl = curl_init('https://api.flutterwave.com/v3/transactions/' . rawurlencode($transaction_id) . '/verify');
        curl_setopt_array($curl, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . $flutterwave_secret_key,
                'Cache-Control: no-cache',
            ],
            CURLOPT_TIMEOUT => 30,
        ]);
        
        $verify_response = curl_exec($curl);
        $curl_err = curl_error($curl);
        curl_close($curl);
        
        if ($curl_err) {
            log_webhook('ERROR: Verification API call failed', ['error' => $curl_err]);
            http_response_code(500);
            echo json_encode(['status' => 'error', 'message' => 'Verification failed']);
            exit();
        }
        
        $verify_result = json_decode($verify_response, true);
        
        log_webhook('Verification response', $verify_result);
        
        // Check verification result
        if (
            !isset($verify_result['status']) || 
            $verify_result['status'] !== 'success' ||
            !isset($verify_result['data']['status']) ||
            !in_array($verify_result['data']['status'], ['successful', 'completed'], true)
        ) {
            log_webhook('ERROR: Verification check failed');
            http_response_code(400);
            echo json_encode(['status' => 'error', 'message' => 'Payment verification failed']);
            exit();
        }
        
        // ── Process the payment ────────────────────────────────────────────
        $pdo->beginTransaction();
        
        // Fetch the transaction record with lock
        $stmt = $pdo->prepare(
            "SELECT * FROM transactions 
             WHERE transaction_ref = :tx_ref 
             FOR UPDATE"
        );
        $stmt->execute(['tx_ref' => $tx_ref]);
        $transaction = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if (!$transaction) {
            $pdo->rollBack();
            log_webhook('ERROR: Transaction not found', ['tx_ref' => $tx_ref]);
            http_response_code(404);
            echo json_encode(['status' => 'error', 'message' => 'Transaction not found']);
            exit();
        }
        
        // Check if already processed
        if ($transaction['status'] === 'successful') {
            $pdo->rollBack();
            log_webhook('Transaction already processed', ['tx_ref' => $tx_ref]);
            http_response_code(200);
            echo json_encode(['status' => 'success', 'message' => 'Already processed']);
            exit();
        }
        
        // Use the NGN amount stored in our database
        $ngn_amount = floatval($transaction['amount']);
        
        log_webhook('Crediting user wallet', [
            'user_id' => $transaction['user_id'],
            'ngn_amount' => $ngn_amount,
            'original_amount' => $amount_charged,
            'currency' => $currency,
        ]);
        
        // ── 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  = :tx_ref"
        )->execute([
            'pm'    => $payment_type,
            'gref'  => $flw_ref,
            'gresp' => json_encode($webhook_data),
            'tx_ref' => $tx_ref,
        ]);
        
        // ── 2. Credit user's main_balance ───────────────────────────────────
        $pdo->prepare(
            "UPDATE users 
             SET main_balance = main_balance + :amount 
             WHERE id = :uid"
        )->execute([
            'amount' => $ngn_amount,
            'uid'    => $transaction['user_id'],
        ]);
        
        log_webhook('Wallet credited successfully', [
            'user_id' => $transaction['user_id'],
            'amount' => $ngn_amount,
        ]);
        
        // ── 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 = ($ngn_amount * $refer_percent) / 100;
                
                log_webhook('Awarding referral commission', [
                    'referrer_id' => $referral['referrer_id'],
                    'commission' => $commission_amount,
                    'percent' => $refer_percent,
                ]);
                
                // Record referral earning
                $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'  => $ngn_amount,
                    'pct'  => $refer_percent,
                    'com'  => $commission_amount,
                ]);
                
                // Credit referrer balance
                $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'],
                ]);
                
                // Update referral status
                $pdo->prepare(
                    "UPDATE referrals 
                     SET status = 'active', 
                         earnings = :com, 
                         updated_at = NOW() 
                     WHERE id = :rid"
                )->execute([
                    'com' => $commission_amount, 
                    'rid' => $referral['id']
                ]);
                
                // Mark referral as awarded
                $pdo->prepare(
                    "UPDATE transactions 
                     SET referral_awarded = 1 
                     WHERE id = :tid"
                )->execute(['tid' => $transaction['id']]);
                
                // Mark user as activated
                $pdo->prepare(
                    "UPDATE users 
                     SET first_activation = 1 
                     WHERE id = :uid"
                )->execute(['uid' => $transaction['user_id']]);
                
                log_webhook('Referral commission awarded successfully');
            }
        }
        
        $pdo->commit();
        
        log_webhook('Transaction processed successfully', [
            'tx_ref' => $tx_ref,
            'user_id' => $transaction['user_id'],
            'amount_credited' => $ngn_amount,
        ]);
        
        // Return success response
        http_response_code(200);
        echo json_encode([
            'status' => 'success',
            'message' => 'Payment processed successfully',
            'tx_ref' => $tx_ref,
        ]);
        exit();
        
    } catch (PDOException $e) {
        if (isset($pdo) && $pdo->inTransaction()) {
            $pdo->rollBack();
        }
        
        log_webhook('ERROR: Database error', [
            'error' => $e->getMessage(),
            'trace' => $e->getTraceAsString(),
        ]);
        
        http_response_code(500);
        echo json_encode(['status' => 'error', 'message' => 'Database error']);
        exit();
        
    } catch (Exception $e) {
        if (isset($pdo) && $pdo->inTransaction()) {
            $pdo->rollBack();
        }
        
        log_webhook('ERROR: Unexpected error', [
            'error' => $e->getMessage(),
            'trace' => $e->getTraceAsString(),
        ]);
        
        http_response_code(500);
        echo json_encode(['status' => 'error', 'message' => 'Processing error']);
        exit();
    }
}

// If we reach here, something went wrong
log_webhook('ERROR: Reached end of script unexpectedly');
http_response_code(500);
echo json_encode(['status' => 'error', 'message' => 'Unknown error']);
exit();
?>
