<?php
declare(strict_types=1);

ini_set('display_errors', '1');
error_reporting(E_ALL);

session_start();
require_once 'db.php';

/* ================= ADMIN AUTH ================= */
if (!isset($_SESSION['admin'])) {
    header('Location: admin_login.php');
    exit;
}

/* ================= HELPERS ================= */
function e(?string $value): string
{
    return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
}

function sendJson(array $data, int $statusCode = 200): void
{
    http_response_code($statusCode);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data);
    exit;
}

/**
 * Normalize the S8V status field.
 *
 * S8V may return statuses in any case ("Successful", "PENDING", "Failed" …)
 * or nested under `status`, `data.status`, or `result.status`. We lower-case
 * and trim so the UI CSS classes (pending/processing/successful/failed/unknown)
 * keep working regardless of how the upstream serializes the value.
 */
function normalizeStatus(array $data, string $fallback = 'unknown'): string
{
    $status = $data['status']
        ?? ($data['data']['status'] ?? null)
        ?? ($data['result']['status'] ?? null)
        ?? $fallback;

    $status = strtolower(trim((string)$status));

    $allowed = ['pending', 'processing', 'successful', 'failed', 'unknown'];
    return in_array($status, $allowed, true) ? $status : 'unknown';
}

/**
 * Pick a `response`-style field from a decoded payload so we can persist it
 * alongside the status. S8V docs show it under `response` (webhook payload)
 * but older replies may surface it under `data.response` or `result.data`.
 */
function extractResponse(array $data): ?string
{
    $candidates = [
        $data['response'] ?? null,
        $data['data']['response'] ?? null,
        $data['data']['data']['response'] ?? null,
        $data['result']['response'] ?? null,
        $data['result']['data']['response'] ?? null,
    ];

    foreach ($candidates as $value) {
        if ($value === null || $value === '') {
            continue;
        }
        return (string)$value;
    }

    return null;
}

function callApi(string $url, array $payload): array
{
    $jsonPayload = json_encode($payload);

    if ($jsonPayload === false) {
        return [
            'ok' => false,
            'message' => 'Failed to encode API payload'
        ];
    }

    $ch = curl_init($url);

    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $jsonPayload,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Accept: application/json'
        ],
        CURLOPT_TIMEOUT => 20,
        CURLOPT_CONNECTTIMEOUT => 10,
    ]);

    $response = curl_exec($ch);
    $curlError = curl_error($ch);
    $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($response === false || $curlError) {
        return [
            'ok' => false,
            'message' => $curlError ?: 'Unable to reach API'
        ];
    }

    $decoded = json_decode($response, true);

    if (!is_array($decoded)) {
        return [
            'ok' => false,
            'message' => 'Invalid API response',
            'raw' => $response,
            'http_code' => $httpCode
        ];
    }

    return [
        'ok' => true,
        'data' => $decoded,
        'raw' => $response,
        'http_code' => $httpCode
    ];
}

/* ================= AJAX HANDLER ================= */
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
    $action = trim((string)($_POST['action'] ?? ''));
    $trackingId = trim((string)($_POST['tracking_id'] ?? ''));

    if ($trackingId === '') {
        sendJson([
            'success' => false,
            'message' => 'Invalid tracking ID'
        ], 422);
    }

    // Token is loaded from an external file so it never lives in source control.
    // The token in the S8V docs (rrUviNdggfSGuGlGbaZURpkfAX4ebiFn201n721faTlMILRbV3)
    // is only an EXAMPLE - keep `s8v_api_key.php` as the source of truth.
    require 's8v_api_key.php';

    if (empty($token)) {
        sendJson([
            'success' => false,
            'message' => 'API token missing'
        ], 500);
    }

    // Endpoint map mirrors S8V docs:
    //   POST https://www.s8v.ng/api/clearance       - submit / retry request
    //   POST https://www.s8v.ng/api/clearance/status- re-check status
    $endpointMap = [
        'check_status'  => 'https://www.s8v.ng/api/clearance/status',
        'retry_request' => 'https://www.s8v.ng/api/clearance',
    ];

    if (!isset($endpointMap[$action])) {
        sendJson([
            'success' => false,
            'message' => 'Invalid action'
        ], 400);
    }

    $payload = [
        'token' => $token,
        'tracking_id' => $trackingId,
    ];

    $apiResult = callApi($endpointMap[$action], $payload);

    if (!$apiResult['ok']) {
        sendJson([
            'success' => false,
            'message' => $apiResult['message'] ?? 'API request failed',
            'raw' => $apiResult['raw'] ?? null
        ], 502);
    }

    $apiData = $apiResult['data'];
    $statusFallback = ($action === 'retry_request') ? 'pending' : 'unknown';
    $status = normalizeStatus($apiData, $statusFallback);
    $responseText = extractResponse($apiData);

    // Persist a normalized status AND keep the upstream payload in `reply`
    // so admins can still see `response` / error details returned by S8V.
    $reply = json_encode($apiData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
    if ($responseText !== null) {
        $reply = $responseText . "\n\n" . $reply;
    }

    $stmt = $conn->prepare("
        UPDATE ipe_requests
        SET status = ?, reply = ?
        WHERE tracking_id = ?
        LIMIT 1
    ");

    if (!$stmt) {
        sendJson([
            'success' => false,
            'message' => 'Database prepare failed'
        ], 500);
    }

    $stmt->bind_param('sss', $status, $reply, $trackingId);
    $executed = $stmt->execute();
    $stmt->close();

    if (!$executed) {
        sendJson([
            'success' => false,
            'message' => 'Database update failed'
        ], 500);
    }

    sendJson([
        'success' => true,
        'message' => $action === 'retry_request'
            ? 'Retry request sent successfully'
            : 'Status checked successfully',
        'status' => $status,
        'reply' => $reply,
        'tracking_id' => $trackingId,
        'show_retry' => ($status === 'pending')
    ]);
}

/* ================= FETCH REQUESTS ================= */
$result = $conn->query("
    SELECT id, user, tracking_id, status, reply, price, created_at
    FROM ipe_requests
    ORDER BY id DESC
    LIMIT 500
");
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Admin – IPE Requests</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
    * { box-sizing: border-box; }
    body {
        margin: 0;
        font-family: Inter, Arial, sans-serif;
        background: #0f172a;
        color: #fff;
        padding: 20px;
    }
    h2 {
        margin: 0 0 15px;
        font-size: 22px;
    }
    .card {
        background: #020617;
        padding: 18px;
        border-radius: 14px;
        overflow-x: auto;
        box-shadow: 0 10px 30px rgba(0,0,0,.25);
    }
    table {
        width: 100%;
        border-collapse: collapse;
        font-size: 14px;
        min-width: 980px;
    }
    th, td {
        padding: 12px 10px;
        border-bottom: 1px solid rgba(255,255,255,.08);
        vertical-align: top;
    }
    th {
        color: #93c5fd;
        text-align: left;
        font-weight: 700;
    }
    .status {
        font-weight: 700;
        text-transform: capitalize;
    }
    .pending { color: #fbbf24; }
    .processing { color: #60a5fa; }
    .successful { color: #22c55e; }
    .failed { color: #ef4444; }
    .unknown { color: #f97316; }

    .reply {
        max-width: 320px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        font-size: 12px;
        color: #cbd5e1;
    }

    .btn-group {
        display: flex;
        gap: 8px;
        flex-wrap: wrap;
    }

    .btn {
        padding: 7px 12px;
        border-radius: 8px;
        border: none;
        font-weight: 700;
        cursor: pointer;
        transition: .2s ease;
    }
    .btn:hover:not(:disabled) {
        transform: translateY(-1px);
        opacity: .95;
    }
    .btn:disabled {
        opacity: .65;
        cursor: not-allowed;
        transform: none;
    }
    .btn-check {
        background: #22c55e;
        color: #052e16;
    }
    .btn-retry {
        background: #f97316;
        color: #431407;
    }

    .toast {
        position: fixed;
        top: 20px;
        right: 20px;
        min-width: 240px;
        max-width: 360px;
        padding: 12px 14px;
        border-radius: 10px;
        color: #fff;
        font-size: 14px;
        box-shadow: 0 10px 25px rgba(0,0,0,.25);
        opacity: 0;
        transform: translateY(-10px);
        pointer-events: none;
        transition: all .25s ease;
        z-index: 9999;
    }
    .toast.show {
        opacity: 1;
        transform: translateY(0);
    }
    .toast.success { background: #166534; }
    .toast.error { background: #991b1b; }

    .muted {
        color: #94a3b8;
        font-size: 12px;
    }
</style>
</head>
<body>

<h2>IPE CLEARANCE — ADMIN PANEL</h2>

<div class="card">
    <table>
        <thead>
            <tr>
                <th>User</th>
                <th>Tracking ID</th>
                <th>Status</th>
                <th>Reply</th>
                <th>Price</th>
                <th>Date</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
        <?php if ($result && $result->num_rows > 0): ?>
            <?php while ($r = $result->fetch_assoc()): ?>
                <?php
                    $status = strtolower(trim((string)($r['status'] ?? 'pending')));
                    $trackingId = (string)$r['tracking_id'];
                ?>
                <tr data-row="<?= e($trackingId) ?>">
                    <td><?= e((string)$r['user']) ?></td>
                    <td><?= e($trackingId) ?></td>

                    <td class="status <?= e($status) ?>">
                        <?= e(ucfirst($status)) ?>
                    </td>

                    <td class="reply" title="<?= e((string)($r['reply'] ?: '-')) ?>">
                        <?= e((string)($r['reply'] ?: '-')) ?>
                    </td>

                    <td>₦<?= number_format((float)$r['price'], 2) ?></td>
                    <td><?= e(date('d M Y H:i', strtotime((string)$r['created_at']))) ?></td>

                    <td>
                        <div class="btn-group">
                            <button
                                type="button"
                                class="btn btn-check js-action-btn"
                                data-id="<?= e($trackingId) ?>"
                                data-action="check_status"
                            >
                                Check
                            </button>

                            <?php if ($status === 'pending'): ?>
                                <button
                                    type="button"
                                    class="btn btn-retry js-action-btn"
                                    data-id="<?= e($trackingId) ?>"
                                    data-action="retry_request"
                                >
                                    Retry
                                </button>
                            <?php endif; ?>
                        </div>
                    </td>
                </tr>
            <?php endwhile; ?>
        <?php else: ?>
            <tr>
                <td colspan="7" class="muted">No requests found.</td>
            </tr>
        <?php endif; ?>
        </tbody>
    </table>
</div>

<div id="toast" class="toast"></div>

<script>
(function () {
    const endpoint = "admin_ipe_requests.php";
    const toast = document.getElementById("toast");

    function showToast(message, type = "success") {
        toast.textContent = message;
        toast.className = `toast ${type} show`;

        clearTimeout(showToast._timer);
        showToast._timer = setTimeout(() => {
            toast.classList.remove("show");
        }, 3000);
    }

    function updateRetryButton(row, trackingId, showRetry) {
        const btnGroup = row.querySelector(".btn-group");
        let retryBtn = btnGroup.querySelector(".btn-retry");

        if (showRetry) {
            if (!retryBtn) {
                retryBtn = document.createElement("button");
                retryBtn.type = "button";
                retryBtn.className = "btn btn-retry js-action-btn";
                retryBtn.dataset.id = trackingId;
                retryBtn.dataset.action = "retry_request";
                retryBtn.textContent = "Retry";
                btnGroup.appendChild(retryBtn);
            }
        } else if (retryBtn) {
            retryBtn.remove();
        }
    }

    function setButtonLoading(button, loading) {
        const action = button.dataset.action;
        if (!button.dataset.originalText) {
            button.dataset.originalText = button.textContent;
        }

        if (loading) {
            button.disabled = true;
            button.textContent = action === "retry_request" ? "Retrying..." : "Checking...";
        } else {
            button.disabled = false;
            button.textContent = button.dataset.originalText;
        }
    }

    async function runAction(button) {
        const trackingId = button.dataset.id;
        const action = button.dataset.action;
        const row = document.querySelector(`tr[data-row="${CSS.escape(trackingId)}"]`);

        if (!row) {
            showToast("Unable to locate table row", "error");
            return;
        }

        const statusCell = row.querySelector(".status");
        const replyCell = row.querySelector(".reply");

        setButtonLoading(button, true);

        try {
            const body = new URLSearchParams({
                action: action,
                tracking_id: trackingId
            });

            const response = await fetch(endpoint, {
                method: "POST",
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
                },
                body: body.toString()
            });

            const data = await response.json();

            if (!response.ok || !data.success) {
                throw new Error(data.message || "Request failed");
            }

            statusCell.textContent = data.status.charAt(0).toUpperCase() + data.status.slice(1);
            statusCell.className = "status " + data.status;

            replyCell.textContent = data.reply || "-";
            replyCell.title = data.reply || "-";

            updateRetryButton(row, trackingId, !!data.show_retry);
            showToast(data.message || "Updated successfully", "success");
        } catch (error) {
            showToast(error.message || "Network error", "error");
        } finally {
            setButtonLoading(button, false);
        }
    }

    document.addEventListener("click", function (event) {
        const button = event.target.closest(".js-action-btn");
        if (!button) return;
        runAction(button);
    });
})();
</script>

</body>
</html>
