// Auto-extracted from backup-page.js (verbatim) — augments BackupPage.prototype. Loaded after the base.
Object.assign(BackupPage.prototype, {
    renderDashboard() {
        const summary = document.getElementById('backup-summary-row');
        const appGrid = document.getElementById('backup-app-grid');
        const locSummary = document.getElementById('backup-repo-list-summary');
        if (!summary || !appGrid || !locSummary) return;

        const d = this.dashboard || {};
        const locs = d.locations || [];
        const apps = d.apps || [];
        const totalSnapshots = Object.values(this.snapshotsByLoc).reduce((acc, r) => {
            return acc + (Array.isArray(r?.snapshots) ? r.snapshots.length : 0);
        }, 0);
        const protectedApps = apps.filter(a => a.latest_snapshot).length;
        const totalSize = locs.reduce((acc, r) => acc + (parseInt(r.total_size_bytes) || 0), 0);

        summary.innerHTML = `
            ${this.tile('Apps protected', `${protectedApps} / ${apps.length}`, 'with at least one backup')}
            ${this.tile('Backups', `${totalSnapshots}`, `across ${locs.length} location${locs.length === 1 ? '' : 's'}`)}
            ${this.tile('Total stored', this.formatBytes(totalSize), 'deduplicated, encrypted')}
        `;

        // Next-run hint in the "Backup status" card header — derived from
        // CFG_BACKUP_CRONTAB_APP (the cron expression the app-backup
        // scheduler uses). Pure client-side computation; no backend
        // surface needed.
        const nextRunEl = document.getElementById('backup-next-run');
        if (nextRunEl) {
            const cron = (window.systemConfigs?.CFG_BACKUP_CRONTAB_APP || '').trim();
            const next = cron ? this.nextCronFireTime(cron) : null;
            if (next) {
                nextRunEl.textContent = `Next backup ${this.formatRelativeFuture(next)} · ${this.formatScheduleClock(next)}`;
                nextRunEl.title = `Next scheduled backup: ${next.toLocaleString()}\nSchedule: ${cron}`;
            } else if (cron) {
                nextRunEl.textContent = `Schedule: ${cron}`;
                nextRunEl.title = `Couldn't parse the schedule "${cron}" to compute the next run.`;
            } else {
                nextRunEl.textContent = 'No schedule set';
                nextRunEl.title = 'CFG_BACKUP_CRONTAB_APP is empty — backups only run when triggered manually.';
            }
        }

        // System config tile is rendered FIRST so the bare-metal-restore
        // prerequisite is always at eye-level — without it, the user's
        // backups exist but the credentials needed to reach them don't.
        const systemTileHtml = this.renderSystemTile(d.system || {});
        if (!apps.length) {
            appGrid.innerHTML = systemTileHtml + `<div class="backup-empty-state">No apps installed yet.</div>`;
        } else {
            appGrid.innerHTML = systemTileHtml + apps.map(app => this.renderAppTile(app)).join('');
        }

        if (!locs.length) {
            locSummary.innerHTML = `<div class="backup-empty-state">No locations enabled.</div>`;
        } else {
            locSummary.innerHTML = locs.map(r => `
                <div class="backup-repo-row">
                    <div class="backup-repo-row-name">
                        <span class="backup-repo-type-pill">${this.escape(r.type)}</span>
                        ${this.escape(r.name)}
                    </div>
                    <div class="backup-repo-row-meta">
                        ${this.formatBytes(parseInt(r.total_size_bytes) || 0)}<br>
                        <span class="backup-card-hint">${r.total_files || 0} files</span>
                    </div>
                </div>
            `).join('');
        }
    },
    // System config tile — same shape as an app tile but with the LibrePortal
    // app icon. Clicking any tile (system or app) opens the Back-up checklist
    // modal with that tile pre-ticked; there are no inline action buttons
    // anymore. Rendered first in the Backup status grid so the bare-metal
    // prerequisite is always visible up top.
    renderSystemTile(sys) {
        const has = !!sys.latest_snapshot;
        const dot = has ? 'ok' : 'none';
        const when = has ? 'Last backed up ' + this.formatRelative(sys.latest_time) : 'No backup yet';
        return `
            <div class="backup-app-tile backup-app-tile--system" data-system="1" title="Back up system config">
                <img class="backup-app-tile-icon" src="/core/icons/apps/libreportal.svg" alt="" onerror="this.style.display='none'">
                <div class="backup-app-tile-text">
                    <div class="backup-app-tile-name">Configs</div>
                    <div class="backup-app-tile-meta">
                        <span class="backup-status-dot ${dot}"></span>
                        <span>${this.escape(when)}</span>
                    </div>
                </div>
                <button type="button" class="backup-app-tile-action" data-action="backup-now" data-system="1" title="Back up now">
                    Back up
                </button>
            </div>
        `;
    },
    tile(label, value, detail) {
        return `
            <div class="backup-summary-tile">
                <div class="backup-summary-tile-label">${this.escape(label)}</div>
                <div class="backup-summary-tile-value">${this.escape(value)}</div>
                <div class="backup-summary-tile-detail">${this.escape(detail || '')}</div>
            </div>
        `;
    },
    renderAppTile(app) {
        const has = !!app.latest_snapshot;
        const dot = has ? 'ok' : 'none';
        const when = has ? this.formatRelative(app.latest_time) : 'No backup yet';
        const { icon, displayName } = this.appMeta(app.app);
        return `
            <div class="backup-app-tile" data-app="${this.escape(app.app)}" title="Open ${this.escape(displayName)} backup history">
                <img class="backup-app-tile-icon" src="${this.escape(icon)}" alt="" onerror="this.src='/core/icons/apps/default.svg'">
                <div class="backup-app-tile-text">
                    <div class="backup-app-tile-name">${this.escape(displayName)}</div>
                    <div class="backup-app-tile-meta">
                        <span class="backup-status-dot ${dot}"></span>
                        <span>${when}</span>
                    </div>
                </div>
                <button type="button" class="backup-app-tile-action" data-action="backup-now" data-app="${this.escape(app.app)}" title="Back up now">
                    Back up
                </button>
            </div>
        `;
    },
});
