<?php

/**
 * ============================================================
 *  Booking Availability Middleware
 *  Interakt WhatsApp Template  <-->  Magento 1.9 REST API
 * ============================================================
 *  Endpoints
 *  ---------
 *  GET  ?exec=av1_<HMAC_TOKEN>_<BOOKING_ID>   -> Available
 *  GET  ?exec=av0_<HMAC_TOKEN>_<BOOKING_ID>   -> Not Available
 * 
 *  Security layers:
 *  1. HMAC-SHA256 signature validation
 *  2. Token expiry check
 *  3. Per-booking-ID one-time use (date-keyed JSON file) Once ANY action fires for a booking ID, ALL links for that booking ID are permanently blocked.
 *
 *  PHP 8.1.2
 * Satyam on 25-05-2026
 * ============================================================
 */

declare(strict_types=1);

// -----------------------
// 0. CONFIGURATION  — move to .env in production
// -----------------------
define('HMAC_SECRET',          '7703844eb6ec6d2ce7e92352e3e8b4e3');
define('TOKEN_TTL_SECONDS',    3600);          // link expires in 1 hour

// Magento 1.9 REST
define('MAGENTO_BASE_URL',     'https://m.ydrooms.space/');
define('MAGENTO_API_TOKEN',    'YOUR_MAGENTO_REST_API_TOKEN');

// Booking template name (must match exactly in Interakt)
define('BOOKING_TEMPLATE_NAME', 'booking_inquiry');   // your template's name in Interakt

// -----------------------
// 1. SECURITY HELPERS
// -----------------------

/**
 * Generate a signed, time-limited token for a booking action link.
 * Embed this in your wa.me URL or Interakt template button URL.
 *
 * Usage (call from your booking creation script):
 *   $token = generateActionToken('av1', '1023');
 *   $url   = "https://yourdomain.com/booking_middleware.php?exec=av1_{$token}_1023";
 */
function generateActionToken(string $action, string $bookingId): string
{
    $expires = time() + TOKEN_TTL_SECONDS;
    $payload = "{$action}|{$bookingId}|{$expires}";
    $sig     = hash_hmac('sha256', $payload, HMAC_SECRET);
    // encode as: expires_sig  (booking ID is passed separately in the URL)
    return urlencode("{$expires}_{$sig}");
}

/**
 * Validate the token extracted from ?exec=
 * Returns ['valid' => true, 'action' => 'av1', 'booking_id' => '1023']
 * or      ['valid' => false, 'error'  => '...']
 */
function validateExecParam(string $exec): array
{
    // format: action_expires_sig_bookingId
    $parts = explode('_', $exec, 4);
    if (count($parts) !== 4) {
        return ['valid' => false, 'error' => 'Malformed request.' . json_encode($parts)];
    }

    [$action, $expires, $sig, $bookingId] = $parts;

    // Check allowed actions
    if (!in_array($action, ['av1', 'av0'], true)) {
        return ['valid' => false, 'error' => 'Unknown action.' . json_encode($action)];
    }

    // Check expiry
    if (time() > (int)$expires) {
        return ['valid' => false, 'error' => 'This link has expired. Please ask the customer to resend their inquiry.'];
    }

    // Verify HMAC signature
    $payload     = "{$action}|{$bookingId}|{$expires}";
    $expectedSig = hash_hmac('sha256', $payload, HMAC_SECRET);
    if (!hash_equals($expectedSig, $sig)) {
        return ['valid' => false, 'error' => 'Invalid or tampered link.'];
    }

    // Sanitize booking ID (numeric only)
    if (!ctype_digit($bookingId)) {
        return ['valid' => false, 'error' => 'Invalid booking ID format.'];
    }

    return ['valid' => true, 'action' => $action, 'booking_id' => $bookingId];
}

// -----------------------
// 2. MAGENTO 1.9 REST API HELPER
// -----------------------

/**
 * Call Magento 1.9 custom REST endpoint.
 * Adjust the endpoint path to match your Magento module's route.
 */
function updateMagentoBooking(string $bookingId, string $status): array
{
    $url = MAGENTO_BASE_URL . '/api/rest/bookings/' . urlencode($bookingId);

    $payload = json_encode([
        'booking_id'          => $bookingId,
        'availability_status' => $status,         // 'available' | 'not_available' | 'other_available'
        'updated_at'          => date('Y-m-d H:i:s'),
        'updated_by'          => 'whatsapp_manager',
    ]);

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST  => 'PUT',
        CURLOPT_POSTFIELDS     => $payload,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 15,
        CURLOPT_HTTPHEADER     => [
            'Content-Type: application/json',
            'Accept: application/json',
            'Authorization: Bearer ' . MAGENTO_API_TOKEN,
        ],
        CURLOPT_SSL_VERIFYPEER => true,
    ]);

    $response   = curl_exec($ch);
    $httpCode   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError  = curl_error($ch);
    curl_close($ch);

    if ($curlError) {
        return ['success' => false, 'error' => "cURL error: {$curlError}"];
    }

    $decoded = json_decode($response, true);

    if ($httpCode >= 200 && $httpCode < 300) {
        return ['success' => true, 'data' => $decoded];
    }

    return [
        'success' => false,
        'error'   => "Magento returned HTTP {$httpCode}: " . ($decoded['message'] ?? $response),
    ];
}

// -----------------------
// 4. LOGGING
// -----------------------

function logEvent(string $level, string $message, array $context = []): void
{
    $logFile = __DIR__ . '/logs/booking_middleware.log';
    $dir     = dirname($logFile);

    if (!is_dir($dir)) {
        mkdir($dir, 0750, true);
    }

    $line = sprintf(
        "[%s] [%s] %s %s\n",
        date('Y-m-d H:i:s'),
        strtoupper($level),
        $message,
        $context ? json_encode($context) : ''
    );

    file_put_contents($logFile, $line, FILE_APPEND | LOCK_EX);
}

// -----------------------
// 5. HTML CONFIRMATION PAGE (shown to manager)
// -----------------------

function renderConfirmationPage(bool $success, string $title, string $message, string $bookingId = ''): never
{
    $statusColor   = $success ? '#1a7a4a' : '#b91c1c';
    $statusBg      = $success ? '#f0fdf4' : '#fef2f2';
    $icon          = $success ? '✅' : '❌';
    $bookingIdHtml = $bookingId !== ''
        ? "<p class=\"meta\">Booking ID: <strong>{$bookingId}</strong></p>"
        : '';

    http_response_code($success ? 200 : 400);
    header('Content-Type: text/html; charset=UTF-8');
    echo <<<HTML
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Booking Response</title>
      <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }
        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
               background: #f4f4f5; display: flex; align-items: center;
               justify-content: center; min-height: 100vh; padding: 20px; }
        .card { background: #fff; border-radius: 12px; padding: 36px 32px;
                max-width: 420px; width: 100%; text-align: center;
                box-shadow: 0 1px 4px rgba(0,0,0,.08); }
        .icon { font-size: 48px; margin-bottom: 16px; }
        .status { display: inline-block; background: {$statusBg}; color: {$statusColor};
                  font-size: 13px; font-weight: 600; padding: 4px 14px;
                  border-radius: 999px; margin-bottom: 14px; }
        h1 { font-size: 20px; font-weight: 600; color: #111; margin-bottom: 10px; }
        p  { font-size: 14px; color: #555; line-height: 1.6; }
        .meta { margin-top: 20px; font-size: 12px; color: #999; }
      </style>
    </head>
    <body>
      <div class="card">
        <div class="icon">{$icon}</div>
        <div class="status">{$title}</div>
        <h1>{$message}</h1>
        {$bookingIdHtml}
        <p class="meta">You can close this window.</p>
      </div>
    </body>
    </html>
    HTML;
    exit;
}

// -----------------------
// 6. ROUTER — handle GET (manager button click)
//            handle POST (Interakt webhook / internal trigger)
// -----------------------

$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';

// - 6a. GET — Manager clicked a button URL -
if ($method === 'GET' && isset($_GET['exec'])) {

    $exec       = trim($_GET['exec']);
    $validation = validateExecParam($exec);

    if (!$validation['valid']) {
        logEvent('warn', 'Invalid exec param', ['exec' => $exec, 'error' => $validation['error']]);
        renderConfirmationPage(false, 'Invalid Request', $validation['error']);
    }

    $action    = $validation['action'];
    $bookingId = $validation['booking_id'];

    // Map action code -> human label + Magento status
    $actionMap = [
        'av1' => ['label' => 'Available',             'status' => 'available',       'emoji' => '✅'],
        'av0' => ['label' => 'Not Available',          'status' => 'not_available',   'emoji' => '❌'],
        'avo' => ['label' => 'Other Room Available',   'status' => 'other_available', 'emoji' => '🔄'],
    ];
    $meta = $actionMap[$action];

    logEvent('info', 'Manager action received', [
        'booking_id' => $bookingId,
        'action'     => $action,
        'label'      => $meta['label'],
    ]);

    // Step 1 — Update Magento booking
    $magentoResult = updateMagentoBooking($bookingId, $meta['status']);

    if (!$magentoResult['success']) {
        logEvent('error', 'Magento update failed', [
            'booking_id' => $bookingId,
            'error'      => $magentoResult['error'],
        ]);
        renderConfirmationPage(
            false,
            'Update Failed',
            'Could not update booking status. Please contact support.',
            $bookingId
        );
    }

    logEvent('info', 'Magento booking updated', ['booking_id' => $bookingId, 'status' => $meta['status']]);

    // Step 3 — Show confirmation page to manager in browser
    renderConfirmationPage(
        true,
        $meta['label'],
        "Booking #{$bookingId} updated successfully.",
        $bookingId
    );
}

// - 6c. Fallback — unknown request -
http_response_code(400);
echo json_encode(['success' => false, 'error' => 'Invalid request']);
exit;
