<?php
session_start();

$config = require __DIR__ . '/../lib/config.php';
require __DIR__ . '/../lib/db.php';
require __DIR__ . '/../lib/helpers.php';

/* Base + demo flag */
$base   = rtrim($config['base_url'] ?? '', '/');
$isDemo = !empty($config['demo_mode']);

/* Safer error mode */
if ($pdo instanceof PDO) {
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}

/* Best-guess client IP (IPv4/IPv6), handling common proxy headers. */
if (!function_exists('client_ip')) {
  function client_ip(): string {
    $candidates = [
      'HTTP_CF_CONNECTING_IP',   // Cloudflare
      'HTTP_X_FORWARDED_FOR',    // Standard proxy chain (may contain multiple)
      'HTTP_CLIENT_IP',
      'REMOTE_ADDR',
    ];
    foreach ($candidates as $key) {
      if (empty($_SERVER[$key])) continue;
      $raw = $_SERVER[$key];

      if ($key === 'HTTP_X_FORWARDED_FOR') {
        $parts = array_map('trim', explode(',', $raw));
        foreach ($parts as $part) {
          if (filter_var($part, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
            return $part;
          }
        }
        continue;
      }

      if (filter_var($raw, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
        return $raw;
      }
    }
    return 'unknown';
  }
}

/* Same alias normalisation used on the admin side */
function alias_slug($s) {
  $s = strtolower(trim($s));
  $s = preg_replace('/[^a-z0-9_-]+/', '-', $s);
  return trim($s, '-_') ?: 'share';
}

$token = $_GET['token'] ?? '';
$aliasParam = $_GET['a'] ?? '';

if (!preg_match('/^[a-f0-9-]{36}$/i', $token)) {
  http_response_code(400); echo "Invalid link."; exit;
}
if ($aliasParam === '') {
  http_response_code(400); echo "Missing share alias."; exit;
}
$alias = alias_slug($aliasParam);

/* Fetch share for this token + alias, also pull possible vehicle reg and request token */
$share = null;
try {
  $q = $pdo->prepare("
    SELECT
      s.*,
      r.token AS request_token,
      NULLIF(TRIM(r.reg_mark), '') AS vehicle_reg
    FROM request_shares s
    JOIN requests r ON r.id = s.request_id
    WHERE r.token = ? AND s.alias = ?
    LIMIT 1
  ");
  $q->execute([$token, $alias]);
  $share = $q->fetch();
} catch (Throwable $e) {
  http_response_code(500); echo "DB error: " . esc($e->getMessage()); exit;
}

if (!$share) {
  echo "Share not found.";
  exit;
}

/* Normalise vehicle reg for display (uppercase, no spaces) */
$vehicleReg = '';
if (!empty($share['vehicle_reg'])) {
  $vehicleReg = strtoupper(preg_replace('/\s+/', '', (string)$share['vehicle_reg']));
}

/* Expiry check */
if (!empty($share['expires_at']) && strtotime($share['expires_at']) < time()) {
  http_response_code(403); echo "This share link has expired."; exit;
}

$share_id     = (int)$share['id'];
$request_id   = (int)$share['request_id'];
$requestToken = (string)$share['request_token'];
$sessionKey   = 'share_ok_'.$request_id.'_'.$share_id;

/* ---- Raw image streaming (authorised only) + optional forced download ---- */
if (($_GET['raw'] ?? '') === '1') {
  if (empty($_SESSION[$sessionKey])) { http_response_code(403); echo "Unauthorized."; exit; }
  $fid = (int)($_GET['fid'] ?? 0);
  if ($fid <= 0) { http_response_code(400); echo "Bad request."; exit; }

  $fQ = $pdo->prepare("
    SELECT rf.filename, rf.original, r.token
    FROM request_share_files rsf
    JOIN request_shares s ON s.id = rsf.share_id
    JOIN requests r ON r.id = s.request_id
    JOIN request_files rf ON rf.id = rsf.file_id
    WHERE rsf.share_id=? AND s.id=? AND rf.request_id=? AND rf.id=?
    LIMIT 1
  ");
  $fQ->execute([$share_id, $share_id, $request_id, $fid]);
  $row = $fQ->fetch();
  if (!$row) { http_response_code(404); echo "Not found."; exit; }

  $filename = $row['filename'];
  $path = rtrim($config['upload_dir'], '/') . '/' . $row['token'] . '/' . $filename;
  if (!is_file($path)) { http_response_code(404); echo "Not found."; exit; }

  $allowed = ['jpg','jpeg','png','gif','webp','bmp','heic','svg'];
  $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
  if (!in_array($ext, $allowed, true)) { http_response_code(403); echo "Blocked."; exit; }

  $finfo = finfo_open(FILEINFO_MIME_TYPE);
  $mime = finfo_file($finfo, $path);
  finfo_close($finfo);

  // If dl=1, force a download with a friendly filename (use original if present)
  $forceDl = (isset($_GET['dl']) && $_GET['dl'] === '1');
  if ($forceDl) {
    $nice = $row['original'] ?: $filename;
    // strip any path parts just in case
    $nice = basename($nice);
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="'.$nice.'"');
  } else {
    header('Content-Type: '.$mime);
  }
  header('Content-Length: '.filesize($path));
  header('Cache-Control: private, max-age=86400');
  readfile($path);
  exit;
}

/* ---- ZIP all images (authorised only) ---- */
if (($_GET['zip'] ?? '') === '1') {
  if (empty($_SESSION[$sessionKey])) { http_response_code(403); echo "Unauthorized."; exit; }

  // Gather files for this share
  $fq = $pdo->prepare("
    SELECT rf.filename, rf.original
    FROM request_share_files rsf
    JOIN request_files rf ON rf.id = rsf.file_id
    WHERE rsf.share_id=? AND rf.request_id=?
    ORDER BY rf.id DESC
  ");
  $fq->execute([$share_id, $request_id]);
  $list = $fq->fetchAll();

  if (!$list) { http_response_code(404); echo "No images to download."; exit; }
  if (!class_exists('ZipArchive')) { http_response_code(500); echo "ZIP not supported on this server."; exit; }

  $tmp = tempnam(sys_get_temp_dir(), 'sharezip_') ?: null;
  if (!$tmp) { http_response_code(500); echo "Temp file error."; exit; }

  $zip = new ZipArchive();
  if ($zip->open($tmp, ZipArchive::OVERWRITE) !== true) {
    @unlink($tmp);
    http_response_code(500); echo "ZIP open error."; exit;
  }

  $allowed = ['jpg','jpeg','png','gif','webp','bmp','heic','svg'];
  $baseDir = rtrim($config['upload_dir'], '/') . '/' . $requestToken . '/';

  foreach ($list as $row) {
    $fn  = (string)$row['filename'];
    $ext = strtolower(pathinfo($fn, PATHINFO_EXTENSION));
    if (!in_array($ext, $allowed, true)) continue;

    $path = $baseDir . $fn;
    if (!is_file($path)) continue;

    $nice = $row['original'] ?: $fn;
    $nice = basename($nice);
    // make sure the name is safe inside the archive
    $nice = preg_replace('/[^\w\.\-\s]/', '_', $nice);
    $zip->addFile($path, $nice);
  }

  $zip->close();

  // If the archive ended up empty (e.g., all filtered out)
  if (!filesize($tmp)) { @unlink($tmp); http_response_code(404); echo "No images to download."; exit; }

  ignore_user_abort(true);
  set_time_limit(0);

  $labelParts = [];
  $labelParts[] = 'images';
  if ($vehicleReg) $labelParts[] = $vehicleReg;
  $labelParts[] = date('Ymd');
  $zipName = implode('-', $labelParts) . '.zip';

  header('Content-Type: application/zip');
  header('Content-Disposition: attachment; filename="'.$zipName.'"');
  header('Content-Length: ' . filesize($tmp));
  header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
  header('Pragma: no-cache');

  readfile($tmp);
  @unlink($tmp);
  exit;
}

/* Handle code form */
$error = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $code = trim($_POST['code'] ?? '');
  if (!preg_match('/^[0-9]{4}$/', $code)) {
    $error = "Please enter the 4-digit code.";
  } else {
    if (password_verify($code, $share['code_hash'])) {
      $_SESSION[$sessionKey] = true;
      $qs = 'token='.urlencode($token).'&a='.urlencode($alias);
      header('Location: share.php?'.$qs);
      exit;
    } else {
      $error = "That code is not correct.";
    }
  }
}

$authorized = !empty($_SESSION[$sessionKey]);

/* ---- NEW: Log a note the first time this share is viewed in this session ---- */
if ($authorized) {
  $loggedKey = 'share_view_logged_'.$request_id.'_'.$share_id;
  if (empty($_SESSION[$loggedKey])) {
    try {
      $ip = client_ip();
      $ua = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
      $ua = substr($ua, 0, 200);
      $note = "Share '{$alias}' viewed from IP: {$ip} • UA: {$ua}";
      $ins = $pdo->prepare("INSERT INTO request_notes (request_id, notes) VALUES (?, ?)");
      $ins->execute([$request_id, $note]);
    } catch (Throwable $e) {
      // Do not block the page if logging fails.
      // error_log('share view note failed: ' . $e->getMessage());
    }
    $_SESSION[$loggedKey] = true;
  }
}

/* Load files in this share */
$files = [];
if ($authorized) {
  $fq = $pdo->prepare("
    SELECT rf.id, rf.filename, rf.original
    FROM request_share_files rsf
    JOIN request_files rf ON rf.id = rsf.file_id
    WHERE rsf.share_id=? AND rf.request_id=?
    ORDER BY rf.id DESC
  ");
  $fq->execute([$share_id, $request_id]);
  $files = $fq->fetchAll();
}
?>
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>View shared images<?= $isDemo ? ' (Demo Mode)' : '' ?></title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    :root{
      --brand:#0f6fff;
      --bg:#f6f8fb;
      --text:#1b1f23;
      --muted:#6b7280;
      --card:#ffffff;
      --border:#e5e7eb;
      --shadow:0 10px 25px rgba(0,0,0,.06);
      --btn:#0f6fff;
      --btn-border:#0f6fff;
    }
    *{box-sizing:border-box}
    html,body{height:100%}
    body{
      margin:0;
      font-family:system-ui,Segoe UI,Roboto,Arial,sans-serif;
      color:var(--text);
      background:linear-gradient(180deg, #ffffff 0%, var(--bg) 100%);
    }
    header{
      position:sticky;top:0;z-index:10;
      background:#fff;border-bottom:1px solid var(--border);
      box-shadow:0 2px 10px rgba(0,0,0,.02);
    }
    .wrap{max-width:980px;margin:0 auto;padding:18px 16px;display:flex;align-items:center;justify-content:space-between}
    .brand{
      display:flex;align-items:center;gap:12px;font-weight:700;font-size:18px;color:#0b1731;
    }
    .brand .dot{width:10px;height:10px;background:var(--brand);border-radius:999px;box-shadow:0 0 0 4px rgba(15,111,255,.15)}
    .brand .reg{font-weight:600;color:var(--muted);letter-spacing:.5px}
    .demo-badge{
      background:#f8d7da;color:#842029;border:1px solid #f5c2c7;
      border-radius:999px;padding:4px 8px;font-size:12px;box-shadow:0 2px 8px rgba(0,0,0,.08)
    }
    main .container{max-width:980px;margin:26px auto;padding:0 16px;}
    .card{background:var(--card);border:1px solid var(--border);border-radius:14px;box-shadow:var(--shadow);}
    .card .body{padding:18px}
    h1{font-size:20px;margin:0 0 10px}
    p.lead{color:var(--muted);margin:4px 0 18px}
    .alert{padding:10px;border-radius:10px;margin:0 0 14px;border:1px solid #f5b5b5;background:#fff5f5;color:#7f1d1d}
    .row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
    .actions-top{display:flex;gap:10px;align-items:center;justify-content:flex-end;margin-bottom:12px}

    /* Buttons */
    .btn{
      appearance:none;border:1px solid var(--btn-border);background:var(--btn);color:#fff;
      padding:10px 14px;border-radius:10px;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;gap:8px;text-decoration:none;
      transition:.15s transform ease, .15s opacity ease;
    }
    .btn:hover{transform:translateY(-1px);opacity:.95}
    .btn.secondary{background:#fff;color:var(--btn);border-color:var(--btn-border)}
    .btn.small{padding:7px 10px;border-radius:8px;font-size:12px;font-weight:600}

    /* Gallery */
    .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}
    .tile{border:1px solid var(--border);border-radius:12px;overflow:hidden;background:#fff;transition:transform .12s ease, box-shadow .12s ease;}
    .tile:hover{transform:translateY(-2px);box-shadow:var(--shadow)}
    .tile img{width:100%;height:auto;display:block}
    .tile .meta{padding:8px 10px;color:var(--muted);font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    .tile .row{justify-content:space-between;padding:8px 10px;border-top:1px solid var(--border)}

    /* Lightbox */
    .lightbox{
      display:none;position:fixed;inset:0;background:rgba(10,12,16,.92);
      justify-content:center;align-items:center;z-index:9999;
    }
    .lightbox img{max-width:92vw;max-height:88vh;border-radius:10px;box-shadow:0 10px 30px rgba(0,0,0,.35)}
    .lb-btn{position:absolute;color:#fff;font-size:34px;font-weight:800;cursor:pointer;user-select:none;padding:8px 12px;line-height:1}
    .lb-close{top:16px;right:22px}
    .lb-prev{top:50%;left:22px;transform:translateY(-50%)}
    .lb-next{top:50%;right:22px;transform:translateY(-50%)}
    .lb-btn:hover{opacity:.9}

    footer{margin:28px 0 40px;text-align:center;color:var(--muted);font-size:12px}
  </style>
</head>
<body>
  <header>
    <div class="wrap">
      <div class="brand">
        <span class="dot" aria-hidden="true"></span>
        Shared Images  &middot;
        <?php if ($vehicleReg): ?>
          <span class="reg"> <?= esc($vehicleReg) ?></span>
        <?php endif; ?>
      </div>
      <?php if ($isDemo): ?><span class="demo-badge">DEMO</span><?php endif; ?>
    </div>
  </header>

  <main>
    <div class="container">
      <?php if (!$authorized): ?>
        <div class="card">
          <div class="body">
            <h1>Enter access code</h1>
            <p class="lead">A 4-digit code is required to view these images.</p>
            <?php if ($error): ?><div class="alert"><?= esc($error) ?></div><?php endif; ?>

            <!-- Pretty 4-box PIN inputs that post into a hidden single field -->
            <form method="post" id="codeForm" autocomplete="one-time-code">
              <input type="hidden" name="code" id="codeHidden">
              <div class="pin">
                <input inputmode="numeric" pattern="[0-9]*" maxlength="1" aria-label="Digit 1">
                <input inputmode="numeric" pattern="[0-9]*" maxlength="1" aria-label="Digit 2">
                <input inputmode="numeric" pattern="[0-9]*" maxlength="1" aria-label="Digit 3">
                <input inputmode="numeric" pattern="[0-9]*" maxlength="1" aria-label="Digit 4">
              </div>
              <div class="actions" style="display:flex;justify-content:center;margin-top:12px">
                <button type="submit" class="btn">View images</button>
              </div>
            </form>
            <p class="muted" style="text-align:center;margin-top:10px">Trouble entering the code? Try typing the digits one by one.</p>
          </div>
        </div>
      <?php else: ?>
        <div class="card">
          <div class="body">
            <div style="display:flex;align-items:center;justify-content:space-between;gap:12px">
              <div>
                <h1 style="margin:0">Images</h1>
                <p class="lead" style="margin-top:6px">Tap a photo to view full size. Use arrow keys or on-screen arrows to navigate.</p>
              </div>
              <?php if (!empty($files)): ?>
                <div class="actions-top">
                  <?php
                    $zipHref = 'share.php?token=' . urlencode($token) . '&a=' . urlencode($alias) . '&zip=1';
                  ?>
                  <a class="btn secondary" href="<?= esc($zipHref) ?>" title="Download all images as ZIP">
                    <!-- simple download icon -->
                    <span aria-hidden="true">⬇️</span> Download all
                  </a>
                </div>
              <?php endif; ?>
            </div>

            <?php if (empty($files)): ?>
              <p class="muted">No images are available in this share.</p>
            <?php else: ?>
              <div class="grid">
                <?php foreach ($files as $i => $f):
                  $viewSrc = 'share.php?token=' . urlencode($token) . '&a=' . urlencode($alias) . '&raw=1&fid=' . (int)$f['id'];
                  $dlSrc   = $viewSrc . '&dl=1';
                ?>
                  <div class="tile">
                    <img src="<?= esc($viewSrc) ?>" alt="" data-index="<?= (int)$i ?>">
                    <div class="meta" title="<?= esc($f['original'] ?: $f['filename']) ?>">
                      <?= esc($f['original'] ?: $f['filename']) ?>
                    </div>
                    <div class="row">
                      <span style="font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">
                        <?= esc(pathinfo($f['original'] ?: $f['filename'], PATHINFO_EXTENSION)) ?> &nbsp;
                      </span>
                      <a class="btn small secondary" href="<?= esc($dlSrc) ?>" title="Download this image">
                        ⬇️ Download
                      </a>
                    </div>
                  </div>
                <?php endforeach; ?>
              </div>
            <?php endif; ?>
          </div>
        </div>

        <!-- Lightbox -->
        <div id="lightbox" class="lightbox" aria-hidden="true">
          <span class="lb-btn lb-close" title="Close">&times;</span>
          <span class="lb-btn lb-prev" title="Previous">&#10094;</span>
          <img id="lightbox-img" src="" alt="">
          <span class="lb-btn lb-next" title="Next">&#10095;</span>
        </div>
      <?php endif; ?>

      <footer>
        &copy; <?= date('Y') ?> Mount Pleasant Motoring Services Ltd
      </footer>
    </div>
  </main>

  <script>
    // PIN input UX (combines 4 boxes into hidden "code")
    (function(){
      const boxes = Array.from(document.querySelectorAll('.pin input'));
      const hidden = document.getElementById('codeHidden');
      const form = document.getElementById('codeForm');
      if (!boxes.length || !hidden || !form) return;

      boxes[0].focus();

      boxes.forEach((box, idx) => {
        box.addEventListener('input', () => {
          box.value = box.value.replace(/\D/g,'').slice(0,1);
          if (box.value && idx < boxes.length - 1) boxes[idx+1].focus();
        });
        box.addEventListener('keydown', (e)=>{
          if (e.key === 'Backspace' && !box.value && idx > 0) {
            boxes[idx-1].focus();
          }
        });
      });

      form.addEventListener('submit', ()=>{
        const code = boxes.map(b => b.value).join('');
        hidden.value = code;
      });
    })();

    // Lightbox gallery
    (function(){
      const thumbs = Array.from(document.querySelectorAll('.tile img'));
      if (!thumbs.length) return;

      const lb = document.getElementById('lightbox');
      const lbImg = document.getElementById('lightbox-img');
      const prev = lb.querySelector('.lb-prev');
      const next = lb.querySelector('.lb-next');
      const close = lb.querySelector('.lb-close');
      let i = 0;

      function open(k){ i=k; lbImg.src = thumbs[i].src; lb.style.display='flex'; lb.setAttribute('aria-hidden','false'); }
      function p(){ i=(i-1+thumbs.length)%thumbs.length; lbImg.src = thumbs[i].src; }
      function n(){ i=(i+1)%thumbs.length; lbImg.src = thumbs[i].src; }
      function x(){ lb.style.display='none'; lb.setAttribute('aria-hidden','true'); }

      thumbs.forEach((im,k)=> im.addEventListener('click', ()=> open(k)));
      prev.addEventListener('click', p); next.addEventListener('click', n); close.addEventListener('click', x);

      document.addEventListener('keydown', e=>{
        if(lb.style.display==='flex'){
          if(e.key==='ArrowLeft') p();
          if(e.key==='ArrowRight') n();
          if(e.key==='Escape') x();
        }
      });

      // simple swipe support
      let sx=0, sy=0;
      lb.addEventListener('touchstart', (e)=>{ if(!e.touches[0]) return; sx=e.touches[0].clientX; sy=e.touches[0].clientY; }, {passive:true});
      lb.addEventListener('touchend', (e)=>{
        const t = e.changedTouches[0]; if(!t) return;
        const dx = t.clientX - sx, dy = t.clientY - sy;
        if (Math.abs(dx) > 30 && Math.abs(dx) > Math.abs(dy)) { dx > 0 ? p() : n(); }
      }, {passive:true});
    })();
  </script>
</body>
</html>
