<?php
/**
 * webhook.php — Kindamba Pay Payment Callback Receiver
 *
 * Each user's unique webhook URL is:
 *   https://yourdomain.com/webhook?token=THEIR_UNIQUE_TOKEN
 *
 * Kindamba Pay POSTs a JSON payload here when a transaction status changes.
 * The ?token= identifies which user (and therefore which API key)
 * this callback belongs to.
 */

require_once __DIR__ . '/config.php';
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/kindamba.php';

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

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

// --- 1. Read raw payload ---
$raw = file_get_contents('php://input');
$payload = json_decode($raw, true);

// --- 2. (Optional) Verify Kindamba webhook signature ---
// Not explicitly detailed in docs, but usually involves Secret Key if provided.
// For now, we rely on the unique webhook token for security.

// --- 3. Identify the user by their unique token ---
$token = trim($_GET['token'] ?? '');

if (empty($token)) {
    http_response_code(401);
    echo json_encode(['error' => 'Missing webhook token']);
    exit;
}

try {
    $stmt = $pdo->prepare("SELECT id, api_key FROM users WHERE webhook_token = ? LIMIT 1");
    $stmt->execute([$token]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    http_response_code(500);
    echo json_encode(['error' => 'Database error']);
    exit;
}

if (!$user) {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid webhook token']);
    exit;
}

$user_id = $user['id'];

// Log for debugging
$logDir = __DIR__ . '/logs';
if (!is_dir($logDir)) {
    @mkdir($logDir, 0755, true);
}
if (is_dir($logDir) && is_writable($logDir)) {
    @file_put_contents(
        $logDir . '/kindamba_webhook_user' . $user_id . '.log',
        date('Y-m-d H:i:s') . " | " . $raw . "\n",
        FILE_APPEND | LOCK_EX
    );
}

// --- 4. Extract transaction_id and status from payload ---
// Kindamba Sends: { "event": "payment.completed", "transaction_id": "...", "status": "completed", "amount": 5000, "external_reference": "..." }
$tran_id = $payload['transaction_id']
        ?? $payload['id']
        ?? $payload['order_id']
        ?? $payload['external_reference']
        ?? null;

$status = strtolower(
    $payload['status']
    ?? $payload['payment_status']
    ?? ''
);

if (!$tran_id || !$status) {
    http_response_code(400);
    echo json_encode(['error' => 'Missing transaction_id or status in payload']);
    exit;
}

// --- 5. Look up the transaction ---
try {
    $stmt = $pdo->prepare("SELECT * FROM transactions WHERE tran_id = ? LIMIT 1");
    $stmt->execute([$tran_id]);
    $transaction = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    http_response_code(500);
    echo json_encode(['error' => 'Database error']);
    exit;
}

if (!$transaction) {
    http_response_code(200);
    echo json_encode(['received' => true, 'note' => 'Transaction not found in our database']);
    exit;
}

// Skip if already finalized
if (in_array($transaction['status'], ['completed', 'failed', 'cancelled', 'user_cancelled', 'rejected', 'expired'])) {
    http_response_code(200);
    echo json_encode(['received' => true, 'status' => $transaction['status']]);
    exit;
}

// --- 6. Map Kindamba status to our status ---
if (in_array($status, ['completed', 'success', 'successful', 'paid'])) {
    $newStatus = 'completed';
} elseif (in_array($status, ['cancelled', 'canceled', 'user_cancelled', 'rejected'])) {
    $newStatus = 'cancelled';
} elseif ($status === 'expired') {
    $newStatus = 'expired';
} elseif (in_array($status, ['failed', 'error'])) {
    $newStatus = 'failed';
} elseif (in_array($status, ['pending', 'inprogress', 'processing'])) {
    // Non-terminal — acknowledge but don't update
    http_response_code(200);
    echo json_encode(['received' => true, 'status' => 'pending']);
    exit;
} else {
    http_response_code(200);
    echo json_encode(['received' => true, 'status' => 'unknown', 'raw' => $status]);
    exit;
}

// --- 7. Update transaction in DB ---
try {
    // Strict Idempotency: Only update if the status is currently 'pending'
    $stmt = $pdo->prepare("UPDATE transactions SET status = ? WHERE tran_id = ? AND status = 'pending'");
    $stmt->execute([$newStatus, $tran_id]);

    if ($stmt->rowCount() > 0) {
        error_log("[KindambaPay] Webhook Success: Updated $tran_id to $newStatus");
    } else {
        error_log("[KindambaPay] Webhook Notice: $tran_id already processed or not pending.");
    }

    http_response_code(200);
    echo json_encode(['received' => true, 'user_id' => $user_id, 'status' => $newStatus]);
} catch (PDOException $e) {
    error_log("[KindambaPay] Webhook DB Error: " . $e->getMessage());
    http_response_code(500);
    echo json_encode(['error' => 'Failed to update transaction']);
}
?>
