// SSH Access — inbound admin SSH to this host. Lives in the Admin area (a
// sidebar item on the Config/Admin page) and renders into whatever container
// it's given (defaults to #config-section). Authorize public keys (paste to
// grant access), remove them, and toggle password login behind the backend's
// lockout guard. Reads /data/ssh/access.json; mutations run as
// `libreportal ssh ...` tasks. LibrePortal never handles a private key here.
class SshPage {
    constructor(rootId = 'config-section') {
        this.rootId = rootId;
        this.taskManager = (typeof TaskManager !== 'undefined') ? new TaskManager() : null;
        this.data = null;
        this._bound = false;
    }

    root() { return document.getElementById(this.rootId); }

    async init() {
        const r = this.root();
        if (r) r.innerHTML = '<div class="ssh-page"><div class="backup-empty-state">Loading…</div></div>';
        this.bindEvents();
        await this.refresh();
        this.render();
    }

    async refresh() {
        this.data = await this.fetchJson(`/data/ssh/access.json?t=${Date.now()}`);
    }

    async fetchJson(url) {
        try { const r = await fetch(url); if (!r.ok) return null; return await r.json(); }
        catch { return null; }
    }

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

    notify(msg, type) {
        if (window.notificationSystem) window.notificationSystem.show(msg, type || 'info');
        else console.log(`[ssh ${type || 'info'}] ${msg}`);
    }

    bindEvents() {
        if (this._bound) return;
        this._bound = true;
        document.addEventListener('click', (e) => {
            if (e.target.closest('[data-action="ssh-add-key"]')) { this.addKey(); return; }
            const rm = e.target.closest('[data-action="ssh-remove-key"]');
            if (rm) { this.removeKey(rm.dataset.fp); return; }
            const tog = e.target.closest('[data-action="ssh-toggle-password"]');
            if (tog) { this.togglePassword(tog.dataset.next); return; }
        });
    }

    render() {
        const root = this.root();
        if (!root) return;
        if (!this.data) {
            root.innerHTML = `<div class="ssh-page"><div class="backup-empty-state">Couldn't load SSH access data.</div></div>`;
            return;
        }
        const d = this.data;
        const pwOn = d.password_auth === true;
        const keys = Array.isArray(d.keys) ? d.keys : [];

        const keysHtml = keys.length ? keys.map(k => `
            <div class="ssh-key-row">
                <div class="ssh-key-row-main">
                    <span class="ssh-key-type">${this.escape(k.type)}</span>
                    <span class="ssh-key-comment">${this.escape(k.comment || '(no comment)')}</span>
                    <span class="ssh-key-fp">${this.escape(k.fingerprint)}</span>
                </div>
                <button type="button" class="backup-danger-btn" data-action="ssh-remove-key" data-fp="${this.escape(k.fingerprint)}">Remove</button>
            </div>`).join('') : `<div class="backup-empty-state">No keys authorized yet — add one below to allow key-based login.</div>`;

        // Reuse the config page's section layout (.config-category/.domains-*)
        // so SSH Access looks like the rest of the Admin config pages.
        const section = (title, desc, inner) => `
            <div class="config-category">
                <div class="domains-wrapper">
                    <div class="domains-header"><div><h3>${title}</h3><p class="category-description">${desc}</p></div></div>
                    <div class="domains-divider"></div>
                    ${inner}
                </div>
                <div class="spacer spacer-lg"></div>
            </div>`;

        const loginInner = `
            <div class="ssh-section-body">
                <div class="admin-card-line"><span>Password login</span><strong>${pwOn ? 'On' : 'Key-only'}</strong></div>
                <div class="admin-card-line"><span>Authorized keys</span><strong>${keys.length}</strong></div>
                <div class="ssh-section-actions">
                    ${pwOn
                        ? `<button type="button" class="backup-secondary-btn" data-action="ssh-toggle-password" data-next="off">Require key-only login</button>`
                        : `<button type="button" class="backup-secondary-btn" data-action="ssh-toggle-password" data-next="on">Re-enable password login</button>`}
                </div>
            </div>`;

        const addInner = `
            <div class="ssh-section-body">
                <p class="category-description">Paste a <strong>public</strong> key (the <code>.pub</code> from your machine) to grant it SSH access.</p>
                <textarea class="backup-ssh-keyinput" id="ssh-add-key-input" rows="3" spellcheck="false" placeholder="ssh-ed25519 AAAA... you@laptop"></textarea>
                <div class="ssh-section-actions">
                    <button type="button" class="backup-primary-btn" data-action="ssh-add-key">Authorize key</button>
                </div>
            </div>`;

        root.innerHTML = `
            <div class="ssh-page">
                <div class="page-header config-page-header">
                    <div class="page-header-title">
                        <div class="admin-breadcrumb">Tools</div>
                        <h1>SSH Access</h1>
                        <p>Control who can SSH into this server (logging in as <code>${this.escape(d.user)}</code>). Grant access by adding a public key, and optionally require key-only login.</p>
                    </div>
                </div>
                ${section('Login', pwOn ? 'Password login is on. Add a key, then you can switch to key-only.' : 'Password login is disabled — only the keys below can connect.', loginInner)}
                ${section('Add a key', 'Authorize a new machine to log in.', addInner)}
                ${section('Authorized keys', 'Machines currently allowed to SSH in.', `<div class="ssh-key-list ssh-section-body">${keysHtml}</div>`)}
            </div>
        `;
    }

    async runTask(command) {
        if (!this.taskManager) { this.notify('Task system unavailable', 'error'); return; }
        try {
            await this.taskManager.createTask(command, 'ssh', null);
            setTimeout(() => this.refresh().then(() => this.render()), 1500);
        } catch (e) {
            this.notify(`Failed to queue task: ${e.message || e}`, 'error');
        }
    }

    async addKey() {
        const key = (document.getElementById('ssh-add-key-input')?.value || '').trim();
        if (!key) { this.notify('Paste a public key first', 'error'); return; }
        const b64 = btoa(unescape(encodeURIComponent(key)));
        await this.runTask(`libreportal ssh key-add ${b64}`);
    }

    async removeKey(fp) {
        if (!fp) return;
        if (!confirm('Remove this key? That machine will no longer be able to SSH in.')) return;
        await this.runTask(`libreportal ssh key-remove ${fp}`);
    }

    async togglePassword(next) {
        if (next === 'off' && !confirm('Disable password login? Make sure a key above works first — otherwise you could lock yourself out.')) return;
        await this.runTask(`libreportal ssh password-auth ${next}`);
    }
}

window.SshPage = SshPage;
