// ══ Deploy client — wiring ═════════════════════════════════════════

function readModalProfile() {
    return {
        id: +$('pfId').value || 0,
        name: $('pfName').value.trim(),
        protocol: $('pfProtocol').value,
        host: $('pfHost').value.trim(),
        port: $('pfPort').value.trim(),
        user: $('pfUser').value,
        pass: $('pfPass').value,
        remotePath: $('pfRemotePath').value.trim(),
        siteUrl: $('pfSiteUrl').value.trim(),
        passive: $('pfPassive').checked,
        privateKeyFile: $('pfKeyFile').value.trim(),
        privateKeyPass: $('pfKeyPass').value,
    };
}

function writeModalProfile(c) {
    c = c || {};
    $('pfId').value = c.id || '';
    $('pfName').value = c.name || '';
    $('pfProtocol').value = c.protocol || 'ftp';
    $('pfHost').value = c.host || '';
    $('pfPort').value = c.port || '';
    $('pfUser').value = c.user || '';
    $('pfPass').value = '';
    $('pfRemotePath').value = c.remotePath || '';
    $('pfSiteUrl').value = c.siteUrl || '';
    $('pfPassive').checked = c.passive !== false;
    $('pfKeyFile').value = c.privateKeyFile || '';
    $('pfKeyPass').value = '';
    $('pfPassHint').textContent = c.id && c.hasPassword ? '(leave blank to keep saved)' : '';
    $('modalTestResult').innerHTML = '<span class="text-muted">Press <strong>Test</strong> to verify the connection.</span>';
    $('modalDiag').innerHTML = '';
    syncProtocolFields();
}

function syncProtocolFields() {
    const isSftp = $('pfProtocol').value === 'sftp';
    document.querySelectorAll('.pf-sftp-only').forEach((el) => el.classList.toggle('d-none', !isSftp));
    document.querySelectorAll('.pf-ftp-only').forEach((el) => el.classList.toggle('d-none', isSftp));
    const p = $('pfPort');
    if (!p.value || p.value === '21' || p.value === '22') p.value = isSftp ? '22' : '21';
}

function openConnModal(conn) {
    $('connModalTitle').textContent = conn ? 'Edit connection' : 'New connection';
    writeModalProfile(conn || { protocol: 'ftp', port: '21', passive: true });
    D.connModal.show();
}

function switchTab(tab) {
    document.querySelectorAll('.dock-tab').forEach((t) => t.classList.toggle('active', t.dataset.tab === tab));
    document.querySelectorAll('.dock-panel').forEach((p) => p.classList.toggle('active', p.id === 'tab-' + tab));
}

// ── Live-DB connection manager ─────────────────────────────────────
const DB_PORTS = { mysql: '3306', pgsql: '5432', sqlsrv: '1433', sqlite: '' };

function renderDbmSelect(selectId = 0) {
    const sel = $('dbmSelect');
    sel.innerHTML = '<option value="0">＋ New live database connection…</option>';
    D.dbConnections.forEach((c) => {
        const o = document.createElement('option');
        o.value = c.id;
        o.textContent = `${c.name} — ${c.dbname || '(no db)'} @ ${c.host}`;
        sel.appendChild(o);
    });
    sel.value = selectId;
}
function readDbForm() {
    return { id: +$('dbmId').value || 0, name: $('dbmName').value.trim(), type: $('dbmType').value,
        host: $('dbmHost').value.trim(), port: $('dbmPort').value.trim(), dbname: $('dbmDbname').value.trim(),
        charset: $('dbmCharset').value.trim() || 'utf8mb4', user: $('dbmUser').value, pass: $('dbmPass').value };
}
function writeDbForm(c) {
    c = c || {};
    $('dbmId').value = c.id || '';
    $('dbmName').value = c.name || '';
    $('dbmType').value = c.type || 'mysql';
    $('dbmHost').value = c.host || '';
    $('dbmPort').value = c.port || (c.id ? '' : DB_PORTS[c.type || 'mysql']);
    $('dbmDbname').value = c.dbname || '';
    $('dbmCharset').value = c.charset || 'utf8mb4';
    $('dbmUser').value = c.user || '';
    $('dbmPass').value = '';
    $('dbmPassHint').textContent = c.id && c.hasPassword ? '(leave blank to keep saved)' : '';
    $('btnDbDelete').classList.toggle('d-none', !c.id);
    $('dbmTestResult').innerHTML = '<span class="text-muted">Test the connection before saving.</span>';
}
function openDbManager() { renderDbmSelect(0); writeDbForm(null); D.dbModal.show(); }

// ── Upload / dry-run ───────────────────────────────────────────────
async function runUpload(dryRun) {
    if (D.busy) { toast('A transfer is already running.', 'warning'); return; }
    const conn = activeConn();
    if (!conn) { toast('Select a server connection first.', 'warning'); return; }

    D.busy = true;
    $('ftpApp').classList.add('busy');
    switchTab('log');
    const btn = dryRun ? $('btnDryRun') : $('btnUpload');
    const orig = btn.innerHTML;
    btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>' + (dryRun ? 'Scanning…' : 'Uploading…');
    setStatus(`<i class="bi bi-arrow-repeat text-primary me-1"></i>${dryRun ? 'Scanning' : 'Uploading to ' + esc(conn.host)}…`);
    $('uploadProgressWrap').classList.remove('d-none');
    const bar = $('uploadProgress'); bar.style.width = '12%';
    const creep = setInterval(() => { const w = parseFloat(bar.style.width) || 12; if (w < 90) bar.style.width = (w + 5) + '%'; }, 350);

    try {
        const json = await api('upload', {
            connectionId: conn.id, mode: D.options.mode, dbConnection: D.options.dbConnection, dryRun: !!dryRun,
        });
        clearInterval(creep); bar.style.width = '100%';
        renderLog(json.log || []);
        if (json.success) {
            toast(json.message, json.failed > 0 ? 'warning' : 'success');
            setStatus(`<i class="bi bi-check-circle-fill text-success me-1"></i>${esc(json.message)}`);
            if (json.history) { D.history = json.history; renderHistory(); D.stats.uploads = (D.stats.uploads || 0) + (dryRun ? 0 : 1); renderStats(); }
            if (json.openUrl) {
                D.lastOpenUrl = json.openUrl;
                if (!dryRun && D.options.openInBrowser) window.open(json.openUrl, '_blank', 'noopener');
            }
            if (!dryRun && D.connected) remoteGo(D.remotePath);
        } else {
            toast(json.message || 'Upload failed.', 'danger');
            setStatus(`<i class="bi bi-x-circle-fill text-danger me-1"></i>${esc(json.message || 'Upload failed')}`);
        }
    } catch (e) {
        clearInterval(creep);
        toast('Network error: ' + e.message, 'danger');
    } finally {
        D.busy = false;
        $('ftpApp').classList.remove('busy');
        btn.innerHTML = orig;
        setTimeout(() => { $('uploadProgressWrap').classList.add('d-none'); bar.style.width = '0%'; }, 1000);
    }
}

// ── Test ───────────────────────────────────────────────────────────
async function testConnection(payload, resultEl, diagTarget, btn) {
    const orig = btn ? btn.innerHTML : '';
    if (btn) { btn.disabled = true; btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Testing…'; }
    if (resultEl) resultEl.innerHTML = '<span class="text-muted">Probing connection…</span>';
    try {
        const json = await api('test', payload);
        renderDiag(json.report, diagTarget);
        if (resultEl) resultEl.innerHTML = json.success
            ? `<span class="text-success"><i class="bi bi-check-circle-fill me-1"></i>${esc(json.message)}</span>`
            : `<span class="text-danger"><i class="bi bi-x-circle-fill me-1"></i>${esc(json.message)}</span>`;
        toast(json.message, json.success ? 'success' : 'danger');
        return json;
    } catch (e) {
        if (resultEl) resultEl.innerHTML = `<span class="text-danger">Network error: ${esc(e.message)}</span>`;
        toast('Network error: ' + e.message, 'danger');
    } finally {
        if (btn) { btn.disabled = false; btn.innerHTML = orig; }
    }
}

// ── Boot ───────────────────────────────────────────────────────────
// Attractive tooltips on every tagged control.
function initTooltips() {
    if (!window.bootstrap || !bootstrap.Tooltip) return;
    document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach((el) => {
        if (!bootstrap.Tooltip.getInstance(el)) {
            new bootstrap.Tooltip(el, { customClass: 'ftp-tip', delay: { show: 350, hide: 0 }, trigger: 'hover' });
        }
    });
}

document.addEventListener('DOMContentLoaded', () => {
    D.connModal = new bootstrap.Modal($('connModal'));
    D.dbModal = new bootstrap.Modal($('dbModal'));
    initTooltips();

    D.connections = boot.connections || [];
    D.dbConnections = boot.dbConnections || [];
    D.options = Object.assign({ mode: 'changed', dbConnection: '__keep__', openInBrowser: true }, boot.options || {});
    D.history = boot.history || [];
    D.stats = boot.stats || { builds: 0, uploads: 0 };
    D.lastBuild = boot.lastBuild || null;
    D.outputDir = boot.outputDir || '';
    D.activeId = boot.activeId || (D.connections[0] ? D.connections[0].id : 0);

    $('localRootLabel').textContent = D.outputDir;
    renderConnSelect();
    renderDbSelect();
    renderHistory();
    renderStats();
    setConnected(false);

    // Apply saved options to controls
    document.querySelectorAll('#modeSeg .seg').forEach((s) => s.classList.toggle('active', s.dataset.mode === D.options.mode));
    $('openInBrowser').checked = D.options.openInBrowser !== false;

    localGo('');

    // Connection select
    $('connSelect').addEventListener('change', (e) => {
        D.activeId = +e.target.value;
        renderConnSelect(); renderStats();
        setConnected(false, 'Disconnected');
        $('remoteList').innerHTML = document.getElementById('remoteEmpty') ? $('remoteList').innerHTML :
            '<div class="pane-empty"><i class="bi bi-hdd-network"></i><p>Not connected</p><span>Press <strong>Connect</strong> to browse.</span></div>';
        $('remoteList').innerHTML = '<div class="pane-empty"><i class="bi bi-hdd-network"></i><p>Not connected</p><span>Press <strong>Connect</strong> to browse the live files.</span></div>';
        $('remoteCrumbs').innerHTML = '';
        persist();
    });

    // Connect / disconnect
    $('btnConnect').addEventListener('click', () => {
        if (D.connected) {
            setConnected(false, 'Disconnected');
            $('remoteList').innerHTML = '<div class="pane-empty"><i class="bi bi-hdd-network"></i><p>Disconnected</p><span>Press <strong>Connect</strong> to browse again.</span></div>';
            $('remoteCrumbs').innerHTML = '';
            return;
        }
        const conn = activeConn();
        if (!conn) return;
        const start = conn.remotePath ? ('/' + conn.remotePath.replace(/^\/+/, '')) : '/';
        remoteGo(start);
    });

    // New / Edit / Delete
    $('btnNewConn').addEventListener('click', () => openConnModal(null));
    $('btnEditConn').addEventListener('click', () => { const c = activeConn(); if (c) openConnModal(c); });
    $('btnDelConn').addEventListener('click', async () => {
        const c = activeConn(); if (!c) return;
        const r = await Swal.fire({ title: 'Delete connection?', text: c.name, icon: 'warning',
            showCancelButton: true, confirmButtonText: 'Delete', confirmButtonColor: '#dc2626' });
        if (!r.isConfirmed) return;
        const res = await api('connection/delete', { id: c.id });
        if (res.success) { D.connections = res.connections; D.activeId = D.connections[0]?.id || 0; renderConnSelect(); renderStats(); setConnected(false); toast('Connection deleted.', 'info'); }
    });

    // Bar test
    $('btnTestConn').addEventListener('click', () => {
        const c = activeConn(); if (!c) return;
        switchTab('diag');
        testConnection({ connectionId: c.id }, null, 'diagBody', $('btnTestConn'));
    });

    // Modal: protocol toggle, password reveal, test, save
    $('pfProtocol').addEventListener('change', syncProtocolFields);
    $('pfPassToggle').addEventListener('click', () => { const el = $('pfPass'); el.type = el.type === 'password' ? 'text' : 'password'; });
    $('btnTestInModal').addEventListener('click', () => testConnection({ profile: readModalProfile() }, $('modalTestResult'), 'modalDiag', $('btnTestInModal')));
    $('btnSaveConn').addEventListener('click', async () => {
        const p = readModalProfile();
        if (!p.name) { toast('Give the connection a name.', 'warning'); return; }
        if (!p.host) { toast('Enter a host.', 'warning'); return; }
        const r = await api('connection/save', { profile: p });
        if (!r.success) { toast(r.message, 'danger'); return; }
        D.connections = r.connections;
        D.activeId = r.id;
        renderConnSelect(); renderStats();
        D.connModal.hide();
        toast('Connection saved.', 'success');
    });

    // Mode segmented
    document.querySelectorAll('#modeSeg .seg').forEach((s) => s.addEventListener('click', () => {
        document.querySelectorAll('#modeSeg .seg').forEach((x) => x.classList.remove('active'));
        s.classList.add('active'); D.options.mode = s.dataset.mode; persist();
    }));

    // DB select + open-in-browser
    $('dbConnectionSelect').addEventListener('change', (e) => { D.options.dbConnection = e.target.value; persist(); });

    // Live-DB manager
    $('btnManageDb').addEventListener('click', openDbManager);
    $('dbmSelect').addEventListener('change', (e) => {
        const c = D.dbConnections.find((x) => x.id === +e.target.value);
        writeDbForm(c || null);
    });
    $('dbmType').addEventListener('change', (e) => {
        if (!$('dbmId').value && (!$('dbmPort').value || Object.values(DB_PORTS).includes($('dbmPort').value))) {
            $('dbmPort').value = DB_PORTS[e.target.value] || '';
        }
    });
    $('dbmPassToggle').addEventListener('click', () => { const el = $('dbmPass'); el.type = el.type === 'password' ? 'text' : 'password'; });
    $('btnDbTest').addEventListener('click', async () => {
        const d = readDbForm();
        if (!d.dbname) { toast('Enter a database name to test.', 'warning'); return; }
        const btn = $('btnDbTest'), orig = btn.innerHTML, res = $('dbmTestResult');
        btn.disabled = true; btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Testing…';
        res.innerHTML = '<span class="text-muted">Connecting to the database…</span>';
        const r = await api('db/test', { db: d });
        btn.disabled = false; btn.innerHTML = orig;
        res.innerHTML = r.success
            ? `<span class="text-success"><i class="bi bi-check-circle-fill me-1"></i>${esc(r.message)}</span>`
            : `<span class="text-danger"><i class="bi bi-x-circle-fill me-1"></i>${esc(r.message)}</span>`;
        toast(r.message, r.success ? 'success' : 'danger');
    });
    $('btnDbSave').addEventListener('click', async () => {
        const d = readDbForm();
        if (!d.name) { toast('Give the database connection a name.', 'warning'); return; }
        const r = await api('db/save', { db: d });
        if (!r.success) { toast(r.message, 'danger'); return; }
        D.dbConnections = r.dbConnections;
        renderDbSelect();
        renderDbmSelect(r.id);
        writeDbForm(D.dbConnections.find((x) => x.id === r.id) || null);
        toast('Live database saved.', 'success');
    });
    $('btnDbDelete').addEventListener('click', async () => {
        const id = +$('dbmId').value; if (!id) return;
        const c = await Swal.fire({ title: 'Delete live database?', text: $('dbmName').value, icon: 'warning',
            showCancelButton: true, confirmButtonText: 'Delete', confirmButtonColor: '#dc2626' });
        if (!c.isConfirmed) return;
        const r = await api('db/delete', { id });
        if (r.success) { D.dbConnections = r.dbConnections; renderDbSelect(); renderDbmSelect(0); writeDbForm(null); toast('Deleted.', 'info'); }
    });
    $('openInBrowser').addEventListener('change', (e) => { D.options.openInBrowser = e.target.checked; persist(); });

    // Upload / dry run
    $('btnUpload').addEventListener('click', () => runUpload(false));
    $('btnDryRun').addEventListener('click', () => runUpload(true));

    // Remote pane controls
    $('btnRemoteRefresh').addEventListener('click', () => D.connected && remoteGo(D.remotePath));
    $('btnRemoteUp').addEventListener('click', remoteUp);
    $('btnRemoteMkdir').addEventListener('click', remoteMkdir);
    $('btnRemoteSetTarget').addEventListener('click', remoteSetTarget);
    $('btnLocalRefresh').addEventListener('click', () => localGo(D.localPath));

    // Dock tabs
    document.querySelectorAll('.dock-tab').forEach((t) => t.addEventListener('click', () => switchTab(t.dataset.tab)));

    setStatus('<i class="bi bi-circle-fill text-secondary me-1"></i>Ready');
});
