#!/usr/bin/env python3
"""Generate HTML gallery for indkorsel person-detection snapshots.
Called via shell_command after each new snapshot is saved.
Output: /config/www/snapshots/indkorsel_gallery.html
"""
import os
import glob
from datetime import datetime

SNAPSHOT_DIR = "/config/www/snapshots/indkorsel"
OUTPUT_FILE   = "/config/www/snapshots/indkorsel_gallery.html"
LOADER_FILE   = "/config/www/snapshots/indkorsel_loader.html"
MAX_SNAPSHOTS = 500


def parse_timestamp(filename):
    base = os.path.basename(filename).replace(".jpg", "")
    try:
        dt = datetime.strptime(base, "%Y-%m-%d_%H-%M-%S")
        return dt.strftime("%-d. %b %Y  %H:%M:%S")
    except Exception:
        return base


os.makedirs(SNAPSHOT_DIR, exist_ok=True)

files = sorted(
    [f for f in glob.glob(os.path.join(SNAPSHOT_DIR, "*.jpg"))
     if os.path.basename(f) != "latest.jpg"],
    reverse=True
)[:MAX_SNAPSHOTS]

items_html = ""
images_js  = []   # [{src, ts}, ...] for JS navigation
for f in files:
    rel = "/local/snapshots/indkorsel/" + os.path.basename(f)
    ts  = parse_timestamp(f)
    idx = len(images_js)
    items_html += f"""
    <div class="thumb" onclick="openModal({idx})">
      <img src="{rel}" loading="lazy" alt="{ts}"/>
      <div class="ts">{ts}</div>
    </div>"""
    images_js.append({"src": rel, "ts": ts})

import json as _json
images_js_str = _json.dumps(images_js)
version = datetime.now().strftime("%Y%m%d%H%M%S")

html = f"""<!DOCTYPE html>
<html lang="da"><head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Indkorsel snapshots</title>
  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
  <meta http-equiv="Pragma" content="no-cache">
  <meta http-equiv="Expires" content="0">
  <style>
    .prune-btn{{display:inline-block;margin-left:12px;padding:3px 10px;font-size:11px;border:1px solid #c44;background:transparent;color:#c88;border-radius:12px;cursor:pointer;vertical-align:middle;transition:background .15s,color .15s}}
    .prune-btn:hover{{background:#c44;color:#fff}}
    .prune-btn:disabled{{opacity:.4;cursor:default}}
    *{{box-sizing:border-box;margin:0;padding:0}}
    body{{background:#111;color:#ddd;font-family:sans-serif;padding:10px}}
    h2{{padding:8px 0 14px;font-size:13px;opacity:.5;font-weight:normal}}
    .grid{{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:6px}}
    .thumb{{cursor:pointer;border-radius:7px;overflow:hidden;background:#222;transition:transform .12s,opacity .12s}}
    .thumb:hover{{transform:scale(1.02);opacity:.9}}
    .thumb img{{width:100%;aspect-ratio:16/9;object-fit:cover;display:block}}
    .ts{{font-size:10px;padding:4px 6px;opacity:.5;text-align:center}}
    .modal{{display:none;position:fixed;inset:0;background:rgba(0,0,0,.93);z-index:9999;flex-direction:column;justify-content:center;align-items:center}}
    .modal.show{{display:flex}}
    .modal img{{max-width:96vw;max-height:82vh;border-radius:8px;object-fit:contain;box-shadow:0 4px 40px rgba(0,0,0,.6)}}
    .modal-ts{{margin-top:12px;font-size:14px;opacity:.6;letter-spacing:.3px}}
    .modal-counter{{margin-top:4px;font-size:11px;opacity:.35;letter-spacing:.3px}}
    .close{{position:absolute;top:14px;right:18px;font-size:32px;cursor:pointer;opacity:.5;line-height:1;user-select:none}}
    .close:hover{{opacity:1}}
    .nav{{position:absolute;top:50%;transform:translateY(-50%);font-size:44px;cursor:pointer;opacity:.35;user-select:none;padding:0 18px;line-height:1}}
    .nav:hover{{opacity:.9}}
    .nav.prev{{left:0}} .nav.next{{right:0}}
    .nav.disabled{{opacity:.08;cursor:default;pointer-events:none}}
    .empty{{padding:40px;text-align:center;opacity:.4;font-size:14px}}
    .reload-badge{{position:fixed;bottom:14px;right:14px;background:#1a73e8;color:#fff;padding:6px 14px;border-radius:20px;font-size:12px;cursor:pointer;display:none;z-index:9998}}
  </style>
</head><body>
  <h2>Viser {len(files)} person-snapshots &ndash; Indkorsel
    <button class="prune-btn" id="pruneBtn" onclick="pruneSnapshots()" title="Slet alle undtagen de 100 nyeste">Behold sidste 100</button>
  </h2>
  {"<div class='grid'>" + items_html + "</div>" if files else "<div class='empty'>Ingen snapshots endnu.</div>"}
  <div id="reload-badge" class="reload-badge" onclick="window.location.reload(true)">Nye billeder &#8211; tryk for at opdatere</div>
  <div class="modal" id="modal">
    <span class="close" onclick="closeModal()">&#x2715;</span>
    <span class="nav prev" id="navPrev" onclick="navigate(-1)">&#x2039;</span>
    <img id="mimg" src="" alt=""/>
    <span class="nav next" id="navNext" onclick="navigate(1)">&#x203a;</span>
    <div class="modal-ts" id="mts"></div>
    <div class="modal-counter" id="mcounter"></div>
  </div>
  <script>
    const IMGS = {images_js_str};
    const VERSION = '{version}';
    let cur = 0;
    function openModal(idx){{
      cur = idx;
      render();
      document.getElementById('modal').classList.add('show');
    }}
    function render(){{
      const item = IMGS[cur];
      document.getElementById('mimg').src  = item.src;
      document.getElementById('mts').textContent     = item.ts;
      document.getElementById('mcounter').textContent = (cur+1) + ' / ' + IMGS.length;
      document.getElementById('navPrev').classList.toggle('disabled', cur === 0);
      document.getElementById('navNext').classList.toggle('disabled', cur === IMGS.length - 1);
    }}
    function navigate(dir){{
      const next = cur + dir;
      if(next >= 0 && next < IMGS.length){{ cur = next; render(); }}
    }}
    function closeModal(){{
      document.getElementById('modal').classList.remove('show');
      document.getElementById('mimg').src = '';
    }}
    document.addEventListener('keydown', e => {{
      if(!document.getElementById('modal').classList.contains('show')) return;
      if(e.key === 'ArrowLeft')  navigate(-1);
      if(e.key === 'ArrowRight') navigate(1);
      if(e.key === 'Escape')     closeModal();
    }});
    document.getElementById('modal').addEventListener('click', function(e){{
      if(e.target === this) closeModal();
    }});
    // Touch swipe support (iPhone/iPad)
    let _tx = null;
    document.getElementById('modal').addEventListener('touchstart', e => {{
      _tx = e.changedTouches[0].clientX;
    }}, {{passive: true}});
    document.getElementById('modal').addEventListener('touchend', e => {{
      if(_tx === null) return;
      const dx = e.changedTouches[0].clientX - _tx;
      _tx = null;
      if(Math.abs(dx) < 40) return;   // ignore taps
      navigate(dx < 0 ? 1 : -1);      // swipe left = næste, swipe right = forrige
    }}, {{passive: true}});
    function pruneSnapshots(){{
      if(!confirm('Slet alle undtagen de 100 nyeste billeder?')) return;
      const btn = document.getElementById('pruneBtn');
      btn.disabled = true;
      btn.textContent = 'Sletter...';
      fetch('/api/webhook/indkorsel_prune_100', {{method:'POST'}})
        .then(() => {{
          btn.textContent = 'Færdig – genindlæser...';
          setTimeout(() => window.location.reload(true), 3500);
        }})
        .catch(() => {{
          btn.disabled = false;
          btn.textContent = 'Fejl – prøv igen';
        }});
    }}
    // Tjek hvert 60 sek om der er en nyere version af galleriet
    setInterval(() => {{
      fetch('/local/snapshots/indkorsel_loader.html?_=' + Date.now())
        .then(r => r.text())
        .then(html => {{
          const m = html.match(/[?]v=(\\d+)/);
          if(m && m[1] !== VERSION) document.getElementById('reload-badge').style.display = 'block';
        }}).catch(() => {{}});
    }}, 60000);
  </script>
</body></html>"""

with open(OUTPUT_FILE, "w", encoding="utf-8") as fh:
    fh.write(html)

# Write a tiny loader page that always redirects to gallery with current timestamp
# so the iframe in HA never serves a cached version
cache_bust = version
loader = f"""<!DOCTYPE html>
<html><head>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<meta http-equiv="refresh" content="0; url=/local/snapshots/indkorsel_gallery.html?v={cache_bust}">
</head><body></body></html>"""
with open(LOADER_FILE, "w", encoding="utf-8") as fh:
    fh.write(loader)

print(f"Gallery updated: {len(files)} snapshots -> {OUTPUT_FILE}")

# Update dashboard YAML iframe URL version so browser always fetches fresh loader
DASHBOARD_VIEW = "/config/dashboards/views/06c_indkorsel_snapshots.yaml"
try:
    import re as _re
    with open(DASHBOARD_VIEW, "r", encoding="utf-8") as fh:
        dash = fh.read()
    updated = _re.sub(
        r'(url: /local/snapshots/indkorsel_loader\.html)(\?v=\d+)?',
        rf'\1?v={version}',
        dash
    )
    if updated != dash:
        with open(DASHBOARD_VIEW, "w", encoding="utf-8") as fh:
            fh.write(updated)
except Exception as _e:
    print(f"Warning: could not update dashboard YAML: {_e}")
