<?php declare(strict_types=1); ?>
<!-- ═══════════════════════════════════════════════════════════════════
     Version History — shared slide-over panel.
     Self-contained (markup + styles + script). Included once by the project
     navbar, so it is available on every in-project page. Opened by any
     element with [data-vh-open]. Reads base URL + slug from #projectNavbar.
     ══════════════════════════════════════════════════════════════════ -->
<style>
    .vh-scrim { position:fixed; inset:0; z-index:12000; background:rgba(15,23,42,.5);
        backdrop-filter:blur(2px); display:flex; justify-content:flex-end; opacity:0;
        transition:opacity .18s; }
    .vh-scrim.vh-open { opacity:1; }
    .vh-scrim[hidden] { display:none; }
    .vh-panel { width:min(430px, 100vw); height:100%; display:flex; flex-direction:column;
        background:var(--pp-surface, #fff); color:var(--pp-text, #0f172a);
        box-shadow:-24px 0 60px rgba(2,6,23,.35); transform:translateX(24px);
        transition:transform .2s ease; }
    .vh-scrim.vh-open .vh-panel { transform:translateX(0); }

    .vh-head { flex:0 0 auto; display:flex; align-items:flex-start; gap:12px; padding:18px 20px;
        border-bottom:1px solid var(--pp-border, #e2e8f0);
        background:linear-gradient(120deg, var(--pp-accent, #4f46e5), color-mix(in srgb, var(--pp-accent, #6366f1) 70%, #7c3aed)); color:#fff; }
    .vh-head-titles h2 { margin:0; font-size:16px; font-weight:800; display:flex; align-items:center; gap:9px; letter-spacing:-.01em; }
    .vh-head-titles p { margin:4px 0 0; font-size:12px; opacity:.9; line-height:1.45; }
    .vh-close { margin-left:auto; flex:0 0 auto; width:32px; height:32px; border:0; border-radius:9px;
        background:rgba(255,255,255,.16); color:#fff; font-size:18px; cursor:pointer; line-height:1;
        display:flex; align-items:center; justify-content:center; transition:.15s; }
    .vh-close:hover { background:rgba(255,255,255,.3); }

    .vh-actions { flex:0 0 auto; padding:12px 20px; border-bottom:1px solid var(--pp-border, #eef1f6); }
    .vh-save-btn { display:inline-flex; align-items:center; gap:7px; width:100%; justify-content:center;
        padding:9px 12px; font-size:13px; font-weight:700; cursor:pointer; border-radius:10px;
        border:1px solid var(--pp-border, #e2e8f0); background:var(--pp-surface-soft, #f8fafc);
        color:var(--pp-text, #0f172a); transition:.15s; }
    .vh-save-btn:hover { border-color:var(--pp-accent, #4f46e5); color:var(--pp-accent, #4f46e5); }

    .vh-body { flex:1; min-height:0; overflow-y:auto; padding:12px 14px; }

    .vh-item { display:flex; gap:12px; padding:12px; border:1px solid var(--pp-border, #eef1f6);
        border-radius:12px; margin-bottom:9px; background:var(--pp-surface, #fff); transition:.15s; }
    .vh-item:hover { border-color:color-mix(in srgb, var(--pp-accent, #4f46e5) 40%, var(--pp-border, #e2e8f0));
        box-shadow:0 6px 18px rgba(2,6,23,.06); }
    .vh-ic { flex:0 0 38px; width:38px; height:38px; border-radius:10px; display:flex; align-items:center;
        justify-content:center; font-size:17px; }
    .vh-ic.t-auto { background:#eef2ff; color:#4f46e5; }
    .vh-ic.t-checkpoint { background:#ecfeff; color:#0e7490; }
    .vh-ic.t-build { background:#ecfdf5; color:#059669; }
    .vh-ic.t-safety { background:#fff7ed; color:#c2410c; }
    .vh-meta { flex:1; min-width:0; }
    .vh-desc { font-size:13.5px; font-weight:700; color:var(--pp-text, #0f172a); line-height:1.3; }
    .vh-time { font-size:11.5px; color:var(--pp-text-muted, #64748b); margin-top:2px; }
    .vh-badge { display:inline-block; font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.04em;
        padding:1px 6px; border-radius:5px; margin-left:6px; vertical-align:middle;
        background:var(--pp-surface-muted, #f1f5f9); color:var(--pp-text-muted, #64748b); }
    .vh-row-actions { display:flex; align-items:center; gap:6px; margin-top:9px; }
    .vh-restore { flex:1; display:inline-flex; align-items:center; justify-content:center; gap:6px;
        padding:7px 10px; font-size:12.5px; font-weight:700; cursor:pointer; border-radius:8px; border:0;
        background:var(--pp-accent, #4f46e5); color:var(--pp-accent-contrast, #fff); transition:.15s; }
    .vh-restore:hover { filter:brightness(1.06); }
    .vh-del { flex:0 0 auto; width:32px; height:32px; border-radius:8px; cursor:pointer;
        border:1px solid var(--pp-border, #e2e8f0); background:transparent; color:var(--pp-text-muted, #94a3b8);
        display:flex; align-items:center; justify-content:center; transition:.15s; }
    .vh-del:hover { border-color:#ef4444; color:#ef4444; }

    .vh-empty { text-align:center; padding:48px 24px; color:var(--pp-text-muted, #64748b); }
    .vh-empty i { font-size:40px; color:color-mix(in srgb, var(--pp-accent, #4f46e5) 55%, var(--pp-text-muted, #94a3b8)); }
    .vh-empty h3 { margin:14px 0 6px; font-size:16px; font-weight:800; color:var(--pp-text, #0f172a); }
    .vh-empty p { margin:0 auto; max-width:280px; font-size:13px; line-height:1.55; }
    .vh-loading { text-align:center; padding:40px; color:var(--pp-text-muted, #64748b); font-size:13px; }

    .vh-foot { flex:0 0 auto; display:flex; align-items:flex-start; gap:9px; padding:14px 20px;
        border-top:1px solid var(--pp-border, #e2e8f0); background:var(--pp-surface-soft, #f8fafc);
        font-size:12px; line-height:1.5; color:var(--pp-text-muted, #475569); }
    .vh-foot i { color:#16a34a; font-size:15px; flex:0 0 auto; margin-top:1px; }
</style>

<div class="vh-scrim" id="vhScrim" hidden aria-hidden="true">
  <aside class="vh-panel" role="dialog" aria-modal="true" aria-label="Version History">
    <header class="vh-head">
      <div class="vh-head-titles">
        <h2><i class="bi bi-clock-history"></i> Your saved versions</h2>
        <p>Every big change is saved automatically, so you can always go back.</p>
      </div>
      <button class="vh-close" id="vhClose" title="Close" aria-label="Close">&times;</button>
    </header>
    <div class="vh-actions">
      <button class="vh-save-btn" id="vhSaveNow"><i class="bi bi-bookmark-plus"></i> Save this version</button>
    </div>
    <div class="vh-body" id="vhBody">
      <div class="vh-loading"><i class="bi bi-arrow-repeat"></i> Loading your versions…</div>
    </div>
    <footer class="vh-foot">
      <i class="bi bi-shield-check"></i>
      <span>Restoring won't delete your current work — you can always come back to it.</span>
    </footer>
  </aside>
</div>

<script>
(function () {
    var scrim = document.getElementById('vhScrim');
    if (!scrim) return;
    var body   = document.getElementById('vhBody');
    var navbar = document.getElementById('projectNavbar');
    var base   = (navbar && navbar.dataset.baseUrl ? navbar.dataset.baseUrl : '').replace(/\/$/, '');
    var slug   = navbar ? navbar.dataset.projectSlug : '';
    var root   = base + '/project/' + encodeURIComponent(slug) + '/versions';

    var TYPES = {
        auto:       { icon: 'bi-clock',          badge: 'Auto-save' },
        checkpoint: { icon: 'bi-bookmark-star',  badge: 'Saved' },
        build:      { icon: 'bi-box-arrow-up-right', badge: 'Build' },
        safety:     { icon: 'bi-shield-check',    badge: 'Safety copy' }
    };

    function esc(s) {
        return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) {
            return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c];
        });
    }

    function timeAgo(ts) {
        var s = Math.floor(Date.now() / 1000) - ts;
        if (s < 45) return 'Just now';
        if (s < 90) return 'A minute ago';
        if (s < 3600) return Math.floor(s / 60) + ' minutes ago';
        if (s < 7200) return 'An hour ago';
        if (s < 86400) return Math.floor(s / 3600) + ' hours ago';
        if (s < 172800) return 'Yesterday';
        if (s < 2592000) return Math.floor(s / 86400) + ' days ago';
        return new Date(ts * 1000).toLocaleDateString();
    }

    function fullDate(ts) {
        return new Date(ts * 1000).toLocaleString([], {
            year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit'
        });
    }

    function open() {
        scrim.hidden = false;
        scrim.setAttribute('aria-hidden', 'false');
        requestAnimationFrame(function () { scrim.classList.add('vh-open'); });
        load();
    }
    function close() {
        scrim.classList.remove('vh-open');
        scrim.setAttribute('aria-hidden', 'true');
        setTimeout(function () { scrim.hidden = true; }, 200);
    }

    function load() {
        body.innerHTML = '<div class="vh-loading"><i class="bi bi-arrow-repeat"></i> Loading your versions…</div>';
        fetch(root, { headers: { 'Accept': 'application/json' }, credentials: 'same-origin' })
            .then(function (r) { return r.json(); })
            .then(function (j) { render((j && j.versions) || []); })
            .catch(function () {
                body.innerHTML = '<div class="vh-empty"><i class="bi bi-wifi-off"></i><h3>Couldn\'t load versions</h3><p>Please check your connection and try again.</p></div>';
            });
    }

    function render(versions) {
        if (!versions.length) {
            body.innerHTML = '<div class="vh-empty">'
                + '<i class="bi bi-clock-history"></i>'
                + '<h3>No saved versions yet</h3>'
                + '<p>Keep building! As you make changes, we\'ll automatically save versions here — so you can always step back if something doesn\'t look right.</p>'
                + '</div>';
            return;
        }
        body.innerHTML = versions.map(function (v) {
            var t = TYPES[v.type] || TYPES.checkpoint;
            var ago = timeAgo(v.ts);
            return '<div class="vh-item">'
                + '<div class="vh-ic t-' + esc(v.type || 'checkpoint') + '"><i class="bi ' + t.icon + '"></i></div>'
                + '<div class="vh-meta">'
                +   '<div class="vh-desc">' + esc(v.description) + '<span class="vh-badge">' + esc(t.badge) + '</span></div>'
                +   '<div class="vh-time">' + esc(ago) + ' · ' + esc(fullDate(v.ts)) + '</div>'
                +   '<div class="vh-row-actions">'
                +     '<button class="vh-restore" data-id="' + esc(v.id) + '" data-ago="' + esc(ago) + '"><i class="bi bi-arrow-counterclockwise"></i> Go back to this version</button>'
                +     '<button class="vh-del" data-id="' + esc(v.id) + '" title="Remove this version"><i class="bi bi-trash3"></i></button>'
                +   '</div>'
                + '</div>'
                + '</div>';
        }).join('');
    }

    function restore(id, ago) {
        Swal.fire({
            title: 'Go back to this version?',
            html: 'We\'ll bring your site back to how it looked <strong>' + esc(ago).toLowerCase() + '</strong>. Your current version stays saved, so nothing is lost.',
            icon: 'question',
            showCancelButton: true,
            confirmButtonText: 'Yes, take me back',
            cancelButtonText: 'Keep what I have now',
            reverseButtons: true
        }).then(function (res) {
            if (!res.isConfirmed) return;
            fetch(root + '/restore', {
                method: 'POST', headers: { 'Content-Type': 'application/json' },
                credentials: 'same-origin', body: JSON.stringify({ id: id })
            }).then(function (r) { return r.json(); }).then(function (j) {
                if (!j || !j.success) { Swal.fire('Hmm', (j && j.message) || 'That version could not be found.', 'error'); return; }
                Swal.fire({
                    title: 'You\'re back to this version',
                    text: 'Your other work is still saved if you need it.',
                    icon: 'success',
                    confirmButtonText: 'Got it'
                }).then(function () { window.location.reload(); });
            }).catch(function () { Swal.fire('Something went wrong', 'Please try again.', 'error'); });
        });
    }

    function saveNow() {
        fetch(root + '/create', {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            credentials: 'same-origin', body: JSON.stringify({})
        }).then(function (r) { return r.json(); }).then(function (j) {
            if (typeof Swal !== 'undefined') {
                Swal.fire({
                    toast: true, position: 'top-end', timer: 2200, showConfirmButton: false,
                    icon: j && j.success ? 'success' : 'info',
                    title: (j && j.message) || 'Saved.'
                });
            }
            load();
        }).catch(function () {});
    }

    function del(id) {
        Swal.fire({
            title: 'Remove this version?', text: 'This just clears it from your history.',
            icon: 'warning', showCancelButton: true, confirmButtonText: 'Remove', cancelButtonText: 'Cancel',
            confirmButtonColor: '#ef4444', reverseButtons: true
        }).then(function (res) {
            if (!res.isConfirmed) return;
            fetch(root + '/delete', {
                method: 'POST', headers: { 'Content-Type': 'application/json' },
                credentials: 'same-origin', body: JSON.stringify({ id: id })
            }).then(function () { load(); }).catch(function () {});
        });
    }

    // Events
    document.addEventListener('click', function (e) {
        if (e.target.closest('[data-vh-open]')) { e.preventDefault(); open(); return; }
        var r = e.target.closest('.vh-restore'); if (r) { restore(r.dataset.id, r.dataset.ago); return; }
        var d = e.target.closest('.vh-del');     if (d) { del(d.dataset.id); return; }
    });
    document.getElementById('vhClose').addEventListener('click', close);
    document.getElementById('vhSaveNow').addEventListener('click', saveNow);
    scrim.addEventListener('click', function (e) { if (e.target === scrim) close(); });
    document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape' && !scrim.hidden) { e.stopPropagation(); close(); }
    });

    window.PpVersionHistory = { open: open, close: close };
})();
</script>
