<?php
declare(strict_types=1);

/**
 * _cors.php (robust CORS handler)
 *
 * Supports BOTH:
 * 1) Credentialed requests (credentials: "include") -> MUST echo exact Origin (never "*")
 * 2) Non-credentialed requests (credentials: "omit") -> can use "*"
 *
 * Fixes:
 * - Preflight wildcard origin not allowed
 * - Origin mismatch (no trailing slashes)
 * - OPTIONS must exit before sessions/output
 * - Handles custom headers requested by browser in preflight
 * - Avoids duplicate headers
 *
 * IMPORTANT:
 * If you are using credentials:"include" from the browser, you MUST:
 * - allow the exact origin (no "*")
 * - return Access-Control-Allow-Credentials: true
 */

$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';

// Browser may send these during preflight
$reqHeaders = $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'] ?? '';
$reqMethod  = $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] ?? '';

// ✅ Origins must match exactly (no trailing slash)
$allowedOrigins = [
  'http://localhost:5174',
  'http://127.0.0.1:5174',
  'http://localhost:3000',
  'http://127.0.0.1:3000',
  'https://finsapdev.qhtestingserver.com',
];

// Remove any previously set CORS headers (prevents duplicates)
header_remove('Access-Control-Allow-Origin');
header_remove('Access-Control-Allow-Credentials');
header_remove('Access-Control-Allow-Methods');
header_remove('Access-Control-Allow-Headers');
header_remove('Access-Control-Max-Age');
header_remove('Vary');

$originAllowed = ($origin !== '' && in_array($origin, $allowedOrigins, true));

/**
 * Decide whether to treat as "credentialed CORS" or not:
 * - If Origin is allowed -> we can safely echo it and allow credentials.
 * - If Origin is not allowed but Origin exists -> we should block.
 * - If Origin missing -> likely same-origin/server-to-server; do nothing.
 *
 * NOTE: We cannot reliably detect if the browser used credentials:"include".
 * So we follow safest policy:
 * - Allowed origin -> echo origin + allow credentials (works for both include/omit)
 * - Disallowed origin -> block (for browser calls)
 */
if ($originAllowed) {
  header("Access-Control-Allow-Origin: $origin");
  header('Vary: Origin');

  // Allow credentials for allowed origins (safe and helps include-mode)
  header('Access-Control-Allow-Credentials: true');

  // Allow methods
  header('Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS');

  // Allow headers: echo requested headers if present (most compatible)
  if ($reqHeaders) {
    header("Access-Control-Allow-Headers: $reqHeaders");
  } else {
    header('Access-Control-Allow-Headers: Content-Type, Accept, Authorization, X-Requested-With, X-Idempotency-Key');
  }

  header('Access-Control-Max-Age: 86400');
}

// ✅ Preflight: must exit immediately, no output, no session_start
if ($method === 'OPTIONS') {
  // If allowed, 204; if not allowed but Origin exists, 403
  http_response_code($originAllowed ? 204 : 403);
  exit;
}

// If browser request has an Origin but it's not allowed, fail fast (helps debugging)
if ($origin !== '' && !$originAllowed) {
  header('Content-Type: application/json; charset=utf-8');
  http_response_code(403);
  echo json_encode([
    'ok' => false,
    'error' => 'CORS origin not allowed',
    'origin' => $origin,
    'allowed' => $allowedOrigins,
    'hint' => 'Add this exact Origin to the allowlist (no trailing slash). Also ensure endpoint does not redirect.',
  ], JSON_UNESCAPED_SLASHES);
  exit;
}
