<?php
/**
 * LUPMIS2 PWA — Iframe embed entry point
 *
 * Same SSO model as index.php (cookie validate → session → inject
 * window.LUPMIS_SESSION), with three things added for the iframe channel
 * defined by LUPMIS2_Reusable_Mapping_Concept.docx §3.2 / §4 and the
 * Permit Map Integration document §2:
 *
 *   1. URL parameters (mode, lon, lat, zoom, upn, basemap, application_code)
 *      are parsed and exposed as `window.LUPMIS_EMBED` so the PWA can
 *      run in a slim, single-purpose mode (see main.js + src/embed-bridge.js).
 *   2. `Content-Security-Policy: frame-ancestors` restricts who may embed
 *      this page — never `*`. The list comes from EMBED_ALLOWED_PARENTS
 *      below and should be tightened to the real permitting host once it
 *      is confirmed.
 *   3. A body class hint (`embed embed-mode-permit`) is set client-side
 *      via the inline script so CSS can hide the unrelated chrome (navbar,
 *      bottom dock, account offcanvas, etc.).
 */
session_start();

// Strip any inherited X-Frame-Options header so CSP frame-ancestors (set
// below) is the only iframe-policy header in the response. Apache often
// sets `X-Frame-Options: SAMEORIGIN` as a default security header for
// every response; without this removal Safari (and other browsers) honour
// X-Frame-Options over CSP frame-ancestors, blocking the legitimate
// embedder. .htaccess also unsets it at the Apache level — this PHP call
// is defence in depth in case mod_headers is unavailable.
header_remove('X-Frame-Options');

// ────────────────────────────────────────────────────────────────────────────
// SSO authentication — validate the cookie if we don't already have a session
// (same logic as index.php)
// ────────────────────────────────────────────────────────────────────────────
if (!isset($_SESSION['user_id']) && isset($_COOKIE['sso_auth_token'])) {
    $plainToken   = $_COOKIE['sso_auth_token'];
    $validate_url = 'https://lupmis4luspa.org/sso/validate?token=' . urlencode($plainToken);

    $curl = curl_init();
    curl_setopt_array($curl, [
        CURLOPT_URL            => $validate_url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING       => "",
        CURLOPT_MAXREDIRS      => 10,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST  => "GET",
        CURLOPT_HTTPHEADER     => [ "Content-Type: application/xml" ],
    ]);
    $response = curl_exec($curl);
    $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    curl_close($curl);

    if ($httpCode === 200) {
        $data = json_decode($response, true);
        if (
            is_array($data)
            && isset($data['valid']) && $data['valid'] === true
            && isset($data['logged_in_user']) && is_array($data['logged_in_user'])
        ) {
            foreach ($data['logged_in_user'] as $key => $value) {
                $_SESSION[$key] = $value;
            }
        }
    } else {
        setcookie('sso_auth_token', '', time() - 3600, '/', '.lupmis4luspa.org');
    }
}

// ────────────────────────────────────────────────────────────────────────────
// Production access guard — render an in-iframe "Sign in required" page
// instead of a 302 redirect.
//
// Why not redirect like index.php does? A 302 inside an <iframe> reloads
// the IFRAME, not the parent window — and the LUSPA login page typically
// refuses to be framed (X-Frame-Options), so the embedder ends up with a
// blank / "refused to connect" iframe with no clear way for the user to
// authenticate. The HTML page below uses target="_top" on its sign-in
// button so the click navigates the parent window to the SSO portal,
// preserving the user's path back to the permits page after login.
// ────────────────────────────────────────────────────────────────────────────
$host = $_SERVER['HTTP_HOST'] ?? '';
$isProduction = (bool) preg_match('/(^|\.)lupmis4luspa\.org$/i', $host);
if ($isProduction && !isset($_SESSION['user_id'])) {
    // CSP / frame-ancestors must still match the embed's policy so the
    // permits page can display this auth-required page in the iframe.
    $EMBED_ALLOWED_PARENTS = [
        'https://lupmis4luspa.org',
    ];
    $frameAncestors = "'self' " . implode(' ', $EMBED_ALLOWED_PARENTS);
    header("Content-Security-Policy: frame-ancestors {$frameAncestors}");
    header('Content-Type: text/html; charset=utf-8');
    header('Cache-Control: no-store, must-revalidate');
    header('X-Embed-Auth-Status: required'); // diagnostic for the permits team
    http_response_code(401);
    ?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>LUPMIS2 — Sign in required</title>
  <style>
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
      margin: 0; padding: 16px;
      background: #f8fafc;
      color: #1e1a4b;
      display: flex; align-items: center; justify-content: center;
      min-height: 100vh; min-height: 100svh;
      box-sizing: border-box;
    }
    .card {
      max-width: 420px; width: 100%;
      padding: 32px 28px;
      background: #fff;
      border: 1px solid #e5e7eb;
      border-radius: 12px;
      box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
      text-align: center;
    }
    .icon { font-size: 38px; line-height: 1; margin-bottom: 10px; }
    h1 { margin: 0 0 12px; font-size: 1.25rem; color: #1e1a4b; }
    p  { margin: 0 0 16px; color: #4b5563; line-height: 1.5; }
    a.cta {
      display: inline-block; margin-top: 4px;
      padding: 10px 18px; border-radius: 8px;
      background: #005eb8; color: #fff;
      text-decoration: none; font-weight: 600;
    }
    a.cta:hover { background: #004a92; }
    .hint { font-size: 0.85rem; color: #6b7280; margin-top: 16px; }
  </style>
</head>
<body>
  <div class="card">
    <div class="icon" aria-hidden="true">🔒</div>
    <h1>Sign in to view the map</h1>
    <p>The LUPMIS2 map can only be loaded after you sign in to the LUSPA portal.</p>
    <a href="https://lupmis4luspa.org/" target="_top" class="cta" rel="noopener">
      Open LUSPA sign-in
    </a>
    <p class="hint">After signing in, return to this page and refresh to load the map.</p>
  </div>
</body>
</html>
    <?php
    exit;
}

// ────────────────────────────────────────────────────────────────────────────
// Session payload (same shape as index.php)
// ────────────────────────────────────────────────────────────────────────────
$payload = [];
if (isset($_SESSION['user_id'])) {
    $payload = [
        'user_id'     => $_SESSION['user_id']     ?? null,
        'ua_id'       => $_SESSION['ua_id']       ?? null,
        'username'    => $_SESSION['username']    ?? null,
        'title'       => $_SESSION['title']       ?? null,
        'full_name'   => $_SESSION['full_name']   ?? null,
        'email'       => $_SESSION['email']       ?? null,
        'user_type'   => $_SESSION['user_type']   ?? null,
        'phone'       => $_SESSION['phone']       ?? null,
        'ua_position' => $_SESSION['ua_position'] ?? null,
        'region_id'   => $_SESSION['region_id']   ?? null,
        'district_id' => $_SESSION['district_id'] ?? null,
    ];
}

// ────────────────────────────────────────────────────────────────────────────
// Embed config — parse the contract's URL parameters (see Permit Map
// Integration doc §2.1). Strict whitelisting + type coercion keeps invalid
// input from reaching the PWA.
// ────────────────────────────────────────────────────────────────────────────
$validBasemaps = ['topo','osm','satellite','googlesat','carto-light','carto-dark','none'];
$validModes    = ['permit'];

$mode    = isset($_GET['mode'])    ? (string)$_GET['mode']    : 'permit';
$basemap = isset($_GET['basemap']) ? (string)$_GET['basemap'] : null;
$upn     = isset($_GET['upn'])     ? (string)$_GET['upn']     : null;
$appCode = isset($_GET['application_code']) ? (string)$_GET['application_code'] : null;

$lon  = isset($_GET['lon'])  && is_numeric($_GET['lon'])  ? (float)$_GET['lon']  : null;
$lat  = isset($_GET['lat'])  && is_numeric($_GET['lat'])  ? (float)$_GET['lat']  : null;
$zoom = isset($_GET['zoom']) && is_numeric($_GET['zoom']) ? (int)$_GET['zoom']   : null;

$embed = [
    'mode'             => in_array($mode, $validModes, true) ? $mode : 'permit',
    'lon'              => $lon,
    'lat'              => $lat,
    'zoom'             => $zoom,
    'upn'              => $upn,
    'basemap'          => ($basemap && in_array($basemap, $validBasemaps, true)) ? $basemap : null,
    'application_code' => $appCode,
];

// ────────────────────────────────────────────────────────────────────────────
// Read the built index.html and inject the session + embed config
// ────────────────────────────────────────────────────────────────────────────
$indexPath = __DIR__ . '/index.html';
$html = is_readable($indexPath)
    ? file_get_contents($indexPath)
    : '<!DOCTYPE html><html><body><h1>LUPMIS2 PWA</h1><p>index.html is missing.</p></body></html>';

$jsonFlags    = JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT;
$sessionJson  = json_encode($payload, $jsonFlags);
$embedJson    = json_encode($embed,   $jsonFlags);
$inject =
    "<script>window.LUPMIS_SESSION = {$sessionJson};" .
    "window.LUPMIS_EMBED = {$embedJson};" .
    // Set the body class as early as possible so CSS rules apply on first paint.
    "document.addEventListener('DOMContentLoaded',function(){" .
    "document.body.classList.add('embed','embed-mode-' + (window.LUPMIS_EMBED.mode || 'permit'));" .
    "});</script>";

$html = preg_replace('/<head\b[^>]*>/i', '$0' . "\n  " . $inject, $html, 1);

// ────────────────────────────────────────────────────────────────────────────
// Headers — frame-ancestors restricts who may embed; tighten this list once
// the real permitting host is confirmed. NEVER use `frame-ancestors *`.
// ────────────────────────────────────────────────────────────────────────────
$EMBED_ALLOWED_PARENTS = [
    'https://lupmis4luspa.org',
    // Add local dev parents here if needed, e.g. 'http://localhost:8000'.
];
$frameAncestors = "'self' " . implode(' ', $EMBED_ALLOWED_PARENTS);

header("Content-Security-Policy: frame-ancestors {$frameAncestors}");
header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: no-store, must-revalidate');
header('Pragma: no-cache');
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: strict-origin-when-cross-origin');

echo $html;
