<?php

/**
 * fetch_paystack_transactions.php
 *
 * Server-side AJAX endpoint: fetches transaction records from the Paystack API
 * for a given date, matches them against the local `payments` table, and returns
 * a JSON response. The Paystack secret key is loaded server-side only and is
 * never written to any output buffer.
 *
 * Feature: daily-transaction-reconciliation
 * Requirements: 13.1, 13.2, 13.3, 13.5, 13.6, 13.7, 13.8, 13.9
 */

// ─── Session setup ────────────────────────────────────────────────────────────
session_name('super_admin_session');

if (!is_dir(dirname(__DIR__, 2) . '/session_data/super')) {
    mkdir(dirname(__DIR__, 2) . '/session_data/super', 0700, true);
}
session_save_path(dirname(__DIR__, 2) . '/session_data/super');
session_set_cookie_params(['path' => '/', 'httponly' => true, 'samesite' => 'Strict']);
session_start();

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

// ─── Auth guard ───────────────────────────────────────────────────────────────
if (!isset($_SESSION['sid']) || strlen($_SESSION['sid']) == 0 ||
    !isset($_SESSION['permission']) || $_SESSION['permission'] !== 'Super User') {
    echo json_encode(['success' => false, 'message' => 'Unauthorised.']);
    exit();
}

// ─── Dependencies ─────────────────────────────────────────────────────────────
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../helpers/ReconciliationHelper.php';
include __DIR__ . '/../includes/dbconnection.php';

// Load .env — secret key stays server-side only
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/..');
$dotenv->load();
$secretKey = $_ENV['PAYSTACK_SECRET_KEY'] ?? '';

if (empty($secretKey)) {
    echo json_encode(['success' => false, 'message' => 'Paystack secret key is not configured.']);
    exit();
}

// ─── Input validation ─────────────────────────────────────────────────────────
$rawDate      = $_POST['date'] ?? '';
$selectedDate = validateReconciliationDate($rawDate);

// ─── Fetch from Paystack API (with pagination) ────────────────────────────────
$from = $selectedDate . 'T00:00:00';
$to   = $selectedDate . 'T23:59:59';

$allTransactions = [];
$nextUrl         = 'https://api.paystack.co/transaction?from=' . urlencode($from)
                 . '&to=' . urlencode($to) . '&perPage=200';

do {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $nextUrl,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => [
            'Authorization: Bearer ' . $secretKey,
            'Content-Type: application/json',
        ],
        CURLOPT_TIMEOUT        => 30,
    ]);

    $responseRaw = curl_exec($ch);
    $httpStatus  = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError   = curl_error($ch);
    curl_close($ch);

    if ($responseRaw === false || !empty($curlError)) {
        echo json_encode(['success' => false, 'message' => 'Unable to fetch Paystack records. Please try again.']);
        exit();
    }

    if ($httpStatus !== 200) {
        echo json_encode(['success' => false, 'message' => 'Unable to fetch Paystack records. Please try again.']);
        exit();
    }

    $response = json_decode($responseRaw, true);

    if (!isset($response['status']) || $response['status'] !== true) {
        echo json_encode(['success' => false, 'message' => 'Unable to fetch Paystack records. Please try again.']);
        exit();
    }

    $allTransactions = array_merge($allTransactions, $response['data'] ?? []);

    // Follow pagination if more pages exist
    $nextUrl = $response['meta']['next'] ?? null;

} while (!empty($nextUrl));

// ─── Compute API totals and channel breakdown ─────────────────────────────────
$apiTotalKobo = 0;
$byChannel    = [];

foreach ($allTransactions as $tx) {
    $kobo    = (int)($tx['amount'] ?? 0);
    $channel = strtolower($tx['channel'] ?? 'unknown');
    $status  = $tx['status'] ?? '';

    // Only count successful transactions
    if ($status !== 'success') {
        continue;
    }

    $apiTotalKobo += $kobo;

    if (!isset($byChannel[$channel])) {
        $byChannel[$channel] = ['count' => 0, 'amount' => 0.0];
    }
    $byChannel[$channel]['count']++;
    $byChannel[$channel]['amount'] += convertKoboToNaira($kobo);
}

$apiTotalNaira = convertKoboToNaira($apiTotalKobo);

// ─── Fetch local Paystack references for the selected date ────────────────────
$localRefs = [];
$stmt = $con->prepare(
    "SELECT reference FROM payments WHERE DATE(payment_date) = ? AND reference IS NOT NULL AND reference != ''"
);
$stmt->bind_param('s', $selectedDate);
$stmt->execute();
$refResult = $stmt->get_result();
while ($refRow = $refResult->fetch_assoc()) {
    $localRefs[] = $refRow['reference'];
}
$stmt->close();

// ─── Fetch local Paystack total for variance calculation ──────────────────────
$localPaystackTotal = 0.0;
$stmt = $con->prepare(
    "SELECT COALESCE(SUM(amount),0) FROM payments WHERE DATE(payment_date) = ? AND LOWER(payment_method) IN ('paystack','bank transfer')"
);
$stmt->bind_param('s', $selectedDate);
$stmt->execute();
$stmt->bind_result($localPaystackTotal);
$stmt->fetch();
$stmt->close();

// ─── Classify references ──────────────────────────────────────────────────────
$apiRefs = array_filter(
    array_column($allTransactions, 'reference'),
    fn($r) => !empty($r)
);
$classification = classifyReferences($localRefs, array_values($apiRefs));

// ─── Build transactions array for response ────────────────────────────────────
$matchedSet = array_flip($classification['matched']);
$transactions = [];

foreach ($allTransactions as $tx) {
    $ref    = $tx['reference'] ?? '';
    $kobo   = (int)($tx['amount'] ?? 0);
    $status = $tx['status'] ?? '';

    // Determine match status
    if (isset($matchedSet[$ref])) {
        $matchStatus = 'matched';
    } else {
        $matchStatus = 'missing_locally';
    }

    $transactions[] = [
        'reference'       => $ref,
        'amount_naira'    => convertKoboToNaira($kobo),
        'status'          => $status,
        'channel'         => strtolower($tx['channel'] ?? ''),
        'customer_email'  => $tx['customer']['email'] ?? '',
        'customer_name'   => trim(($tx['customer']['first_name'] ?? '') . ' ' . ($tx['customer']['last_name'] ?? '')),
        'paid_at'         => isset($tx['paid_at'])
                             ? date('d M Y H:i', strtotime($tx['paid_at']))
                             : '',
        'match_status'    => $matchStatus,
    ];
}

// Sort by paid_at descending
usort($transactions, fn($a, $b) => strcmp($b['paid_at'], $a['paid_at']));

// ─── Compute API variance ─────────────────────────────────────────────────────
$apiVariance = computeVariance($apiTotalNaira, (float)$localPaystackTotal);

// ─── Return JSON response ─────────────────────────────────────────────────────
echo json_encode([
    'success'               => true,
    'api_total_count'       => count(array_filter($allTransactions, fn($t) => ($t['status'] ?? '') === 'success')),
    'api_total_amount_naira'=> $apiTotalNaira,
    'by_channel'            => $byChannel,
    'local_paystack_total'  => (float)$localPaystackTotal,
    'api_variance'          => $apiVariance,
    'transactions'          => $transactions,
]);
