<!DOCTYPE html>
<?php
/* This installation's licence page.
   Vars: $baseUrl, $assetsUrl, $user, $isOwner, $status, $enforced, $stamped, $locked */
use PpPhp\Core\Licensing\LicenseProtocol as P;

if (!isset($baseUrl)) $baseUrl = '';
if (!isset($assetsUrl)) $assetsUrl = rtrim($baseUrl, '/') . '/assets';
$b = rtrim($baseUrl, '/');
$token = \PpPhp\Core\Security::CSRF()->Token();

$state = (string) ($status['status'] ?? P::NONE);
// When this build is NOT enforced (unstamped — e.g. your own licence server,
// or any dev build), nothing here ever locks, so don't nag to activate. The
// grace clock is meaningless in that case.
if (!empty($isBackup)) {
    // Failover clone of the main — never licensed on its own.
    $tone = ['ok', 'hdd-network', 'Backup server'];
} elseif (!empty($isAuthority)) {
    // This install holds the signing key — it IS the licence server.
    $tone = ['ok', 'shield-lock', 'Licence server'];
} elseif (empty($enforced)) {
    $tone = ['idle', 'shield', 'Licensing not enforced'];
} else {
    $tone = match ($state) {
        P::OK      => ['ok',   'shield-check',            'Licensed'],
        P::GRACE   => ['warn', 'shield-exclamation',      'Attention needed'],
        P::REVOKED => ['bad',  'shield-slash',            'Deactivated'],
        P::EXPIRED => ['bad',  'shield-x',                'Expired'],
        P::INVALID => ['bad',  'shield-x',                'Unreadable'],
        default    => ['idle', 'shield',                  'Not activated'],
    };
}
$seats = $status['seats'] ?? null;
$support = trim((string) ($status['support'] ?? '')) ?: \PpPhp\Core\Licensing\LicenseProtocol::SUPPORT_CONTACT;
?>
<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()) ?> · Licence</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">
    <script src="<?= $assetsUrl ?>/bootstrap/js/bootstrap.bundle.min.js" defer></script>
    <?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); padding-top: 56px; }
        .ppl-topbar { background: var(--pp-surface, #fff); border-bottom: 1px solid var(--pp-border, #e6e9f0); }
        .ppl-wrap { max-width: 880px; margin: 2rem auto; padding: 0 1rem; }
        .ppl-card { background: var(--pp-surface, #fff); border: 1px solid var(--pp-border, #e6e9f0);
                    border-radius: 14px; padding: 1.25rem 1.35rem; margin-bottom: 1.1rem; }
        .ppl-card h2 { font-size: 1.02rem; font-weight: 800; margin: 0 0 .2rem; }
        .ppl-sub { color: var(--pp-text-muted, #64748b); font-size: .88rem; margin: 0 0 1rem; }
        /* At-a-glance system health strip (licence · updates · build · plan/trial) */
        .ppl-health { display: flex; gap: .6rem; flex-wrap: wrap; margin-bottom: 1.1rem; }
        .ppl-hchip { flex: 1 1 190px; min-width: 175px; display: flex; align-items: center; gap: .7rem;
            background: var(--pp-surface, #fff); border: 1px solid var(--pp-border, #e6e9f0); border-radius: 12px; padding: .7rem .85rem; }
        .ppl-hicon { width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center; font-size: 1.05rem; flex: none; }
        .ppl-hchip .t { font-size: .64rem; text-transform: uppercase; letter-spacing: .05em; color: var(--pp-text-muted, #64748b); font-weight: 700; }
        .ppl-hchip .v { font-size: .9rem; font-weight: 700; line-height: 1.15; }
        .ppl-hchip .s { font-size: .72rem; color: var(--pp-text-muted, #64748b); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 15rem; }
        .ppl-hchip .s a { color: var(--pp-accent, #4f46e5); text-decoration: none; }
        .ppl-hicon.ok   { color: #16a34a; background: color-mix(in srgb, #16a34a 14%, transparent); }
        .ppl-hicon.warn { color: #d97706; background: color-mix(in srgb, #f59e0b 16%, transparent); }
        .ppl-hicon.bad  { color: #dc2626; background: color-mix(in srgb, #ef4444 14%, transparent); }
        .ppl-hicon.idle { color: var(--pp-text-muted, #64748b); background: var(--pp-surface-muted, #f1f5f9); }
        .ppl-hicon.info { color: var(--pp-accent, #4f46e5); background: color-mix(in srgb, var(--pp-accent, #4f46e5) 12%, transparent); }
        /* Collapsed "Re-activate with a different key" (shown only when licensed) */
        details.ppl-reactivate { padding: 0; }
        details.ppl-reactivate > summary { list-style: none; cursor: pointer; display: flex; align-items: center;
            gap: .6rem; padding: 1rem 1.35rem; user-select: none; }
        details.ppl-reactivate > summary::-webkit-details-marker { display: none; }
        details.ppl-reactivate > summary:hover { background: color-mix(in srgb, var(--pp-accent,#4f46e5) 5%, transparent); border-radius: 14px; }
        .ppl-reactivate-title { font-weight: 700; font-size: .96rem; display: inline-flex; align-items: center; gap: .45rem; }
        .ppl-reactivate-title i { color: var(--pp-accent, #6366f1); }
        .ppl-reactivate-hint { color: var(--pp-text-muted, #64748b); font-size: .82rem; }
        .ppl-reactivate-chev { margin-left: auto; color: var(--pp-text-muted, #64748b); transition: transform .2s; }
        details.ppl-reactivate[open] > summary > .ppl-reactivate-chev { transform: rotate(180deg); }
        .ppl-reactivate-body { padding: 0 1.35rem 1.25rem; border-top: 1px solid var(--pp-border, #e6e9f0); padding-top: 1rem; }
        @media (prefers-reduced-motion: reduce) { .ppl-reactivate-chev { transition: none; } }
        /* Small "?" hint marker + native tooltip so the admin knows what a field is. */
        .ppl-hint { display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px;
            margin-left: .2rem; border-radius: 50%; background: var(--pp-surface-soft, #eef1f6);
            color: var(--pp-text-muted, #94a3b8); font-size: .62rem; font-weight: 800; cursor: help; vertical-align: middle; }
        .ppl-hint:hover, .ppl-hint:focus-visible { background: color-mix(in srgb, var(--pp-accent, #6366f1) 16%, transparent);
            color: var(--pp-accent, #6366f1); outline: none; }
        .ppl-bk { font-size: .72rem; font-weight: 700; color: var(--pp-text-muted, #64748b);
            background: var(--pp-surface-soft, #f1f5f9); border: 1px solid var(--pp-border, #e2e8f0);
            border-radius: 999px; padding: .05rem .5rem; cursor: help; }

        .ppl-hero { display: flex; gap: 1.1rem; align-items: flex-start; }
        .ppl-badge { width: 58px; height: 58px; border-radius: 16px; display: grid; place-items: center;
                     font-size: 1.7rem; flex: none; }
        .ppl-badge.ok   { background: color-mix(in srgb, #16a34a 14%, transparent); color: #16a34a; }
        .ppl-badge.warn { background: color-mix(in srgb, #f59e0b 16%, transparent); color: #b45309; }
        .ppl-badge.bad  { background: color-mix(in srgb, #dc2626 13%, transparent); color: #dc2626; }
        .ppl-badge.idle { background: color-mix(in srgb, #64748b 13%, transparent); color: #64748b; }
        .ppl-state { font-size: 1.25rem; font-weight: 800; line-height: 1.2; }
        .ppl-reason { color: var(--pp-text-muted, #64748b); font-size: .9rem; margin-top: .15rem; }

        .ppl-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
                     gap: .9rem 1.4rem; margin-top: 1.15rem; padding-top: 1.05rem;
                     border-top: 1px solid var(--pp-border, #eef1f6); }
        .ppl-fact dt { font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
                       color: var(--pp-text-muted, #94a3b8); font-weight: 700; margin: 0 0 .12rem; }
        .ppl-fact dd { margin: 0; font-size: .92rem; font-weight: 600; word-break: break-word; }
        .ppl-fact dd code { font-size: .8rem; }
        /* Plan badge + capabilities */
        .ppl-plan-badge { flex: 0 0 auto; width: 34px; height: 34px; border-radius: 10px; display: inline-flex; align-items: center;
            justify-content: center; color: #fff; font-size: 16px;
            background: linear-gradient(140deg, var(--c, #64748b), color-mix(in srgb, var(--c, #64748b) 55%, #000));
            box-shadow: 0 3px 10px color-mix(in srgb, var(--c, #64748b) 40%, transparent); }
        .ppl-caps { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: .6rem; margin-top: .3rem; }
        .ppl-cap { display: flex; align-items: center; gap: .6rem; padding: .6rem .75rem; border-radius: 11px;
                   border: 1px solid var(--pp-border, #e6e9f0); }
        .ppl-cap .ic { flex: 0 0 32px; width: 32px; height: 32px; border-radius: 9px; display: flex; align-items: center; justify-content: center; font-size: 15px; }
        .ppl-cap .lb { flex: 1; min-width: 0; font-size: .86rem; font-weight: 700; }
        .ppl-cap .st { font-size: 1rem; }
        .ppl-cap.on { border-color: color-mix(in srgb, #10b981 40%, transparent); background: color-mix(in srgb, #10b981 7%, var(--pp-surface, #fff)); }
        .ppl-cap.on .ic { background: color-mix(in srgb, #10b981 15%, var(--pp-surface, #fff)); color: #059669; }
        .ppl-cap.on .st { color: #10b981; }
        .ppl-cap.off { opacity: .72; }
        .ppl-cap.off .ic { background: var(--pp-surface-soft, #f1f5f9); color: var(--pp-text-muted, #94a3b8); }
        .ppl-cap.off .lb { color: var(--pp-text-muted, #64748b); }
        .ppl-cap.off .st { color: var(--pp-border-strong, #cbd5e1); }

        .ppl-note { background: color-mix(in srgb, var(--pp-accent, #4f46e5) 6%, transparent);
                    border-radius: 10px; padding: .85rem 1rem; font-size: .87rem; }
        .ppl-note.warn { background: color-mix(in srgb, #f59e0b 12%, transparent); }
        .ppl-note ul { margin: .4rem 0 0; padding-left: 1.1rem; }
        .ppl-note li { margin: .1rem 0; }
        textarea.ppl-code { font: 500 .82rem/1.45 ui-monospace, Menlo, monospace; resize: vertical; }
        .ppl-danger { color: #dc2626; }
    </style>
</head>
<body>
<?php
    $navBrandLabel = "This install's licence";
    $navBrandIcon  = 'shield-check';
    $navBack = ['url' => $b . '/projects', 'label' => 'Projects', 'icon' => 'arrow-left'];
    $navExtra = !empty($isOwner)
        ? '<a href="' . htmlspecialchars($b) . '/licensing/server" class="btn btn-sm btn-outline-light" data-tip="Open the licence server"><i class="bi bi-key"></i><span class="d-none d-lg-inline ms-1">Licence server</span></a>'
        : '';
    include constant('BASE_PATH') . '/core/views/console-navbar.php';
?>

<div class="ppl-wrap">

    <?php if ($locked): ?>
        <div class="alert alert-danger d-flex align-items-start gap-2">
            <i class="bi bi-lock-fill mt-1"></i>
            <div>
                <strong>The design console is locked.</strong>
                <div class="small mt-1">
                    This copy could not verify its licence. Please contact your administrator at
                    <a href="mailto:<?= htmlspecialchars($support) ?>"><strong><?= htmlspecialchars($support) ?></strong></a>
                    to restore access.
                </div>
                <div class="small mt-1">
                    Apps you have already built keep running normally — their visitors are unaffected, and
                    nothing has been deleted. Designing, building and deploying resume the moment a valid
                    licence is in place.
                </div>
            </div>
        </div>
    <?php elseif ($enforced && ($state === P::GRACE) && !empty($status['activated'])): ?>
        <div class="alert alert-warning d-flex align-items-start gap-2">
            <i class="bi bi-wifi-off mt-1"></i>
            <div>
                <strong>Can't reach the licence server.</strong>
                <div class="small mt-1">
                    Still running on grace — about <strong><?= htmlspecialchars(P::human((int) ($status['graceLeft'] ?? 0))) ?></strong>
                    left before the console locks. It clears automatically as soon as a check succeeds. If it
                    persists, contact <a href="mailto:<?= htmlspecialchars($support) ?>"><strong><?= htmlspecialchars($support) ?></strong></a>.
                </div>
            </div>
        </div>
    <?php endif; ?>

    <?php if ($enforced && !$locked && empty($isBackup) && empty($isAuthority)):
        // A consolidated at-a-glance strip pulling the four signals a customer
        // cares about into one row — all from LOCAL/cached readers (no network on
        // page load): licence state, the cached update flag, the server-build
        // reachability, and the plan (or the trial countdown).
        $he        = static fn ($s): string => htmlspecialchars((string) $s, ENT_QUOTES);
        $hActivated = !empty($status['activated']);
        $hInTrial   = ($state === P::GRACE) && !$hActivated;
        $hUpAvail   = class_exists(\PpPhp\Core\Update\UpdateNotifier::class)
            ? \PpPhp\Core\Update\UpdateNotifier::available() : '';
        $hBuildUrls = is_array($status['buildUrl'] ?? null) ? $status['buildUrl'] : [];
        $hEndpoints = is_array($status['endpoints'] ?? null) ? $status['endpoints'] : [];
        $hCanBuild  = $hActivated && ($hBuildUrls !== [] || $hEndpoints !== []);
        $hBuildHost = $hBuildUrls !== [] ? (string) (parse_url((string) $hBuildUrls[0], PHP_URL_HOST) ?: $hBuildUrls[0])
            : trim((string) ($status['serverLabel'] ?? ''));
        if ($state === P::OK) {
            $hExp = (int) ($status['expiresIn'] ?? 0);
            $hLicSub = $hExp > 0 ? 'renews in ' . P::human($hExp) : 'active';
        } elseif ($hInTrial) {
            $hLicSub = P::human((int) ($status['graceLeft'] ?? 0)) . ' left';
        } else {
            $hLicSub = (string) $tone[2];
        }
        $hPlan = trim((string) ($status['planName'] ?? '')) ?: (trim((string) ($status['plan'] ?? '')) ?: 'Standard');
        $hPlanIcon = trim((string) ($status['planIcon'] ?? '')) ?: 'box-seam';
    ?>
    <div class="ppl-health">
        <div class="ppl-hchip">
            <span class="ppl-hicon <?= $he($tone[0]) ?>"><i class="bi bi-<?= $he($tone[1]) ?>"></i></span>
            <div><div class="t">Licence</div><div class="v"><?= $he($tone[2]) ?></div><div class="s"><?= $he($hLicSub) ?></div></div>
        </div>
        <div class="ppl-hchip">
            <span class="ppl-hicon <?= $hUpAvail !== '' ? 'warn' : 'ok' ?>"><i class="bi bi-<?= $hUpAvail !== '' ? 'cloud-arrow-down-fill' : 'check-circle-fill' ?>"></i></span>
            <div><div class="t">Updates</div>
                <div class="v"><?= $hUpAvail !== '' ? 'v' . $he($hUpAvail) . ' ready' : 'Up to date' ?></div>
                <div class="s"><a href="<?= $he($b . '/platform/updates') ?>"><?= $hUpAvail !== '' ? 'Install now →' : 'Check for updates →' ?></a></div></div>
        </div>
        <div class="ppl-hchip">
            <span class="ppl-hicon <?= $hCanBuild ? 'ok' : 'idle' ?>"><i class="bi bi-hdd-network-fill"></i></span>
            <div><div class="t">Build server</div>
                <div class="v"><?= $hCanBuild ? 'Server build ready' : 'Not available' ?></div>
                <div class="s"><?= $hCanBuild ? ($hBuildHost !== '' ? $he($hBuildHost) : 'via your licence mesh') : ($hActivated ? 'no build server assigned' : 'activate to enable') ?></div></div>
        </div>
        <?php if ($hInTrial): ?>
        <div class="ppl-hchip">
            <span class="ppl-hicon warn"><i class="bi bi-hourglass-split"></i></span>
            <div><div class="t">Free trial</div><div class="v"><?= $he(P::human((int) ($status['graceLeft'] ?? 0))) ?> left</div><div class="s">enter a key to keep access</div></div>
        </div>
        <?php else: ?>
        <div class="ppl-hchip">
            <span class="ppl-hicon info"><i class="bi bi-<?= $he($hPlanIcon) ?>"></i></span>
            <div><div class="t">Plan</div><div class="v"><?= $he(ucfirst($hPlan)) ?></div>
                <div class="s"><?= is_array($seats) && isset($seats['used'], $seats['limit']) ? $he($seats['used'] . ' of ' . $seats['limit'] . ' seats') : 'server-side features' ?></div></div>
        </div>
        <?php endif; ?>
    </div>
    <?php endif; ?>

    <div class="ppl-card">
        <div class="ppl-hero">
            <div class="ppl-badge <?= $tone[0] ?>"><i class="bi bi-<?= $tone[1] ?>"></i></div>
            <div class="flex-grow-1">
                <div class="ppl-state"><?= htmlspecialchars($tone[2]) ?></div>
                <div class="ppl-reason"><?php
                    if (!empty($isBackup)) {
                        echo 'This is a backup licence server — a failover clone of the main. It needs no licence of its own and never expires or locks.';
                    } elseif (!empty($isAuthority)) {
                        echo 'This is your licence server — it issues and signs the licences your customers activate. It is the source of trust, so it needs no licence of its own and never expires or locks.';
                    } elseif (empty($enforced)) {
                        echo 'This copy does not require a licence — nothing here will ever lock. If this is your licence server, there is nothing to activate.';
                    } else {
                        echo htmlspecialchars((string) ($status['reason'] ?? ''));
                    }
                ?></div>
            </div>
            <?php if (!empty($status['activated'])): ?>
                <button class="btn btn-outline-secondary btn-sm" id="btnRefresh">
                    <i class="bi bi-arrow-repeat"></i> Refresh now
                </button>
            <?php endif; ?>
        </div>

        <?php if (!empty($status['activated'])): ?>
            <dl class="ppl-facts">
                <div class="ppl-fact"><dt>Licensed to</dt>
                    <dd><?= htmlspecialchars((string) ($status['holder'] ?: '—')) ?></dd></div>
                <div class="ppl-fact"><dt>Plan</dt>
                    <dd><?= htmlspecialchars((string) ($status['plan'] ?: 'standard')) ?></dd></div>
                <div class="ppl-fact"><dt>Licence key</dt>
                    <dd><code><?= htmlspecialchars((string) ($status['licenseHint'] ?? '—')) ?></code></dd></div>
                <?php if (is_array($seats)): ?>
                    <div class="ppl-fact"><dt>Installations</dt>
                        <dd><?= (int) ($seats['used'] ?? 0) ?> of <?= (int) ($seats['limit'] ?? 0) ?> in use</dd></div>
                <?php endif; ?>
                <div class="ppl-fact"><dt>Lease renews</dt>
                    <dd><?= $state === P::OK ? 'in ' . htmlspecialchars(P::human((int) $status['expiresIn'])) : '—' ?></dd></div>
                <div class="ppl-fact"><dt>Last contact</dt>
                    <dd><?= !empty($status['lastContact'])
                            ? htmlspecialchars(date('j M Y, H:i', (int) $status['lastContact']))
                            : 'never' ?></dd></div>
                <?php if (!empty($status['licenseEnds'])): ?>
                    <div class="ppl-fact"><dt>Licence ends</dt>
                        <dd><?= htmlspecialchars(date('j M Y', (int) $status['licenseEnds'])) ?></dd></div>
                <?php endif; ?>
                <div class="ppl-fact"><dt>Installation ID</dt>
                    <dd><code><?= htmlspecialchars(substr((string) ($status['instanceId'] ?? ''), 0, 12)) ?>…</code></dd></div>
                <?php if (!empty($status['endpoints'])):
                    // Show a short, professional code for the licence server rather
                    // than the raw URL — cleaner, and the address stays out of view
                    // (and out of screenshots). The full URL is on hover for anyone
                    // who needs it. Suffix = the ccTLD when present (e.g. NP), else a
                    // short deterministic hash so every server still reads distinctly.
                    $__srvUrl  = (string) ($status['endpoints'][0] ?? '');
                    $__host    = strtolower((string) (parse_url($__srvUrl, PHP_URL_HOST) ?: $__srvUrl));
                    $__host    = (string) preg_replace('/^www\./', '', $__host);
                    $__parts   = array_values(array_filter(explode('.', $__host)));
                    $__last    = $__parts ? (string) end($__parts) : '';
                    $__suffix  = (strlen($__last) === 2 && ctype_alpha($__last))
                        ? strtoupper($__last)
                        : strtoupper(substr(base_convert(substr(hash('crc32b', $__host), 0, 6), 16, 36), 0, 3));
                    // Prefer the vendor's own label for this server (set on the licence
                    // server, carried in the signed lease); fall back to a derived code.
                    $__vendorLabel = trim((string) ($status['serverLabel'] ?? ''));
                    $__srvCode = $__vendorLabel !== '' ? $__vendorLabel
                        : 'SEC-SRV-' . ($__suffix !== '' ? $__suffix : 'NET');
                ?>
                    <div class="ppl-fact"><dt>Licence service
                            <span class="ppl-hint" tabindex="0" role="img"
                                  aria-label="A short code for the licence server this copy checks in with. Hover the code to see its full address."
                                  title="A short code for the licence server this copy checks in with. Hover the code to see its full address.">?</span>
                        </dt>
                        <dd style="display:flex;align-items:center;flex-wrap:wrap;gap:.4rem">
                            <code title="<?= htmlspecialchars($__srvUrl) ?>" style="cursor:help"><?= htmlspecialchars($__srvCode) ?></code>
                            <?php if (count($status['endpoints']) > 1): $__bk = count($status['endpoints']) - 1; ?>
                                <span class="ppl-bk" tabindex="0"
                                      title="<?= $__bk ?> backup licence <?= $__bk === 1 ? 'server is' : 'servers are' ?> used automatically if the primary (<?= htmlspecialchars($__srvCode) ?>) is unreachable.">
                                    +<?= $__bk ?> backup</span>
                            <?php endif; ?>
                        </dd></div>
                <?php endif; ?>
            </dl>

            <?php if (!empty($status['lastError'])): ?>
                <div class="ppl-note warn mt-3">
                    <strong>Last check didn't go through</strong>
                    <div class="mt-1"><?= htmlspecialchars((string) $status['lastError']) ?></div>
                </div>
            <?php endif; ?>
        <?php endif; ?>
    </div>

    <?php
        // What this licence's plan unlocks. Labels come from the shared catalogue
        // (Capability ships to clients); the granted keys ride in the signed lease.
        $__caps    = is_array($status['capabilities'] ?? null) ? $status['capabilities'] : [];
        $__catalog = class_exists(\PpPhp\Core\Licensing\Capability::class) ? \PpPhp\Core\Licensing\Capability::CATALOG : [];
        $__planName  = trim((string) ($status['planName'] ?? '')) ?: ucwords(str_replace(['-', '_'], ' ', trim((string) ($status['plan'] ?? ''))));
        $__planIcon  = trim((string) ($status['planIcon'] ?? '')) ?: 'box-seam';
        $__planColor = trim((string) ($status['planColor'] ?? '')) ?: '#64748b';
    ?>
    <?php if (!empty($status['activated']) && $__catalog && empty($isBackup)): ?>
    <div class="ppl-card">
        <h2 style="display:flex;align-items:center;gap:.55rem">
            <span class="ppl-plan-badge" style="--c:<?= htmlspecialchars($__planColor) ?>"><i class="bi bi-<?= htmlspecialchars($__planIcon) ?>"></i></span>
            Your plan<?= $__planName !== '' ? ' — ' . htmlspecialchars($__planName) : '' ?></h2>
        <p class="ppl-sub">The server-side features included with this licence. Contact your provider to change plan.</p>
        <div class="ppl-caps">
            <?php foreach ($__catalog as $__k => $__m): $__on = in_array($__k, $__caps, true); ?>
                <div class="ppl-cap <?= $__on ? 'on' : 'off' ?>" title="<?= htmlspecialchars($__m['desc']) ?>">
                    <span class="ic"><i class="bi bi-<?= $__on ? htmlspecialchars($__m['icon']) : 'lock' ?>"></i></span>
                    <span class="lb"><?= htmlspecialchars($__m['label']) ?></span>
                    <i class="bi bi-<?= $__on ? 'check-circle-fill' : 'dash-circle' ?> st"></i>
                </div>
            <?php endforeach; ?>
        </div>
    </div>
    <?php endif; ?>

    <?php if (!empty($isBackup)): ?>
        <div class="ppl-card">
            <h2>This is a backup server</h2>
            <p class="ppl-sub mb-0">
                It mirrors the main licence server<?= $roleMainUrl !== '' ? ' at <code>' . htmlspecialchars($roleMainUrl) . '</code>' : '' ?>
                for redundancy and failover only. A backup carries no licence of its own, so there is
                <strong>nothing to activate here and no expiry to track</strong> — clients reach it automatically
                if the main is ever unavailable.
                <?php if ($isOwner): ?>
                    Manage pairing and sync from the <a href="<?= $b ?>/licensing/server">licence server</a> page.
                <?php endif; ?>
            </p>
        </div>
    <?php elseif (!$enforced): ?>
        <div class="ppl-card">
            <h2>Licensing is not enforced on this copy</h2>
            <p class="ppl-sub mb-0">
                This is unstamped source rather than a released build, so nothing here restricts anything —
                you can activate to test the flow, but the console will never lock.
                <?php if ($isOwner): ?>
                    Stamp your public key on the <a href="<?= $b ?>/licensing/server">licence server</a> page to turn
                    enforcement on for the bundles you ship.
                <?php endif; ?>
            </p>
        </div>
    <?php endif; ?>

    <?php if (empty($isBackup)): ?>
    <?php
        $reactivate = !empty($status['activated']);
        // Activating against a SEPARATE licence is a rare, deliberate action on any
        // copy that isn't a plain unactivated client — the licence server itself, or
        // an unenforced/dev copy. Fold it away by default in those cases so the page
        // isn't dominated by a form nobody here needs. A genuine client that still
        // has to activate keeps the form open and prominent.
        $foldActivate = $reactivate || !empty($isAuthority) || empty($enforced);
    ?>
    <?php if ($foldActivate): ?>
    <details class="ppl-card ppl-reactivate">
        <summary>
            <span class="ppl-reactivate-title"><i class="bi bi-key"></i> <?= $reactivate ? 'Re-activate with a different key' : 'Activate this installation' ?></span>
            <span class="ppl-reactivate-hint"><?= $reactivate ? "Only if you're moving this install to another licence — click to open" : 'Only if this copy should run on a separate licence — click to open' ?></span>
            <i class="bi bi-chevron-down ppl-reactivate-chev"></i>
        </summary>
        <div class="ppl-reactivate-body">
    <?php else: ?>
    <div class="ppl-card">
        <h2>Activate this installation</h2>
    <?php endif; ?>
        <p class="ppl-sub">
            Paste the activation code from your licence email. It is one long string starting with
            <code>PPK1.</code> and carries everything needed — you don't have to enter a server address.
        </p>
        <div class="mb-2">
            <textarea class="form-control ppl-code" id="code" rows="3"
                      placeholder="PPK1.eyJ1IjoiaHR0cHM6Ly8…"></textarea>
        </div>
        <div class="mb-2">
            <label class="form-label small text-muted mb-1">Administrator email <span class="text-muted">— the address your licence was issued to</span></label>
            <input class="form-control form-control-sm" id="email" type="email" placeholder="you@example.com" autocomplete="email">
        </div>
        <div class="row g-2 align-items-end">
            <div class="col-sm-7">
                <label class="form-label small text-muted mb-1">Name this installation (optional)</label>
                <input class="form-control form-control-sm" id="label" placeholder="e.g. Production — acme.com">
            </div>
            <div class="col-sm-5 text-sm-end">
                <button class="btn btn-outline-secondary btn-sm me-1" id="btnTestConn"
                    title="Check whether this server can reach the licence server, before activating">
                    <i class="bi bi-wifi"></i> Test connection
                </button>
                <button class="btn btn-primary" id="btnActivate"><i class="bi bi-check2-circle"></i> Activate</button>
            </div>
        </div>
    <?php if ($foldActivate): ?>
        </div>
    </details>
    <?php else: ?>
    </div>
    <?php endif; ?>

    <div class="ppl-card">
        <h2>How this works</h2>
        <div class="ppl-note">
            <ul class="mb-0">
                <li>Your licence is a signed permission slip that verifies offline and checks in with our main
                    and backup servers <strong>every hour</strong> — to renew, and to learn the current backup
                    addresses so it always knows where to reach us if one server is down.</li>
                <li>If none of our servers can be reached, nothing stops right away — you have
                    <strong><?= (int) (P::RUNTIME_GRACE / 3600) ?> hours</strong> of grace, counted from the last
                    successful check, and it resets every time one succeeds. After that the console locks and
                    asks you to contact <a href="mailto:<?= htmlspecialchars($support) ?>"><?= htmlspecialchars($support) ?></a>.</li>
                <li>Apps you build are never affected. They contain no licensing code at all, so a lapse here
                    can never take a live site offline.</li>
                <li>Moving to a new server? Use <em>Release this seat</em> below, then activate there with the
                    same code.</li>
            </ul>
        </div>
    </div>
    <?php endif; /* empty($isBackup) — activation + client-licensing help hidden on a backup */ ?>

    <?php if (!empty($status['activated'])): ?>
        <div class="ppl-card">
            <h2 class="ppl-danger">Release this seat</h2>
            <p class="ppl-sub mb-2">
                Frees the seat on your licence so another server can use it. This copy stops being licensed
                immediately — do it when you are decommissioning or migrating, not to troubleshoot.
            </p>
            <button class="btn btn-outline-danger btn-sm" id="btnDeactivate">
                <i class="bi bi-box-arrow-right"></i> Release this seat
            </button>
        </div>
    <?php endif; ?>
</div>

<script>
(function () {
    const B = '<?= $b ?>', TOKEN = '<?= htmlspecialchars($token) ?>';

    async function post(path, body, btn) {
        const label = btn ? btn.innerHTML : '';
        if (btn) { btn.disabled = true; btn.innerHTML = '<span class="spinner-border spinner-border-sm"></span> Working…'; }
        try {
            const r = await fetch(B + path, {
                method: 'POST', credentials: 'same-origin',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(Object.assign({ _token: TOKEN }, body))
            });
            return await r.json();
        } catch (e) {
            return { success: false, message: 'The request could not be sent: ' + e.message };
        } finally {
            if (btn) { btn.disabled = false; btn.innerHTML = label; }
        }
    }

    const done = (res) => Swal.fire({
        icon: res.success ? 'success' : 'error',
        title: res.success ? 'Done' : 'Not completed',
        text: res.message || '',
        confirmButtonText: 'OK'
    }).then(() => { if (res.success) location.reload(); });

    document.getElementById('btnActivate')?.addEventListener('click', async (e) => {
        const code = document.getElementById('code').value.trim();
        const email = document.getElementById('email').value.trim();
        if (!code) {
            Swal.fire({ icon: 'info', title: 'Paste your activation code', text: 'It starts with "PPK1." and comes from your licence email.' });
            return;
        }
        done(await post('/licensing/activate', { code, email, label: document.getElementById('label').value.trim() }, e.currentTarget));
    });

    document.getElementById('btnTestConn')?.addEventListener('click', async (e) => {
        const code = (document.getElementById('code')?.value || '').trim();
        const res = await post('/licensing/diagnose', code ? { code } : {}, e.currentTarget);
        const box = (s) => '<div style="margin:.35rem 0;padding:.4rem .55rem;border-radius:.4rem;background:color-mix(in srgb,var(--pp-text,#1e293b) 5%,transparent);font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;word-break:break-word">' + String(s).replace(/[<>]/g, '') + '</div>';
        // Build a compact technical detail block so the exact cause is visible.
        let rows = (res.targets || []).map(function (r) {
            const status = r.reachable ? '✅ reachable'
                : (r.httpStatus ? ('HTTP ' + r.httpStatus + (r.isJson ? '' : ' · not the licence API'))
                                : ('no connection · curl errno ' + r.errno));
            return box([
                r.url, status,
                r.ip ? ('IP ' + r.ip) : 'IP —',
                (r.connectMs ? ('connect ' + r.connectMs + 'ms') : 'connect —'),
                (r.error ? ('“' + r.error + '”') : '')
            ].filter(Boolean).join(' · '));
        }).join('');
        // Egress layer — the decisive part: does ANY outbound 443 work?
        const eg = res.egress;
        if (eg) {
            const line = (t) => t ? (t.target + ' → ' + (t.open ? ('✅ open (' + t.ms + 'ms)') : ('✗ blocked · ' + (t.error || ('errno ' + t.errno)))) ) : '';
            rows += box('Outbound port 443 reachability:');
            if (eg.authority) rows += box('licence server  ' + line(eg.authority) + (eg.resolvedIp ? ('  · resolves to ' + eg.resolvedIp) : ''));
            (eg.neutral || []).forEach(function (n) { rows += box('neutral         ' + line(n)); });
        }
        Swal.fire({
            icon: res.success ? 'success' : (res.verdict === 'no-target' ? 'info' : 'error'),
            title: res.success ? 'Licence server reachable' : 'Cannot reach the licence server',
            html: '<div style="text-align:left"><p style="margin:.25rem 0 .5rem">' +
                  (res.message || '').replace(/[<>]/g, '') + '</p>' + rows + '</div>',
            width: 620,
            confirmButtonText: 'OK'
        });
    });

    document.getElementById('btnRefresh')?.addEventListener('click', async (e) =>
        done(await post('/licensing/refresh', {}, e.currentTarget)));

    document.getElementById('btnDeactivate')?.addEventListener('click', async (e) => {
        const btn = e.currentTarget;
        const ask = await Swal.fire({
            icon: 'warning', title: 'Release this seat?',
            text: 'This installation stops being licensed straight away. Apps you have already built keep running.',
            showCancelButton: true, confirmButtonText: 'Release it', confirmButtonColor: '#dc2626'
        });
        if (ask.isConfirmed) done(await post('/licensing/deactivate', {}, btn));
    });
})();
</script>
</body>
</html>
