{* Mail Servers — type=mail only. Web and DNS live on their own pages. *}
<div class="panel panel-default">
    <div class="panel-heading">
        <h3 class="panel-title pull-left"><i class="fa fa-envelope"></i> Mail Servers</h3>
        <div class="pull-right">
            <select id="puq-filter-group" class="input-sm" style="margin-right:6px;">
                <option value="">All groups</option>
            </select>
            <button class="btn btn-primary btn-sm" id="puq-add-btn"><i class="fa fa-plus"></i> Add Mail Server</button>
        </div>
        <div class="clearfix"></div>
    </div>
    <div class="panel-body">
        <table class="table table-striped table-bordered" id="puq-data-table" style="width:100%;">
            <thead>
                <tr>
                    <th style="width:50px;">ID</th>
                    <th>Server</th>
                    <th style="width:120px;">Group</th>
                    <th style="width:90px;">Status</th>
                    <th style="width:90px;">Capacity</th>
                    <th style="width:180px;">Actions</th>
                </tr>
            </thead>
            <tbody><tr><td colspan="6" class="text-center"><i class="fa fa-spinner fa-spin"></i> Loading…</td></tr></tbody>
        </table>
    </div>
</div>

{include file="$dir/templates/_server_modal.tpl" scopeTypes="mail"}

{literal}
<script>
(function(){
    var baseUrl = '{/literal}{$meta.admin_module_url}&ajax={literal}';
    var SERVER_TYPE = 'mail';
    var driversByType = { web: ['hestiacp'], mail: ['hestiacp'], dns: ['hestiacp','powerdns'] };
    var editingId = null;
    function pctColor(p){
        if (p == null || isNaN(p)) return 'default';
        if (p >= 90) return 'danger';
        if (p >= 75) return 'warning';
        if (p >= 50) return 'info';
        return 'success';
    }
    function metricCell(icon, label, pct, detail){
        if (pct == null) {
            return '<div class="m-cell"><div class="m-label"><i class="fa ' + icon + '"></i>' + esc(label) + '</div>' +
                   '<div class="m-bar"><div style="width:0%"></div></div><div class="m-pct text-muted">—</div></div>';
        }
        var cls   = pctColor(pct);
        var pctI  = Math.min(100, Math.max(0, pct));
        var pctTxt= (pct % 1 === 0 ? pct : pct.toFixed(1)) + '%';
        var title = label + (detail ? ' — ' + detail : '') + ' (' + pctTxt + ')';
        var pctExtra = (cls === 'danger') ? ' m-pct-danger' : (cls === 'warning' ? ' m-pct-warning' : '');
        return '<div class="m-cell" title="' + esc(title) + '">' +
                 '<div class="m-label"><i class="fa ' + icon + '"></i>' + esc(label) + '</div>' +
                 '<div class="m-bar m-bar-' + cls + '"><div style="width:' + pctI + '%"></div></div>' +
                 '<div class="m-pct' + pctExtra + '">' + pctTxt + '</div>' +
               '</div>';
    }
    function healthBadgeInline(state, err){
        var cls = {never:'default',queued:'warning',collecting:'info',ok:'success',error:'danger'}[state]||'default';
        var errIcon = state === 'error' && err ? ' <i class="fa fa-exclamation-triangle" title="'+escAttr(err)+'"></i>' : '';
        return '<span class="label label-'+cls+'">'+esc((state||'never').toUpperCase())+errIcon+'</span>';
    }

    function load() {
        var groupId = $('#puq-filter-group').val() || '';
        var qs = 'type=' + encodeURIComponent(SERVER_TYPE);
        if (groupId !== '') qs += '&group_id=' + encodeURIComponent(groupId);
        puqAjax({
            container: '#puq-data-table',
            loadingCaption: 'Loading mail servers…',
            url: baseUrl + 'listServers&' + qs,
            dataType: 'json',
            success: function(r) {
                var $tbody = $('#puq-data-table tbody').empty();
                if (r.status !== 'success' || !r.data.length) {
                    $tbody.append('<tr><td colspan="6" class="text-center text-muted">No mail servers yet.</td></tr>');
                    return;
                }
                r.data.forEach(function(s) {
                    var statusLbl = s.status === 'active' ? 'success' : s.status === 'maintenance' ? 'warning' : 'default';
                    var cap = (s.capacity_used != null ? s.capacity_used : '—') + ' / ' + (s.capacity_max != null ? s.capacity_max : '—');
                    var summary = s.status_summary;
                    var summaryTxt = '';
                    if (summary && typeof summary === 'object') {
                        var loadPct = (summary.load_1 != null && summary.cpu_cores)
                            ? Math.round(summary.load_1 * 100 / summary.cpu_cores) : null;
                        var loadTxt = (summary.load_1!=null?summary.load_1.toFixed(2):'—') + ' / ' +
                                      (summary.load_5!=null?summary.load_5.toFixed(2):'—') + ' / ' +
                                      (summary.load_15!=null?summary.load_15.toFixed(2):'—') + ' (1/5/15m)';
                        var cells =
                            metricCell('fa-microchip',      'CPU',  summary.cpu_percent,
                                       summary.cpu_cores ? (summary.cpu_cores + ' cores') : null) +
                            metricCell('fa-memory',         'RAM',  summary.mem_percent,
                                       fmtBytes(summary.mem_used) + ' / ' + fmtBytes(summary.mem_total)) +
                            metricCell('fa-hdd',            'Disk', summary.disk_percent,
                                       fmtBytes(summary.disk_used) + ' / ' + fmtBytes(summary.disk_total) +
                                       ' · free ' + fmtBytes(summary.disk_free)) +
                            metricCell('fa-tachometer-alt', 'Load', loadPct, loadTxt);

                        var pills = [];
                        if (summary.hestia_version) pills.push('<span class="pill" title="Hestia version"><i class="fa fa-code-branch"></i>v' + esc(summary.hestia_version) + '</span>');
                        if (summary.os)             pills.push('<span class="pill" title="OS"><i class="fa fa-cube"></i>' + esc(summary.os) + '</span>');
                        if (summary.users_count != null) pills.push('<span class="pill" title="Users"><i class="fa fa-user"></i>' + summary.users_count + '</span>');
                        if (summary.packages_count != null) pills.push('<span class="pill" title="Packages"><i class="fa fa-box"></i>' + summary.packages_count + '</span>');
                        if (summary.services_running != null && summary.services_count != null) {
                            var ok = summary.services_running === summary.services_count;
                            var svcColor = ok ? '' : ' style="background:#fff3cd;color:#8a6d3b"';
                            pills.push('<span class="pill"' + svcColor + ' title="Services running/total"><i class="fa fa-cogs"></i>' + summary.services_running + '/' + summary.services_count + '</span>');
                        }
                        if (summary.ips_count != null) pills.push('<span class="pill" title="IPs"><i class="fa fa-network-wired"></i>' + summary.ips_count + '</span>');

                        summaryTxt = '<div class="puq-metrics">' + cells + '</div>' +
                                     (pills.length ? '<div class="puq-inventory">' + pills.join('') + '</div>' : '');
                    }
                    var actionsUrl = '{/literal}{$meta.admin_module_url}{literal}&page=server_actions&server_id=' + s.id;

                    var headTs = s.status_last_collected_at
                        ? '<span class="srv-health-ts" title="Last collected">' + esc(s.status_last_collected_at.substring(0,16)) + '</span>'
                        : '';
                    var capsHead = '';
                    [['web', 'caps_web', 'primary'],
                     ['mail', 'caps_mail', 'success'],
                     ['dns', 'caps_dns', 'info']].forEach(function (pair) {
                        var on = parseInt(s[pair[1]] || 0, 10) === 1;
                        capsHead += '<span class="label label-' + (on ? pair[2] : 'default')
                            + '" style="margin-right:2px;opacity:' + (on ? 1 : 0.3) + ';">'
                            + pair[0] + '</span>';
                    });
                    var serverCell =
                        '<div class="puq-server-cell">' +
                          '<div class="srv-head">' +
                            capsHead +
                            '<span class="srv-name">' + esc(s.name) + '</span>' +
                            '<span class="srv-host">' + esc(s.hostname) + ':' + s.port + '</span>' +
                            '<span class="srv-driver">' + esc(s.driver) + '</span>' +
                            healthBadgeInline(s.status_state, s.status_error) +
                            headTs +
                          '</div>' +
                          summaryTxt +
                        '</div>';

                    var groupCell = s.group_name
                        ? '<span class="label label-default" title="Group #' + s.group_id + '">' + esc(s.group_name) + '</span>'
                        : '<span class="text-muted">—</span>';

                    $tbody.append(
                        '<tr data-id="' + s.id + '">' +
                        '<td>' + s.id + '</td>' +
                        '<td>' + serverCell + '</td>' +
                        '<td>' + groupCell + '</td>' +
                        '<td><span class="label label-' + statusLbl + '">' + esc(s.status) + '</span></td>' +
                        '<td>' + cap + '</td>' +
                        '<td>' +
                          '<button class="btn btn-xs btn-info puq-test" title="Test"><i class="fa fa-plug"></i></button> ' +
                          '<button class="btn btn-xs btn-default puq-refresh" title="Refresh status"><i class="fa fa-sync"></i></button> ' +
                          '<a class="btn btn-xs btn-success puq-nav-link" href="' + actionsUrl + '" title="Actions"><i class="fa fa-bolt"></i></a> ' +
                          '<button class="btn btn-xs btn-primary puq-edit"><i class="fa fa-edit"></i></button> ' +
                          '<button class="btn btn-xs btn-danger puq-delete"><i class="fa fa-trash"></i></button>' +
                        '</td></tr>'
                    );
                });
            }
        });
    }

    function loadFilterGroups() {
        $.ajax({
            url: baseUrl + 'listServerGroups', dataType: 'json',
            success: function(r) {
                var $sel = $('#puq-filter-group');
                $sel.find('option:not([value=""])').remove();
                (r.data || []).forEach(function(g) {
                    $sel.append('<option value="' + g.id + '">' + esc(g.name) + '</option>');
                });
            }
        });
    }
    function loadGroups(selected) {
        // Gate Save until the group list is rendered (see web_servers.tpl): a
        // premature/failed load would post an empty group_id and detach the
        // server's group.
        $('#puq-modal-save').prop('disabled', true);
        $.ajax({
            url: baseUrl + 'listServerGroups', dataType: 'json',
            success: function(r) {
                var $sel = $('#puq-field-group').empty().append('<option value="">—</option>');
                (r.data || []).forEach(function(g) { $sel.append('<option value="' + g.id + '">' + esc(g.name) + '</option>'); });
                if (selected) $sel.val(selected);
                $('#puq-modal-save').prop('disabled', false);
            },
            error: function() {
                showNotification('Failed to load server groups — cannot save (refresh and retry).', 'error');
            }
        });
    }
    function loadTemplates(selected) {
        $.ajax({
            url: baseUrl + 'listDnsZoneTemplates', dataType: 'json',
            success: function(r) {
                var $sel = $('#puq-field-template').empty().append('<option value="">—</option>');
                (r.data || []).forEach(function(t) { $sel.append('<option value="' + t.id + '">' + esc(t.name) + (t.is_default==1?' (default)':'') + '</option>'); });
                if (selected) $sel.val(selected);
            }
        });
    }
    function refreshDriverDropdown(type, selectedDriver) {
        var drivers = driversByType[type] || ['hestiacp'];
        var $sel = $('#puq-field-driver').empty();
        drivers.forEach(function(d) { $sel.append('<option value="'+d+'">'+d+'</option>'); });
        if (selectedDriver && drivers.indexOf(selectedDriver) !== -1) $sel.val(selectedDriver);
    }

    function renderDriverConfig(type, driver, cfg) {
        $.ajax({
            url: baseUrl + 'getDriverConfigSchema&type=' + encodeURIComponent(type) + '&driver=' + encodeURIComponent(driver),
            dataType: 'json',
            success: function(r) {
                var $host = $('#puq-driver-config').empty();
                var schema = (r.data || {});
                Object.keys(schema).forEach(function(key) {
                    var f = schema[key];
                    var val = (cfg && cfg[key] != null) ? cfg[key] : f.default;
                    var html = '';
                    if (f.type === 'checkbox') {
                        html = '<div class="form-group" data-field="config.' + key + '"><label>' +
                            '<input type="hidden" name="config['+key+']" value="0">' +
                            '<input type="checkbox" name="config['+key+']" value="1" ' + (val ? 'checked' : '') + '> ' +
                            esc(f.label) + '</label>' +
                            (f.help ? '<div class="help-block small">' + esc(f.help) + '</div>' : '') + '</div>';
                    } else if (f.type === 'select') {
                        var opts = '';
                        Object.keys(f.options || {}).forEach(function(k){
                            opts += '<option value="' + esc(k) + '"' + (String(val) === String(k) ? ' selected' : '') + '>' + esc(f.options[k]) + '</option>';
                        });
                        html = '<div class="form-group" data-field="config.' + key + '"><label>' + esc(f.label) + '</label>' +
                            '<select class="form-control" name="config['+key+']" style="max-width:300px">' + opts + '</select>' +
                            (f.help ? '<div class="help-block small">' + esc(f.help) + '</div>' : '') + '</div>';
                    } else {
                        var inputType = f.type === 'number' ? 'number' : 'text';
                        html = '<div class="form-group" data-field="config.' + key + '"><label>' + esc(f.label) + '</label>' +
                            '<input type="' + inputType + '" class="form-control" name="config['+key+']" value="' + esc(val) + '">' +
                            (f.help ? '<div class="help-block small">' + esc(f.help) + '</div>' : '') + '</div>';
                    }
                    $host.append(html);
                });
            }
        });
    }

    function openModal(row) {
        editingId = row ? row.id : null;
        var f = $('#puq-modal-form')[0];
        f.reset();
        formClearErrors('#puq-modal-form');
        $('#puq-field-id').val(row ? row.id : '');
        if (typeof window.puqApplyServerCaps === 'function') window.puqApplyServerCaps(row, SERVER_TYPE);
        refreshDriverDropdown(SERVER_TYPE, row ? row.driver : 'hestiacp');
        $('#puq-field-name').val(row ? row.name : '');
        $('#puq-field-hostname').val(row ? row.hostname : '');
        $('#puq-field-ip').val(row && row.ip ? row.ip : '');
        $('#puq-field-port').val(row ? row.port : 22);
        $('#puq-field-username').val(row && row.username ? row.username : 'root');
        var auth = (row && row.ssh_auth_method) ? row.ssh_auth_method : 'password';
        $('input[name=ssh_auth_method][value='+auth+']').prop('checked', true);
        $('#puq-auth-password-row').toggle(auth === 'password');
        $('#puq-auth-key-row').toggle(auth === 'key');
        $('#puq-field-ssh-password').val('');
        $('#puq-field-ssh-private-key').val('');
        $('#puq-field-ssh-key-passphrase').val('');
        $('#puq-field-pdns-api-key').val('');
        $('#puq-field-status').val(row ? row.status : 'active');
        $('#puq-field-capacity').val(row && row.capacity_max ? row.capacity_max : '');
        loadGroups(row ? row.group_id : null);
        loadTemplates(row ? row.dns_template_id : null);
        var selectedDriver = $('#puq-field-driver').val();
        renderDriverConfig(SERVER_TYPE, selectedDriver, row ? row.config_parsed : null);
        if (typeof window.puqApplyDriverVisibility === 'function') window.puqApplyDriverVisibility(selectedDriver);
        $('#puq-web-only').hide();
        $('#puq-test-btn').toggle(!!row);
        $('#puq-modal-title').text(row ? 'Edit Mail Server' : 'Add Mail Server');
        $('#puq-modal').modal('show');
    }

    $(document).ready(function(){
        loadFilterGroups();
        load();

        $('#puq-filter-group').on('change', load);

        $('#puq-field-driver').on('change', function() {
            renderDriverConfig(SERVER_TYPE, this.value, null);
            if (typeof window.puqApplyDriverVisibility === 'function') window.puqApplyDriverVisibility(this.value);
        });
        $('#puq-modal').on('change', 'input[name=ssh_auth_method]', function() {
            var v = $('input[name=ssh_auth_method]:checked').val();
            $('#puq-auth-password-row').toggle(v === 'password');
            $('#puq-auth-key-row').toggle(v === 'key');
        });

        $('#puq-add-btn').on('click', function() { openModal(null); });

        $('#puq-data-table').on('click', '.puq-edit', function() {
            var btn = this;
            var id = $(this).closest('tr').data('id');
            btnSpinner(btn);
            $.ajax({
                url: baseUrl + 'getServer&id=' + id, dataType: 'json',
                success: function(r) {
                    if (r.status === 'success') {
                        var row = r.data;
                        try { row.config_parsed = row.config ? JSON.parse(row.config) : {}; } catch(e){ row.config_parsed = {}; }
                        openModal(row);
                    } else {
                        showNotification(r.msg || 'Failed to load.', 'error');
                    }
                },
                error: function() { showNotification('Request failed.', 'error'); },
                complete: function() { btnRestore(btn, 'edit', ''); }
            });
        });

        $('#puq-modal-save').on('click', function() {
            formSubmit({
                btn: this, form: '#puq-modal-form', baseUrl: baseUrl, action: 'saveServer',
                onSuccess: function() { $('#puq-modal').modal('hide'); load(); }
            });
        });

        $('#puq-data-table').on('click', '.puq-delete', function() {
            $('#puq-delete-id').val($(this).closest('tr').data('id'));
            $('#puq-delete-modal').modal('show');
        });

        $('#puq-confirm-delete').on('click', function() {
            var btn = this;
            btnSpinner(btn, 'Deleting...');
            $.ajax({
                url: baseUrl + 'deleteServer', type: 'POST', data: { id: $('#puq-delete-id').val() }, dataType: 'json',
                success: function(r) {
                    if (r.status === 'success') { showNotification(r.msg || 'Server deleted.', 'success'); load(); }
                    else { showNotification(r.msg || 'Delete failed.', 'error'); }
                    $('#puq-delete-modal').modal('hide');
                },
                error: function() { showNotification('Request failed.', 'error'); $('#puq-delete-modal').modal('hide'); },
                complete: function() { btnRestore(btn, 'trash', 'Delete'); }
            });
        });

        $('#puq-data-table').on('click', '.puq-test', function() {
            var btn = this;
            var id = $(this).closest('tr').data('id');
            btnSpinner(btn);
            $.ajax({
                url: baseUrl + 'testServerConnection', type: 'POST', data: { id: id }, dataType: 'json',
                success: function(r) {
                    if (r.status === 'success') { showNotification('Connection OK — status refresh queued', 'success'); setTimeout(load, 1500); }
                    else showNotification('Connection FAILED: ' + (r.error || r.msg || 'unknown'), 'error');
                },
                error: function() { showNotification('Request failed.', 'error'); },
                complete: function() { btnRestore(btn, 'plug', ''); }
            });
        });

        $('#puq-data-table').on('click', '.puq-refresh', function() {
            var btn = this;
            var id = $(this).closest('tr').data('id');
            btnSpinner(btn);
            $.ajax({
                url: baseUrl + 'refreshServerStatus', type: 'POST', data: { id: id }, dataType: 'json',
                success: function(r) {
                    if (r.status === 'success') { showNotification(r.msg || 'Refresh queued', 'success'); setTimeout(load, 1500); }
                    else showNotification(r.msg || 'Refresh failed', 'error');
                },
                error: function() { showNotification('Request failed.', 'error'); },
                complete: function() { btnRestore(btn, 'sync', ''); }
            });
        });

        $('#puq-test-btn').on('click', function() {
            if (!editingId) return;
            var btn = this;
            btnSpinner(btn, 'Testing...');
            $.ajax({
                url: baseUrl + 'testServerConnection', type: 'POST', data: { id: editingId }, dataType: 'json',
                success: function(r) {
                    if (r.status === 'success') showNotification('Connection OK', 'success');
                    else showNotification('Connection FAILED: ' + (r.error || r.msg || 'unknown'), 'error');
                },
                error: function() { showNotification('Request failed.', 'error'); },
                complete: function() { btnRestore(btn, 'plug', 'Test connection'); }
            });
        });
    });
})();
</script>
{/literal}
