<?php
// DVA Payment Verification Endpoint
// Verifies a Paystack bank transfer by matching the payment reference in transaction narrations.

error_reporting(0);

// Catch any PHP errors and return them as JSON so the client sees a proper error message
set_exception_handler(function($e) {
    if (!headers_sent()) header('Content-Type: application/json');
    echo json_encode(['status' => 'error', 'message' => 'Server error: ' . $e->getMessage()]);
    exit;
});

// Task 2.1 — Method guard
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    exit;
}

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

// Task 2.1 — Detect source page and include correct session file
$sourcePage = isset($_POST['source_page']) ? trim($_POST['source_page']) : '';

$entrancePages = ['confirmpayen', 'confirmpaylesson', 'confirmpayen2'];
$studentPages  = ['confirmpaynd', 'confirmpaynb'];

$tabSessionID = isset($_POST['tab_id']) ? trim($_POST['tab_id']) : '';

if (in_array($sourcePage, $entrancePages)) {
    // Replicate session2.php logic but using POST tab_id instead of GET
    if (empty($tabSessionID)) {
        http_response_code(403);
        echo json_encode(['status' => 'error', 'message' => 'Unauthorized']);
        exit;
    }
    session_write_close();
    session_id($tabSessionID);
    session_name('guest_portal_' . $tabSessionID);
    session_start();

    // session2.php doesn't check any specific key — just that the session exists
    // No further auth check needed for entrance pages

} elseif (in_array($sourcePage, $studentPages)) {
    // Replicate session.php logic but using POST tab_id instead of GET
    ini_set('session.gc_maxlifetime', 7200);
    ini_set('session.cookie_lifetime', 7200);
    session_name('student_portal');
    session_start();

    if (empty($tabSessionID)) {
        $tabSessionID = isset($_SESSION['current_tab_id']) ? $_SESSION['current_tab_id'] : '';
    }

    if (empty($tabSessionID) || !isset($_SESSION['tabs'][$tabSessionID])) {
        http_response_code(403);
        echo json_encode(['status' => 'error', 'message' => 'Unauthorized']);
        exit;
    }

    // Sync student session data (mirrors session.php)
    $studentSession = $_SESSION['tabs'][$tabSessionID];
    $_SESSION['student_id'] = $studentSession['student_id'];

} else {
    http_response_code(403);
    echo json_encode(['status' => 'error', 'message' => 'Unauthorized']);
    exit;
}

require_once 'vendor/autoload.php';
include('includes/dbconnection.php');

// Load environment variables
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
$paystackSecretKey = $_ENV['PAYSTACK_SECRET_KEY'];

// Task 2.2 — Input validation

// Validate amount
$amount = isset($_POST['amount']) ? $_POST['amount'] : '';
if (!is_numeric($amount) || floatval($amount) <= 0) {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'Invalid amount']);
    exit;
}

// Validate payment_reference format: DVA-[A-Z0-9]{8}
$paymentReference = isset($_POST['payment_reference']) ? trim($_POST['payment_reference']) : '';
if (!preg_match('/^DVA-[A-Z0-9]{8}$/', $paymentReference)) {
    echo json_encode([
        'status'  => 'expired',
        'message' => 'Your payment reference has expired. Please refresh the page to get a new one.'
    ]);
    exit;
}

// Collect and sanitize other POST fields (used in prepared statements below)
$email       = isset($_POST['email'])       ? trim($_POST['email'])       : '';
$studentno   = isset($_POST['studentno'])   ? trim($_POST['studentno'])   : '';
$studentName = isset($_POST['studentName']) ? trim($_POST['studentName']) : '';
$stdid       = isset($_POST['stdid'])       ? trim($_POST['stdid'])       : '';
$feeType     = isset($_POST['feeType'])     ? trim($_POST['feeType'])     : '';
$termId      = isset($_POST['term_id'])     ? trim($_POST['term_id'])     : '';
$sessionId   = isset($_POST['session_id'])  ? trim($_POST['session_id'])  : '';

// Task 2.3 — Reference expiry check
$stmt = $con->prepare(
    "SELECT id, created_at, expires_at FROM dva_pending_payments
     WHERE payment_reference = ? LIMIT 1"
);
$stmt->bind_param('s', $paymentReference);
$stmt->execute();
$pendingResult = $stmt->get_result();
$pendingRow    = $pendingResult->fetch_assoc();
$stmt->close();

if (!$pendingRow) {
    echo json_encode([
        'status'  => 'expired',
        'message' => 'Your payment reference has expired. Please refresh the page to get a new one.'
    ]);
    exit;
}

// Check expiry
$now       = new DateTime();
$expiresAt = new DateTime($pendingRow['expires_at']);
if ($now > $expiresAt) {
    echo json_encode([
        'status'  => 'expired',
        'message' => 'Your payment reference has expired. Please refresh the page to get a new one.'
    ]);
    exit;
}

$createdAt = $pendingRow['created_at']; // used as $from for Paystack query

// Task 2.4 — Paystack transaction lookup

// Get active virtual account
$dvaStmt = $con->prepare(
    "SELECT paystack_customer_id FROM school_virtual_accounts WHERE is_active = 1 LIMIT 1"
);
$dvaStmt->execute();
$dvaResult  = $dvaStmt->get_result();
$dvaAccount = $dvaResult->fetch_assoc();
$dvaStmt->close();

if (!$dvaAccount) {
    echo json_encode(['status' => 'error', 'message' => 'No active virtual account configured']);
    exit;
}

$customerId = $dvaAccount['paystack_customer_id'];

// Build $from timestamp from the pending payment's created_at
$fromTimestamp = urlencode($createdAt);

// cURL Paystack transaction list
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,
    "https://api.paystack.co/transaction?customer={$customerId}&from={$fromTimestamp}&perPage=50"
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer $paystackSecretKey",
    "Content-Type: application/json"
]);
$response = curl_exec($ch);
$curlError = curl_error($ch);
curl_close($ch);

if ($curlError || $response === false) {
    echo json_encode(['status' => 'error', 'message' => 'Could not reach payment provider']);
    exit;
}

$responseData = json_decode($response, true);

if (!isset($responseData['status']) || $responseData['status'] !== true) {
    $errMsg = isset($responseData['message']) ? $responseData['message'] : 'Could not reach payment provider';
    echo json_encode(['status' => 'error', 'message' => $errMsg]);
    exit;
}

// Task 2.5 — Transaction matching
$transactions  = isset($responseData['data']) ? $responseData['data'] : [];
$matchedTx     = null;

foreach ($transactions as $tx) {
    $narration = isset($tx['narration']) ? $tx['narration'] : '';
    $txStatus  = isset($tx['status'])    ? $tx['status']    : '';
    if (strpos($narration, $paymentReference) !== false && $txStatus === 'success') {
        $matchedTx = $tx;
        break;
    }
}

if (!$matchedTx) {
    echo json_encode([
        'status'  => 'not_found',
        'message' => 'Transfer not found. Please ensure you used the reference code as your narration and try again.'
    ]);
    exit;
}

// Extract matched transaction details
$paystackRef = $matchedTx['reference'];
$amountPaid  = $matchedTx['amount'] / 100; // Convert kobo → NGN

// Check for existing payment record with this Paystack reference
$checkStmt = $con->prepare("SELECT id FROM payments WHERE reference = ? LIMIT 1");
$checkStmt->bind_param('s', $paystackRef);
$checkStmt->execute();
$checkResult = $checkStmt->get_result();
$existingRow = $checkResult->fetch_assoc();
$checkStmt->close();

if ($existingRow) {
    // UPDATE existing record
    $upsertStmt = $con->prepare(
        "UPDATE payments SET
            student_id     = ?,
            studentno      = ?,
            studentName    = ?,
            email          = ?,
            amount         = ?,
            status         = 'approved',
            fee_type       = ?,
            payment_date   = NOW(),
            payment_method = 'Bank Transfer',
            term_id        = ?,
            session_id     = ?
         WHERE reference = ?"
    );
    $upsertStmt->bind_param(
        'ssssdssss',
        $stdid, $studentno, $studentName, $email,
        $amountPaid, $feeType, $termId, $sessionId,
        $paystackRef
    );
} else {
    // INSERT new record
    $upsertStmt = $con->prepare(
        "INSERT INTO payments
            (student_id, studentno, studentName, email, reference, amount, status,
             fee_type, payment_date, payment_method, term_id, session_id)
         VALUES (?, ?, ?, ?, ?, ?, 'approved', ?, NOW(), 'Bank Transfer', ?, ?)"
    );
    $upsertStmt->bind_param(
        'sssssdsss',
        $stdid, $studentno, $studentName, $email,
        $paystackRef, $amountPaid, $feeType, $termId, $sessionId
    );
}

if (!$upsertStmt->execute()) {
    $upsertStmt->close();
    echo json_encode(['status' => 'error', 'message' => 'Payment record could not be saved']);
    exit;
}
$upsertStmt->close();

// Task 2.6 — Set session and return redirect

$_SESSION['payment_details'] = [
    'transaction_id' => $paystackRef,
    'amount'         => $amountPaid,
    'email'          => $email,
    'payment_method' => 'Bank Transfer',
    'status'         => 'approved',
    'student_no'     => $studentno,
    'student_name'   => $studentName,
    'fee_type'       => $feeType,
    'tab_id'         => $tabSessionID,
    'term'           => $termId,
    'session'        => $sessionId,
];

// Determine redirect URL based on source page
if (in_array($sourcePage, $entrancePages)) {
    $redirect = "confirmpaymententrance.php?tab_id={$tabSessionID}";
} else {
    $redirect = "confirmpayment.php?tab_id={$tabSessionID}";
}

echo json_encode(['status' => 'success', 'redirect' => $redirect]);
exit;
