<!DOCTYPE html>
<?php
/* Owner-only Community Installer deliverable.
   Vars: $baseUrl, $assetsUrl, $ownerName, $token, $dir, $installerMode, $hasInstaller, $builtAt, $hasCreds */
if (!isset($baseUrl)) $baseUrl = '';
if (!isset($assetsUrl)) $assetsUrl = rtrim($baseUrl, '/') . '/assets';
$rebuildUrl = rtrim($baseUrl, '/') . '/platform/deliverables/community/rebuild';
$dlUrl      = rtrim($baseUrl, '/') . '/platform/deliverables/community/download';
?>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= htmlspecialchars(\PpPhp\Core\Brand::name()) ?> · Community Installer</title>
    <?php include constant('BASE_PATH') . '/core/views/favicon.php'; ?>
    <link href="<?= $assetsUrl ?>/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <link href="<?= $assetsUrl ?>/icons/bootstrap-icons.css" rel="stylesheet">
    <?php include constant('BASE_PATH') . '/core/views/theme-head.php'; ?>
    <link href="<?= $assetsUrl ?>/sweetalert2/sweetalert2.min.css" rel="stylesheet">
    <script src="<?= $assetsUrl ?>/sweetalert2/sweetalert2.min.js"></script>
    <style>
        body { background: var(--pp-app-bg, #f5f6fa); color: var(--pp-text, #172033); }
        .ppb-topbar { background: var(--pp-surface, #fff); border-bottom: 1px solid var(--pp-border, #e6e9f0); }
        .ppb-wrap { max-width: 780px; margin: 2.2rem auto; padding: 0 1rem; }
        .ppb-card { background: var(--pp-surface, #fff); border: 1px solid var(--pp-border, #e6e9f0); border-radius: 16px; box-shadow: 0 8px 30px rgba(15,23,42,.06); overflow: hidden; }
        .ppb-head { padding: 1.4rem 1.6rem; background: linear-gradient(135deg, #4f46e5, #6366f1); color: #fff; }
        .ppb-owner { display: inline-flex; align-items: center; gap: .35rem; font-size: .72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; background: rgba(255,255,255,.18); padding: .2rem .6rem; border-radius: 999px; }
        .ppb-body { padding: 1.6rem; }
        .ppb-col h6 { font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; color: var(--pp-muted, #64748b); margin-bottom: .5rem; }
        .ppb-col ul { list-style: none; padding: 0; margin: 0; font-size: .9rem; }
        .ppb-col li { display: flex; align-items: baseline; gap: .5rem; padding: .18rem 0; }
        .ppb-col li i { color: #16a34a; }
        .ppb-status { display: flex; gap: .7rem; align-items: center; border: 1px solid var(--pp-border, #e6e9f0); border-radius: 12px; padding: .85rem 1rem; margin: 0 0 1.1rem; }
        .ppb-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
        .ppb-note { display: flex; gap: .6rem; align-items: flex-start; background: var(--pp-surface-soft, #f1f5f9); border: 1px solid var(--pp-border, #e2e8f0); border-radius: 12px; padding: .8rem 1rem; font-size: .86rem; color: var(--pp-muted, #475569); }
        .ppb-actions { display: flex; gap: .7rem; align-items: center; flex-wrap: wrap; margin-top: 1.3rem; }
    </style>
</head>
<body>
    <div class="ppb-topbar py-2">
        <div class="d-flex align-items-center px-3" style="max-width:1100px;margin:0 auto;">
            <a href="<?= $baseUrl ?>/projects" class="text-decoration-none d-flex align-items-center" style="color:inherit;">
                <?= \PpPhp\Core\Brand::lockup(32) ?>
            </a>
            <div class="ms-auto d-flex align-items-center gap-2"><?php include constant('BASE_PATH') . '/core/views/theme-toggle.php'; ?><a href="<?= $baseUrl ?>/projects" class="btn btn-sm btn-outline-secondary"><i class="bi bi-arrow-left me-1"></i>Back to Projects</a></div>
        </div>
    </div>

    <div class="ppb-wrap">
        <div class="ppb-card">
            <div class="ppb-head">
                <div class="ppb-owner"><i class="bi bi-shield-lock-fill"></i> Owner only</div>
                <h3 class="mt-2 mb-1"><i class="bi bi-box-seam me-2"></i>Community Installer</h3>
                <p class="mb-0" style="opacity:.92;">The community forum, packaged as a <strong>standalone installer</strong>. Unzip on any server and open <code>install.php</code> — it sets up the database and admin at runtime.</p>
            </div>
            <div class="ppb-body">

                <!-- Build status -->
                <div class="ppb-status">
                    <?php if ($hasInstaller && !$stale): ?>
                        <span class="ppb-dot" style="background:#16a34a"></span>
                        <div>
                            <div class="fw-semibold">Installer ready &amp; up to date</div>
                            <div class="text-muted" style="font-size:.84rem">Last built <?= htmlspecialchars((string) $builtAt) ?> · <code><?= htmlspecialchars($dir) ?></code></div>
                        </div>
                    <?php elseif ($hasInstaller && $stale): ?>
                        <span class="ppb-dot" style="background:#f59e0b"></span>
                        <div>
                            <div class="fw-semibold text-warning-emphasis">Changes since last build — Rebuild recommended</div>
                            <div class="text-muted" style="font-size:.84rem">Last built <?= htmlspecialchars((string) $builtAt) ?><?php if ($sourceChanged): ?> · source edited <?= htmlspecialchars((string) $sourceChanged) ?><?php endif; ?></div>
                        </div>
                    <?php else: ?>
                        <span class="ppb-dot" style="background:#f59e0b"></span>
                        <div>
                            <div class="fw-semibold">Not built yet</div>
                            <div class="text-muted" style="font-size:.84rem">Click <strong>Rebuild</strong> to generate the installer bundle.</div>
                        </div>
                    <?php endif; ?>
                </div>

                <?php if ($hasInstaller && $stale): ?>
                <div class="ppb-note mb-3" style="border-color:#fcd34d;background:color-mix(in srgb,#f59e0b 8%,transparent);color:#92400e">
                    <i class="bi bi-exclamation-triangle mt-1"></i>
                    <div>You've edited the community project since the last build. <strong>Rebuild</strong> to refresh the installer — or just hit <strong>Download</strong>, which rebuilds automatically when there are unbuilt changes.</div>
                </div>
                <?php endif; ?>

                <?php if (!$installerMode): ?>
                <div class="alert alert-warning py-2 px-3" style="font-size:.86rem">
                    <i class="bi bi-exclamation-triangle me-1"></i>
                    Standalone-installer mode is <strong>off</strong> for the community project. Turn on
                    <em>“Include standalone install.php”</em> in its <a href="<?= $baseUrl ?>/output/community">Output → Advanced</a> settings, then Rebuild — otherwise the download won't carry <code>install.php</code>.
                </div>
                <?php endif; ?>

                <?php if ($hasCreds): ?>
                <div class="alert alert-danger py-2 px-3" style="font-size:.86rem">
                    <i class="bi bi-shield-exclamation me-1"></i>
                    The current build still contains a <code>config/database.php</code> with live credentials. A Rebuild in installer mode removes it; the download excludes it regardless.
                </div>
                <?php endif; ?>

                <div class="ppb-col mb-3">
                    <h6>What's inside</h6>
                    <ul>
                        <li><i class="bi bi-check-lg"></i> The complete community forum app (no external dependencies)</li>
                        <li><i class="bi bi-check-lg"></i> <code>install.php</code> — guided DB setup, table creation, first admin</li>
                        <li><i class="bi bi-check-lg"></i> <code>database.sql</code> — schema + starter Q&amp;A content</li>
                        <li><i class="bi bi-check-lg"></i> <code>config/database.sample.php</code> — <strong>no baked credentials</strong></li>
                    </ul>
                </div>

                <div class="ppb-actions">
                    <button id="btnRebuild" class="btn btn-outline-primary"><i class="bi bi-arrow-repeat me-1"></i>Rebuild</button>
                    <a id="btnDownload" href="<?= $dlUrl ?>" class="btn btn-primary"><i class="bi bi-download me-1"></i>Download ZIP</a>
                    <a href="<?= $baseUrl ?>/platform/deliverables/marketing" class="btn btn-outline-secondary"><i class="bi bi-globe2 me-1"></i>Marketing Website</a>
                    <a href="<?= $baseUrl ?>/help/owner_deliverables" class="btn btn-link btn-sm text-decoration-none ms-auto"><i class="bi bi-question-circle me-1"></i>Help</a>
                </div>
                <p class="text-muted mt-3 mb-0" style="font-size:.82rem;"><i class="bi bi-shield-check me-1"></i><strong>Download always ships a fresh build</strong> — if the output was cleaned or you have unbuilt changes, it rebuilds first. The ZIP is streamed, then deleted from this server; no credentials are ever included.</p>
            </div>
        </div>
        <?php $which = 'community'; include __DIR__ . '/partials/deliverables_analytics.php'; ?>

        <?php
          $fmtBytes = static function (int $n): string {
              if ($n <= 0) return '';
              $u = ['B','KB','MB','GB']; $i = (int) floor(log(max(1, $n), 1024));
              return round($n / (1024 ** $i), $i ? 1 : 0) . ' ' . $u[$i];
          };
          $updatePackages = $updatePackages ?? [];
          $genUrl = rtrim($baseUrl, '/') . '/platform/deliverables/community/update/generate';
          $delUrl = rtrim($baseUrl, '/') . '/platform/deliverables/community/update/delete';
          $dlBase = rtrim($baseUrl, '/') . '/platform/deliverables/community/update/download?file=';
        ?>
        <div class="ppb-card mt-3">
          <div class="p-3 p-md-4">
            <h6 class="fw-bold mb-1"><i class="bi bi-file-earmark-zip me-1"></i> Signed update package (download &amp; hand off)</h6>
            <p class="text-muted small mb-3">The community portal is hosted separately, so an update is a
              <strong>signed ZIP you download here</strong> and upload into the forum's
              <strong>Admin → Software updates</strong>. Nothing is served from this app. The version comes from
              <code>forum/version.php</code> in the community source: bump it, then Generate.</p>
            <?php if (empty($hasSigningKey)): ?>
              <div class="alert alert-warning py-2 small mb-3"><i class="bi bi-exclamation-triangle me-1"></i>
                No signing key yet — create one in <a href="<?= $baseUrl ?>/licensing">Licensing → Signing key</a> before generating a package.</div>
            <?php endif; ?>
            <div class="mb-2">
              <label class="form-label small mb-1">Release notes <span class="text-muted">(shown to forum admins)</span></label>
              <textarea id="pubNotes" class="form-control form-control-sm" rows="2" placeholder="What changed in this version…"></textarea>
            </div>
            <button id="btnGenerate" class="btn btn-sm btn-outline-primary"<?= empty($hasSigningKey) ? ' disabled' : '' ?>><i class="bi bi-file-earmark-zip me-1"></i>Generate update package</button>
            <a href="<?= $baseUrl ?>/help/community_updates" class="btn btn-sm btn-link text-decoration-none"><i class="bi bi-question-circle me-1"></i>How this works</a>

            <div id="pkgList" class="mt-3">
              <?php if ($updatePackages): ?>
                <div class="table-responsive">
                  <table class="table table-sm align-middle mb-0">
                    <thead><tr><th>Package</th><th>Version</th><th>Size</th><th>Generated</th><th class="text-end">Actions</th></tr></thead>
                    <tbody>
                    <?php foreach ($updatePackages as $p): ?>
                      <tr data-file="<?= htmlspecialchars($p['file'], ENT_QUOTES) ?>">
                        <td><code><?= htmlspecialchars($p['file'], ENT_QUOTES) ?></code></td>
                        <td><span class="badge bg-secondary-subtle text-secondary-emphasis"><?= htmlspecialchars($p['version'], ENT_QUOTES) ?></span></td>
                        <td><?= htmlspecialchars($fmtBytes((int) $p['size']), ENT_QUOTES) ?></td>
                        <td class="text-muted small"><?= $p['mtime'] ? date('Y-m-d H:i', (int) $p['mtime']) : '' ?></td>
                        <td class="text-end" style="white-space:nowrap">
                          <a class="btn btn-sm btn-primary" href="<?= htmlspecialchars($dlBase . rawurlencode($p['file']), ENT_QUOTES) ?>"><i class="bi bi-download me-1"></i>Download</a>
                          <button class="btn btn-sm btn-outline-danger btn-del-pkg"><i class="bi bi-trash"></i></button>
                        </td>
                      </tr>
                    <?php endforeach; ?>
                    </tbody>
                  </table>
                </div>
              <?php else: ?>
                <p class="text-muted small mb-0" id="pkgEmpty"><i class="bi bi-inbox me-1"></i>No packages generated yet.</p>
              <?php endif; ?>
            </div>
            <p class="text-muted mt-2 mb-0" style="font-size:.8rem"><i class="bi bi-shield-check me-1"></i>Packages are held in <code>storage/community-updates/</code> (never web-served). Download the one you need, upload it to the forum, then Delete it here.</p>
          </div>
        </div>
    </div>

    <script>
    (function () {
        const gen = document.getElementById('btnGenerate');
        const token = <?= json_encode($token) ?>;
        const genUrl = <?= json_encode($genUrl) ?>;
        const delUrl = <?= json_encode($delUrl) ?>;
        if (gen) gen.addEventListener('click', async function () {
            gen.disabled = true;
            const old = gen.innerHTML;
            gen.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Building &amp; signing…';
            try {
                const r = await fetch(genUrl, {
                    method: 'POST', credentials: 'same-origin',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ _token: token, notes: document.getElementById('pubNotes').value })
                });
                if (!r.ok) {
                    const msg = await r.text();
                    Swal.fire({ icon: 'error', title: 'Could not generate', text: msg || ('HTTP ' + r.status) });
                    gen.disabled = false; gen.innerHTML = old;
                } else {
                    const j = await r.json();
                    await Swal.fire({ icon: 'success', title: 'Package ready — v' + j.version,
                        html: 'Signed with key <code>' + (j.keyId || '') + '</code>.<br>Download it below and upload it into the forum’s Admin → Software updates.' });
                    location.reload();
                }
            } catch (e) {
                Swal.fire({ icon: 'error', title: 'Could not generate', text: String(e) });
                gen.disabled = false; gen.innerHTML = old;
            }
        });
        // Delete a generated package (event-delegated).
        document.getElementById('pkgList').addEventListener('click', async function (e) {
            const btn = e.target.closest('.btn-del-pkg');
            if (!btn) return;
            const row = btn.closest('tr');
            const file = row.getAttribute('data-file');
            const ok = await Swal.fire({ icon: 'warning', title: 'Delete this package?', text: file,
                showCancelButton: true, confirmButtonText: 'Delete', confirmButtonColor: '#dc2626' });
            if (!ok.isConfirmed) return;
            try {
                const r = await fetch(delUrl, {
                    method: 'POST', credentials: 'same-origin',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ _token: token, file: file })
                });
                const j = await r.json();
                if (j.success) { row.remove(); Swal.fire({ icon: 'success', title: 'Deleted', timer: 1000, showConfirmButton: false }); }
                else Swal.fire({ icon: 'error', title: 'Could not delete' });
            } catch (err) { Swal.fire({ icon: 'error', title: 'Could not delete', text: String(err) }); }
        });
    })();
    </script>

    <script>
    (function () {
        const btn = document.getElementById('btnRebuild');
        const dl  = document.getElementById('btnDownload');
        const token = <?= json_encode($token) ?>;
        btn.addEventListener('click', async function () {
            btn.disabled = true;
            const old = btn.innerHTML;
            btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Rebuilding…';
            try {
                const r = await fetch(<?= json_encode($rebuildUrl) ?>, {
                    method: 'POST',
                    credentials: 'same-origin',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ _token: token })
                });
                const j = await r.json();
                if (j.success) {
                    await Swal.fire({ icon: j.hasInstaller ? 'success' : 'warning',
                        title: j.hasInstaller ? 'Installer rebuilt' : 'Built (no installer)',
                        text: j.hasInstaller ? (j.message || 'Done.') : 'Build succeeded but no install.php was produced — enable installer mode in Output, then rebuild.',
                        confirmButtonText: 'OK' });
                    location.reload();
                } else {
                    Swal.fire({ icon: 'error', title: 'Rebuild failed', text: j.message || 'Unknown error.' });
                    btn.disabled = false; btn.innerHTML = old;
                }
            } catch (e) {
                Swal.fire({ icon: 'error', title: 'Rebuild failed', text: String(e) });
                btn.disabled = false; btn.innerHTML = old;
            }
        });
        if (dl.classList.contains('disabled')) {
            dl.addEventListener('click', e => e.preventDefault());
        }
    })();
    </script>
</body>
</html>
