<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DRACS - Site Management</title>
    <link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='images/dracs.svg') }}">
    <style>
        * { box-sizing: border-box; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
        }
        button, input, select, textarea { font-family: inherit; }
        .container {
            max-width: 1400px;
            margin: 0 auto;
            background-color: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
        }
        .header-left { display: flex; align-items: center; gap: 15px; }
        .logo { height: 48px; width: auto; }
        .auth-section { display: flex; gap: 15px; align-items: center; }
        .username-display { font-size: 14px; color: #555; }
        .theme-toggle { display: flex; align-items: center; gap: 10px; margin-left: 20px; }
        .theme-toggle label { font-size: 14px; color: #555; font-weight: 500; }
        .toggle-switch { position: relative; width: 50px; height: 24px; background-color: #ccc; border-radius: 12px; cursor: pointer; transition: background-color 0.3s; }
        .toggle-switch::after { content: ''; position: absolute; width: 20px; height: 20px; border-radius: 50%; background-color: white; top: 2px; left: 2px; transition: transform 0.3s; box-shadow: 0 2px 4px rgba(0,0,0,0.2); }
        .toggle-switch.active { background-color: #007bff; }
        .toggle-switch.active::after { transform: translateX(26px); }

        h2 { margin-bottom: 16px; font-size: 1.2em; border-bottom: 2px solid #eee; padding-bottom: 8px; }
        table { width: 100%; border-collapse: collapse; }
        th { text-align: left; padding: 8px 12px; border-bottom: 2px solid #ddd; font-weight: 600; font-size: 0.9em; color: #555; }
        td { padding: 8px 12px; border-bottom: 1px solid #eee; font-size: 0.9em; }
        tr.selectable { cursor: pointer; }
        tr.selectable:hover { background: #f0f4ff; }
        tr.selected { background: #dbeafe; }
        .btn { padding: 6px 16px; border: none; border-radius: 4px; cursor: pointer; font-size: 0.9em; font-weight: 500; }
        .btn-primary { background: #1976d2; color: white; }
        .btn-primary:hover { background: #1565c0; }
        .btn-secondary { background: #e0e0e0; color: #333; }
        .btn-secondary:hover { background: #bdbdbd; }
        .btn-danger { background: #ef5350; color: white; }
        .btn-danger:hover { background: #c62828; }
        .btn:disabled { opacity: 0.5; cursor: not-allowed; }
        .actions-bar { display: flex; gap: 8px; margin-top: 16px; }
        .form-panel { margin-top: 16px; padding: 16px; border: 1px solid #e0e0e0; border-radius: 6px; background: #fafafa; }
        .form-panel h3 { margin-bottom: 12px; }
        .form-row { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 12px; }
        .form-group { display: flex; flex-direction: column; gap: 4px; }
        .form-group label { font-size: 0.85em; font-weight: 500; color: #555; }
        .form-group input, .form-group select { padding: 6px 10px; border: 1px solid #ccc; border-radius: 4px; font-size: 0.9em; }
        .notification { position: fixed; top: 16px; right: 16px; padding: 12px 20px; border-radius: 6px; color: white; z-index: 1000; animation: fadeIn 0.3s; }
        .notification.success { background: #43a047; }
        .notification.error { background: #e53935; }
        @keyframes fadeIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }
        .footer-bar { text-align: center; margin-top: 24px; }
        .logout-link { color: #1976d2; text-decoration: none; font-size: 14px; font-weight: 500; }
        .logout-link:hover { text-decoration: underline; }
        body.dark-theme .logout-link { color: #7ab8f5; }
        .primary-tag { display: inline-block; padding: 1px 6px; border-radius: 3px; background: #e8f5e9; color: #2e7d32; font-size: 0.8em; margin-left: 4px; }

        .modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 100; justify-content: center; align-items: center; }
        .modal-overlay.active { display: flex; }
        .modal-box { background: white; border-radius: 8px; padding: 24px; min-width: 360px; max-width: 500px; box-shadow: 0 8px 32px rgba(0,0,0,0.3); }
        .modal-box h3 { margin-top: 0; margin-bottom: 16px; }
        .modal-box .modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }

        .host-override-row { display: flex; gap: 8px; align-items: center; padding: 4px 0; flex-wrap: wrap; }
        .host-override-row input { width: 140px; padding: 4px 8px; font-size: 0.85em; border: 1px solid #ccc; border-radius: 4px; }
        .host-override-row .btn { padding: 4px 10px; font-size: 0.8em; }
        .btn-eye { background: none; border: 1px solid #ccc; border-radius: 4px; padding: 3px 5px; cursor: pointer; color: #666; line-height: 1; display: flex; align-items: center; flex-shrink: 0; }
        .btn-eye:hover { background: #f0f0f0; color: #222; }
        .pw-field-wrap { display: flex; gap: 4px; align-items: center; }
        .pw-field-wrap input { flex: 1; }
        .drag-handle { width: 28px; text-align: center; cursor: grab; color: #aaa; font-size: 1.1em; user-select: none; }
        .drag-handle:active { cursor: grabbing; }
        tr.dragging { opacity: 0.4; }
        tr.drag-over td { border-top: 2px solid #1976d2; }

        /* Dark Theme */
        body.dark-theme { background-color: #1a1a1a; }
        body.dark-theme .container { background-color: #2d2d2d; color: #e0e0e0; }
        body.dark-theme h1, body.dark-theme h2, body.dark-theme h3, body.dark-theme h4 { color: #e0e0e0; }
        body.dark-theme h2 { border-bottom-color: #444; }
        body.dark-theme .username-display { color: #b0b0b0; }
        body.dark-theme .theme-toggle label { color: #b0b0b0; }
        body.dark-theme th { color: #b0b0b0; border-bottom-color: #555; }
        body.dark-theme td { color: #e0e0e0; border-bottom-color: #444; }
        body.dark-theme tr.selectable:hover { background: #3a3a3a; }
        body.dark-theme tr.selected { background: #2a6ba8; }
        body.dark-theme .form-panel { background: #3a3a3a; border-color: #555; }
        body.dark-theme .form-group label { color: #b0b0b0; }
        body.dark-theme .form-group input { background-color: #4a4a4a; color: #e0e0e0; border-color: #555; }
        body.dark-theme .host-override-row input { background-color: #4a4a4a; color: #e0e0e0; border-color: #555; }
        body.dark-theme .form-panel textarea { background-color: #4a4a4a; color: #e0e0e0; border-color: #555; }
        body.dark-theme .btn-secondary { background: #555; color: #e0e0e0; }
        body.dark-theme .btn-secondary:hover { background: #666; }
        body.dark-theme .btn-eye { border-color: #555; color: #b0b0b0; }
        body.dark-theme .btn-eye:hover { background: #4a4a4a; color: #e0e0e0; }
        body.dark-theme .drag-handle { color: #666; }
        body.dark-theme tr.drag-over td { border-top-color: #2a6ba8; }
        body.dark-theme .btn-primary { background: #1e5a8e; }
        body.dark-theme .btn-primary:hover { background: #2a6ba8; }
        body.dark-theme .btn-danger { background: #c62828; }
        body.dark-theme .primary-tag { background: #1e4d2b; color: #90ee90; }
        body.dark-theme .coll-desired { background-color: #4a4a4a; color: #e0e0e0; border-color: #555; }
        body.dark-theme .form-group select { background-color: #4a4a4a; color: #e0e0e0; border-color: #555; }
        body.dark-theme .modal-overlay { background: rgba(0,0,0,0.8); }
        body.dark-theme .modal-box { background: #2d2d2d; color: #e0e0e0; }
        body.dark-theme .modal-box input { background-color: #4a4a4a; color: #e0e0e0; border-color: #555; }
        body.dark-theme .notification.success { background: #1e4d2b; }
        body.dark-theme .notification.error { background: #5c1e1e; }
        /* Config Collection table */
        .coll-settings-table { border-collapse: collapse; width: 100%; font-size: 13px; }
        .coll-settings-table thead th { border-bottom: 1px solid #ddd; padding: 4px 8px; text-align: left; }
        .coll-settings-table td { padding: 4px 8px; }
        .coll-settings-table input[type="number"] { width: 70px; }
        body.dark-theme .coll-settings-table thead th { border-bottom-color: #555; }
        body.dark-theme .coll-settings-table input[type="number"] { background-color: #4a4a4a; color: #e0e0e0; border-color: #555; border: 1px solid #555; border-radius: 3px; }
        body.dark-theme .coll-desc { color: #999; }
        /* SSL Certificate Management */
        .ssl-section { margin-top: 4px; }
        .ssl-subsection { margin-top: 10px; }
        .ssl-subsection h5 { margin: 0 0 6px; font-size: 0.9em; font-weight: 600; }
        .ssl-tools-warn { color: #dc3545; font-size: 0.82em; margin-left: 6px; }
        .ssl-fingerprint-box {
            margin-top: 6px; padding: 6px 10px; font-size: 0.8em; font-family: monospace;
            background: #f0f4ff; border: 1px solid #cce; border-radius: 4px;
        }
        body.dark-theme .ssl-fingerprint-box { background: #1a2a3a; border-color: #335; }
        .ssl-pem-area {
            width: 100%; font-family: monospace; font-size: 0.78em;
            box-sizing: border-box; resize: vertical;
        }
        .ssl-file-row { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
        .ssl-file-label { font-size: 0.83em; color: #555; }
        body.dark-theme .ssl-file-label { color: #aaa; }
        .ssl-override-panel {
            margin-top: 6px; padding: 8px 10px;
            border: 1px dashed #ccc; border-radius: 4px; background: #f9f9f9;
        }
        body.dark-theme .ssl-override-panel { background: #2a3a4a; border-color: #445; }
        .ssl-override-fp { font-size: 0.78em; font-family: monospace; color: #555; }
        body.dark-theme .ssl-override-fp { color: #aaa; }
        .schedule-row { display: flex; gap: 16px; flex-wrap: wrap; align-items: flex-end; margin-top: 8px; }
        .schedule-row .form-group select,
        .schedule-row .form-group input[type="time"] {
            padding: 4px 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 13px;
        }
        body.dark-theme .schedule-row .form-group select,
        body.dark-theme .schedule-row .form-group input[type="time"] {
            background-color: #4a4a4a; color: #e0e0e0; border-color: #555;
        }
    </style>
</head>
<body>
<script>if(localStorage.getItem('theme')==='dark')document.body.classList.add('dark-theme');</script>
    <div class="container">
        <div class="header">
            <div class="header-left">
                <img src="{{ url_for('static', filename='images/dracs.svg') }}" alt="DRACS Logo" class="logo">
                <h1 style="margin: 0; border: none; padding: 0;">DRACS Site Management</h1>
                <div class="theme-toggle">
                    <label for="theme-toggle-switch">Dark Mode</label>
                    <div id="theme-toggle-switch" class="toggle-switch" onclick="toggleTheme()"></div>
                </div>
            </div>
            <div class="auth-section">
                <span class="username-display">Logged in as <strong>{{ username }}</strong> ({{ user_role }})</span>
                <a href="/attr-catalog?site={{ from_site }}" class="logout-link" style="margin-right: 8px;" title="Attribute Catalog" aria-label="Attribute Catalog"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="1em" height="1em" fill="currentColor" style="vertical-align:-0.125em" aria-hidden="true"><path d="M0 2a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1v7.5a2.5 2.5 0 0 1-2.5 2.5h-9A2.5 2.5 0 0 1 1 12.5V5a1 1 0 0 1-1-1zm2 3v7.5A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5V5zm13-3H1v2h14zM5 7.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5"/></svg></a>
                <a href="/?site={{ from_site }}" class="logout-link" title="Inventory" aria-label="Inventory"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="1em" height="1em" fill="currentColor" style="vertical-align:-0.125em" aria-hidden="true"><path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5m0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5m0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5"/></svg></a>
            </div>
        </div>

        <h2>Sites</h2>
        <table>
            <thead>
                <tr>
                    <th>Site Name</th>
                    <th>Hosts</th>
                    <th>Primary</th>
                    <th style="width:28px;"></th>
                </tr>
            </thead>
            <tbody id="site-table-body"></tbody>
        </table>
        <div class="actions-bar">
            <button class="btn btn-primary" onclick="showAddModal()">Add</button>
            <button class="btn btn-secondary" id="btn-rename" disabled onclick="showRenameModal()">Rename</button>
            <button class="btn btn-secondary" id="btn-manage" disabled onclick="showManagePanel()">Manage</button>
            <button class="btn btn-secondary" id="btn-set-primary" disabled onclick="setAsPrimary()">Set as Primary</button>
            <button class="btn btn-danger" id="btn-remove" disabled onclick="showRemoveModal()">Remove</button>
        </div>

        <div id="manage-panel" class="form-panel" style="display:none;">
            <h3>Manage Site: <span id="manage-site-name"></span></h3>
            <h4 style="margin: 8px 0 4px;">Default Credentials</h4>
            <div class="form-row">
                <div class="form-group">
                    <label>Username</label>
                    <input type="text" id="manage-username" autocomplete="off">
                </div>
                <div class="form-group">
                    <label>Password</label>
                    <div class="pw-field-wrap">
                        <input type="password" id="manage-password" autocomplete="off">
                        <button type="button" class="btn-eye" id="manage-password-eye"
                                title="Show/hide password"
                                onclick="togglePasswordVisibility('manage-password', this)">
                            <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
                        </button>
                    </div>
                </div>
                <div class="form-group">
                    <label>VNC Port</label>
                    <input type="text" id="manage-vnc-port" autocomplete="off">
                </div>
                <div class="form-group">
                    <label>VNC Password</label>
                    <div class="pw-field-wrap">
                        <input type="password" id="manage-vnc-password" autocomplete="off">
                        <button type="button" class="btn-eye" id="manage-vnc-password-eye"
                                title="Show/hide VNC password"
                                onclick="togglePasswordVisibility('manage-vnc-password', this)">
                            <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
                        </button>
                    </div>
                </div>
                <div class="form-group">
                    <label>Conserver Password</label>
                    <div class="pw-field-wrap">
                        <input type="password" id="manage-conserver-password" autocomplete="off">
                        <button type="button" class="btn-eye" id="manage-conserver-password-eye"
                                title="Show/hide Conserver password"
                                onclick="togglePasswordVisibility('manage-conserver-password', this)">
                            <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
                        </button>
                    </div>
                </div>
            </div>
            <h4 style="margin: 16px 0 4px;">SSL Certificate Management</h4>
            <div class="ssl-section">
                <div>
                    <label style="display:inline-flex;align-items:center;gap:6px;">
                        <input type="checkbox" id="ssl-enabled" onchange="updateSslSectionState()">
                        Enable SSL Certificate Management (Requires Dell racadm tools)
                    </label>
                    <span id="ssl-tools-status" class="ssl-tools-warn"></span>
                </div>
                <div id="ssl-cert-section" style="margin-top:10px;display:none;">
                    <div class="ssl-subsection">
                        <h5>SSL Certificate (PEM)</h5>
                        <div class="ssl-file-row">
                            <button class="btn btn-secondary" onclick="document.getElementById('ssl-cert-file').click()">Choose File&hellip;</button>
                            <input type="file" id="ssl-cert-file" accept=".pem,.crt,.cer" style="display:none;"
                                   onchange="sslFileToArea(this,'ssl-cert-pem')">
                            <span class="ssl-file-label">or paste PEM below</span>
                        </div>
                        <textarea id="ssl-cert-pem" class="ssl-pem-area" rows="5"
                                  placeholder="-----BEGIN CERTIFICATE-----&#10;...&#10;-----END CERTIFICATE-----"></textarea>
                        <div id="ssl-cert-fp" class="ssl-fingerprint-box" style="display:none;"></div>
                    </div>
                    <div class="ssl-subsection">
                        <h5>SSL Private Key (PEM)</h5>
                        <div class="ssl-file-row">
                            <button class="btn btn-secondary" onclick="document.getElementById('ssl-key-file').click()">Choose File&hellip;</button>
                            <input type="file" id="ssl-key-file" accept=".pem,.key" style="display:none;"
                                   onchange="sslFileToArea(this,'ssl-key-pem')">
                            <span class="ssl-file-label">or paste PEM below</span>
                        </div>
                        <textarea id="ssl-key-pem" class="ssl-pem-area" rows="5"
                                  placeholder="-----BEGIN PRIVATE KEY-----&#10;...&#10;-----END PRIVATE KEY-----"></textarea>
                    </div>
                </div>
                <div style="margin-top:8px;">
                    <button class="btn btn-secondary" onclick="saveSslConfig()">Save SSL Settings</button>
                    <button class="btn btn-primary" id="ssl-sweep-btn" onclick="triggerSslSweep()"
                            style="display:none;margin-left:8px;">Run Now</button>
                </div>
            </div>

            <h4 style="margin: 16px 0 4px;">Host-Specific Overrides</h4>
            <div id="host-overrides-list"></div>
            <div style="margin-top: 8px;">
                <button class="btn btn-secondary" onclick="addHostOverrideRow()">+ Add Host Override</button>
            </div>

            <h4 style="margin: 16px 0 4px;">SSL Certificate Schedule</h4>
            <div id="ssl-schedule-section" class="ssl-section">
                <p style="font-size:0.85em;color:#888;margin:0 0 6px;">
                    Schedule automatic SSL certificate updates. Only enabled when SSL Certificate Management is active and a certificate/key pair has been uploaded.
                </p>
                <label style="display:inline-flex;align-items:center;gap:6px;">
                    <input type="checkbox" id="ssl-schedule-enabled">
                    Enable SSL Certificate Schedule
                </label>
                <div class="schedule-row">
                    <div class="form-group">
                        <label>Frequency</label>
                        <select id="ssl-schedule-frequency">
                            <option value="daily">Daily</option>
                            <option value="weekly">Weekly</option>
                            <option value="biweekly">Bi-Weekly</option>
                            <option value="monthly">Monthly</option>
                            <option value="quarterly">Quarterly</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label>Time of Day</label>
                        <input type="time" id="ssl-schedule-time" value="02:00">
                    </div>
                </div>
                <div style="margin-top:8px;">
                    <button class="btn btn-secondary" onclick="saveSslConfig()">Save SSL Schedule</button>
                </div>
            </div>

            <h4 style="margin: 16px 0 4px;">DNS Domains</h4>
            <p style="font-size: 0.85em; color: #888; margin: 0 0 6px;">Allowed DNS domains for host discovery. One per line. Leave blank to allow all.</p>
            <textarea id="manage-allowed-domains" rows="4"
                style="width: 100%; font-family: monospace; box-sizing: border-box;"></textarea>
            <h4 style="margin: 16px 0 4px;">QUADS</h4>
            <div class="form-row">
                <div class="form-group">
                    <label>
                        <input type="checkbox" id="manage-quads-enabled" onchange="updateQuadsUrlState()">
                        Enable QUADS host filtering for no-role users
                    </label>
                </div>
            </div>
            <div class="form-row" style="align-items: flex-end; gap: 8px;">
                <div class="form-group" style="flex: 1;">
                    <label>QUADS API URL</label>
                    <input type="text" id="manage-quads-url" autocomplete="off"
                           placeholder="http://quads.example.com" disabled>
                </div>
                <div class="form-group">
                    <button class="btn btn-secondary" onclick="verifyQuads()" id="quads-verify-btn" disabled>Verify</button>
                </div>
            </div>
            <h4 style="margin: 16px 0 4px;">Config Collection</h4>
            <p class="coll-desc" style="font-size: 0.85em; margin: 0 0 8px;">Enable per-attribute iDRAC data collection and set refresh interval in hours.</p>
            <table class="coll-settings-table">
                <thead>
                    <tr>
                        <th>Attribute</th>
                        <th>Enabled</th>
                        <th>Interval (hours)</th>
                        <th>Desired Value</th>
                    </tr>
                </thead>
                <tbody id="collection-settings-tbody">
                    <tr><td colspan="4" style="color:#888; text-align:center; padding:8px;">Loading…</td></tr>
                </tbody>
            </table>
            <div style="margin-top: 8px;">
                <button class="btn btn-secondary" onclick="saveCollectionSettings()">Save Collection Settings</button>
            </div>
            <div style="margin-top: 16px; display: flex; gap: 8px;">
                <button class="btn btn-primary" onclick="saveManage()">Save</button>
                <button class="btn btn-secondary" onclick="hideManagePanel()">Cancel</button>
            </div>
        </div>

        <div class="footer-bar">
            <button class="btn btn-secondary" id="close-btn">Close</button>
        </div>
    </div>

    <!-- Add Site Modal -->
    <div id="add-modal" class="modal-overlay">
        <div class="modal-box">
            <h3>Add Site</h3>
            <div class="form-group">
                <label>Site Name (alphanumeric and underscores only)</label>
                <input type="text" id="add-site-name" style="width:100%; margin-top:4px;">
            </div>
            <div class="modal-actions">
                <button class="btn btn-primary" onclick="submitAdd()">Add</button>
                <button class="btn btn-secondary" onclick="closeModal('add-modal')">Cancel</button>
            </div>
        </div>
    </div>

    <!-- Rename Site Modal -->
    <div id="rename-modal" class="modal-overlay">
        <div class="modal-box">
            <h3>Rename Site: <span id="rename-current-name"></span></h3>
            <div class="form-group">
                <label>New Name</label>
                <input type="text" id="rename-new-name" style="width:100%; margin-top:4px;">
            </div>
            <div class="modal-actions">
                <button class="btn btn-primary" onclick="submitRename()">Rename</button>
                <button class="btn btn-secondary" onclick="closeModal('rename-modal')">Cancel</button>
            </div>
        </div>
    </div>

    <!-- Remove Site Modal -->
    <div id="remove-modal" class="modal-overlay">
        <div class="modal-box">
            <h3>Remove Site</h3>
            <p>Are you sure you want to remove <strong id="remove-site-name"></strong>?</p>
            <p style="font-size:0.85em; color:#999; margin-top:8px;">This will also remove all credential settings for this site.</p>
            <div class="modal-actions">
                <button class="btn btn-danger" onclick="submitRemove()">Remove</button>
                <button class="btn btn-secondary" onclick="closeModal('remove-modal')">Cancel</button>
            </div>
        </div>
    </div>

    <script>
        const fromSite = '{{ from_site|default("", true) }}';
        let sites = [];
        let selectedSite = null;
        let _attrCatalog = [];

        function toggleTheme() {
            const body = document.body;
            const ts = document.getElementById('theme-toggle-switch');
            if (body.classList.contains('dark-theme')) {
                body.classList.remove('dark-theme');
                ts.classList.remove('active');
                localStorage.setItem('theme', 'light');
            } else {
                body.classList.add('dark-theme');
                ts.classList.add('active');
                localStorage.setItem('theme', 'dark');
            }
        }
        (function() {
            if (localStorage.getItem('theme') === 'dark') {
                document.body.classList.add('dark-theme');
                const ts = document.getElementById('theme-toggle-switch');
                if (ts) ts.classList.add('active');
            }
        })();

        document.getElementById('close-btn').onclick = function() {
            let url = '/';
            if (fromSite) url += '?site=' + encodeURIComponent(fromSite);
            window.location.href = url;
        };

        function showNotification(msg, type) {
            const el = document.createElement('div');
            el.className = 'notification ' + type;
            el.textContent = msg;
            document.body.appendChild(el);
            setTimeout(() => el.remove(), 3000);
        }

        function openModal(id) { document.getElementById(id).classList.add('active'); }
        function closeModal(id) { document.getElementById(id).classList.remove('active'); }

        function selectSite(name) {
            selectedSite = sites.find(s => s.name === name) || null;
            document.querySelectorAll('#site-table-body tr').forEach(r => {
                r.classList.toggle('selected', r.dataset.name === name);
            });
            const hasSel = !!selectedSite;
            const canRemove = hasSel && !selectedSite.is_primary && selectedSite.host_count === 0;
            const canSetPrimary = hasSel && !selectedSite.is_primary;
            document.getElementById('btn-rename').disabled = !hasSel;
            document.getElementById('btn-manage').disabled = !hasSel;
            document.getElementById('btn-remove').disabled = !canRemove;
            const spBtn = document.getElementById('btn-set-primary');
            spBtn.disabled = !canSetPrimary;
            spBtn.className = 'btn ' + (canSetPrimary ? 'btn-primary' : 'btn-secondary');
            hideManagePanel();
        }

        let draggedRow = null;

        function onDragStart(e) {
            draggedRow = this;
            e.dataTransfer.effectAllowed = 'move';
            e.dataTransfer.setData('text/plain', this.dataset.name);
            setTimeout(() => this.classList.add('dragging'), 0);
        }
        function onDragOver(e) {
            e.preventDefault();
            e.dataTransfer.dropEffect = 'move';
            if (this !== draggedRow) this.classList.add('drag-over');
        }
        function onDragLeave() { this.classList.remove('drag-over'); }
        function onDrop(e) {
            e.preventDefault();
            this.classList.remove('drag-over');
            if (this === draggedRow) return;
            const tbody = document.getElementById('site-table-body');
            const rows = [...tbody.querySelectorAll('tr')];
            const draggedIdx = rows.indexOf(draggedRow);
            const targetIdx = rows.indexOf(this);
            tbody.insertBefore(draggedRow, draggedIdx < targetIdx ? this.nextSibling : this);
            saveOrder();
        }
        function onDragEnd() {
            this.classList.remove('dragging');
            document.querySelectorAll('#site-table-body tr').forEach(r => r.classList.remove('drag-over'));
            draggedRow = null;
        }

        async function saveOrder() {
            const tbody = document.getElementById('site-table-body');
            const orderedIds = [...tbody.querySelectorAll('tr')]
                .map(r => { const s = sites.find(x => x.name === r.dataset.name); return s ? s.id : null; })
                .filter(id => id !== null);
            const resp = await fetch('/api/sites/reorder', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({site_ids: orderedIds})
            });
            const data = await resp.json();
            if (!data.success) {
                showNotification('Failed to save order', 'error');
                loadSites();
            } else {
                // keep in-memory array in sync with new display order
                const nameOrder = [...document.getElementById('site-table-body').querySelectorAll('tr')].map(r => r.dataset.name);
                sites = nameOrder.map(n => sites.find(s => s.name === n)).filter(Boolean);
            }
        }

        async function loadSites() {
            const resp = await fetch('/api/sites');
            const data = await resp.json();
            if (!data.success) return;
            sites = data.sites;
            const tbody = document.getElementById('site-table-body');
            tbody.innerHTML = '';
            sites.forEach(s => {
                const tr = document.createElement('tr');
                tr.className = 'selectable';
                tr.dataset.name = s.name;
                tr.draggable = true;
                tr.addEventListener('dragstart', onDragStart);
                tr.addEventListener('dragover', onDragOver);
                tr.addEventListener('dragleave', onDragLeave);
                tr.addEventListener('drop', onDrop);
                tr.addEventListener('dragend', onDragEnd);
                tr.onclick = () => selectSite(s.name);
                const primaryBadge = s.is_primary ? '<span class="primary-tag">Primary</span>' : '';
                tr.innerHTML = `
                    <td>${s.name} ${primaryBadge}</td>
                    <td>${s.host_count}</td>
                    <td>${s.is_primary ? 'Yes' : 'No'}</td>
                    <td class="drag-handle" title="Drag to reorder">⠿</td>
                `;
                tbody.appendChild(tr);
            });
            selectedSite = null;
            document.getElementById('btn-rename').disabled = true;
            document.getElementById('btn-manage').disabled = true;
            document.getElementById('btn-set-primary').disabled = true;
            document.getElementById('btn-set-primary').className = 'btn btn-secondary';
            document.getElementById('btn-remove').disabled = true;
        }

        // Add
        function showAddModal() {
            document.getElementById('add-site-name').value = '';
            openModal('add-modal');
            document.getElementById('add-site-name').focus();
        }
        async function submitAdd() {
            const name = document.getElementById('add-site-name').value.trim();
            if (!name) { showNotification('Site name required', 'error'); return; }
            const resp = await fetch('/api/sites', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({name: name})
            });
            const data = await resp.json();
            if (data.success) {
                closeModal('add-modal');
                loadSites();
                showNotification('Site created: ' + name, 'success');
            } else {
                showNotification(data.message, 'error');
            }
        }

        // Rename
        function showRenameModal() {
            if (!selectedSite) return;
            document.getElementById('rename-current-name').textContent = selectedSite.name;
            document.getElementById('rename-new-name').value = selectedSite.name;
            openModal('rename-modal');
            document.getElementById('rename-new-name').focus();
            document.getElementById('rename-new-name').select();
        }
        async function submitRename() {
            if (!selectedSite) return;
            const newName = document.getElementById('rename-new-name').value.trim();
            if (!newName || newName === selectedSite.name) { closeModal('rename-modal'); return; }
            const resp = await fetch('/api/sites/' + encodeURIComponent(selectedSite.name), {
                method: 'PATCH',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({name: newName})
            });
            const data = await resp.json();
            if (data.success) {
                closeModal('rename-modal');
                loadSites();
                showNotification('Site renamed to ' + newName, 'success');
            } else {
                showNotification(data.message, 'error');
            }
        }

        // Remove
        function showRemoveModal() {
            if (!selectedSite || selectedSite.is_primary) return;
            document.getElementById('remove-site-name').textContent = selectedSite.name;
            openModal('remove-modal');
        }
        async function submitRemove() {
            if (!selectedSite) return;
            const resp = await fetch('/api/sites/' + encodeURIComponent(selectedSite.name), {method: 'DELETE'});
            const data = await resp.json();
            if (data.success) {
                closeModal('remove-modal');
                loadSites();
                showNotification('Site removed', 'success');
            } else {
                showNotification(data.message, 'error');
            }
        }

        // Set as Primary
        async function setAsPrimary() {
            if (!selectedSite || selectedSite.is_primary) return;
            const resp = await fetch('/api/sites/' + encodeURIComponent(selectedSite.name) + '/set-primary', {
                method: 'PUT'
            });
            const data = await resp.json();
            if (data.success) {
                loadSites();
                showNotification(data.message, 'success');
            } else {
                showNotification(data.message, 'error');
            }
        }

        // Manage
        const EYE_OPEN = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>';
        const EYE_SLASH = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>';

        function togglePasswordVisibility(inputId, btn) {
            const input = document.getElementById(inputId);
            const isHidden = input.type === 'password';
            input.type = isHidden ? 'text' : 'password';
            btn.innerHTML = isHidden ? EYE_SLASH : EYE_OPEN;
        }

        function hideManagePanel() { document.getElementById('manage-panel').style.display = 'none'; }

        async function showManagePanel() {
            if (!selectedSite) return;
            document.getElementById('manage-site-name').textContent = selectedSite.name;

            // Load credentials config and SSL config concurrently
            const [credsResp, sslOverrides] = await Promise.all([
                fetch('/api/sites/' + encodeURIComponent(selectedSite.name) + '/config').then(r => r.json()),
                loadSslConfig(selectedSite.name),
            ]);

            if (!credsResp.success) { showNotification(credsResp.message || 'Failed to load config', 'error'); return; }

            const cfg = credsResp.config;
            document.getElementById('manage-username').value = cfg.defaults.username || '';
            const pwInput = document.getElementById('manage-password');
            pwInput.value = cfg.defaults.password || '';
            pwInput.type = 'password';
            document.getElementById('manage-password-eye').innerHTML = EYE_OPEN;
            document.getElementById('manage-vnc-port').value = cfg.defaults.vnc_port || '5901';
            const vncPwInput = document.getElementById('manage-vnc-password');
            vncPwInput.value = cfg.defaults.vnc_password || '';
            vncPwInput.type = 'password';
            document.getElementById('manage-vnc-password-eye').innerHTML = EYE_OPEN;
            const conserverPwInput = document.getElementById('manage-conserver-password');
            conserverPwInput.value = cfg.defaults.conserver_password || '';
            conserverPwInput.type = 'password';
            document.getElementById('manage-conserver-password-eye').innerHTML = EYE_OPEN;
            document.getElementById('manage-quads-enabled').checked = cfg.defaults.quads_enabled === 'true';
            document.getElementById('manage-quads-url').value = cfg.defaults.quads_url || '';
            updateQuadsUrlState();

            const list = document.getElementById('host-overrides-list');
            list.innerHTML = '';
            for (const [hostname, overrides] of Object.entries(cfg.hosts || {})) {
                addHostOverrideRow(hostname, overrides, sslOverrides[hostname] || {});
            }

            document.getElementById('manage-allowed-domains').value = cfg.allowed_domains || '';

            await loadCollectionSettings(selectedSite.name);

            document.getElementById('manage-panel').style.display = 'block';
        }

        function addHostOverrideRow(hostname, overrides, sslData) {
            hostname = hostname || '';
            overrides = overrides || {};
            sslData = sslData || {};
            const list = document.getElementById('host-overrides-list');
            const row = document.createElement('div');
            row.className = 'host-override-row';
            const hasCert = sslData.has_cert && sslData.has_key;
            const fpText = hasCert
                ? `<span class="ssl-override-fp">Cert: ${sslData.cert_fingerprint || '(no fingerprint)'}</span>`
                : '<span class="ssl-override-fp" style="color:#999;">No SSL cert override</span>';
            row.innerHTML = `
                <input type="text" placeholder="hostname" value="${hostname}" class="ho-hostname">
                <input type="text" placeholder="username" value="${overrides.username || ''}" class="ho-username">
                <input type="text" placeholder="password" value="${overrides.password || ''}" class="ho-password">
                <input type="text" placeholder="vnc_port" value="${overrides.vnc_port || ''}" class="ho-vnc-port" style="width:80px;">
                <input type="text" placeholder="vnc_password" value="${overrides.vnc_password || ''}" class="ho-vnc-password">
                <button class="btn btn-secondary" onclick="toggleHostSslPanel(this)">SSL</button>
                <button class="btn btn-danger" onclick="this.parentElement.remove()">Remove</button>
                <div class="ssl-override-panel" style="display:none;width:100%;margin-top:6px;">
                    <div style="margin-bottom:6px;">${fpText}</div>
                    <div class="ssl-subsection">
                        <h5>Certificate PEM</h5>
                        <div class="ssl-file-row">
                            <button class="btn btn-secondary" style="font-size:0.82em;" onclick="this.nextElementSibling.click()">Choose File&hellip;</button>
                            <input type="file" accept=".pem,.crt,.cer" style="display:none;" onchange="sslFileToArea(this, null, this.closest('.ssl-override-panel').querySelector('.ho-ssl-cert'))">
                        </div>
                        <textarea class="ho-ssl-cert ssl-pem-area" rows="4" placeholder="-----BEGIN CERTIFICATE-----"></textarea>
                    </div>
                    <div class="ssl-subsection">
                        <h5>Private Key PEM</h5>
                        <div class="ssl-file-row">
                            <button class="btn btn-secondary" style="font-size:0.82em;" onclick="this.nextElementSibling.click()">Choose File&hellip;</button>
                            <input type="file" accept=".pem,.key" style="display:none;" onchange="sslFileToArea(this, null, this.closest('.ssl-override-panel').querySelector('.ho-ssl-key'))">
                        </div>
                        <textarea class="ho-ssl-key ssl-pem-area" rows="4" placeholder="-----BEGIN PRIVATE KEY-----"></textarea>
                    </div>
                    <div style="display:flex;gap:8px;margin-top:8px;">
                        <button class="btn btn-primary" style="font-size:0.85em;" onclick="saveHostSslOverride(this)">Save SSL Override</button>
                        ${hasCert ? `<button class="btn btn-danger" style="font-size:0.85em;" onclick="deleteHostSslOverride(this,'${hostname}')">Remove SSL</button>` : ''}
                    </div>
                </div>
            `;
            list.appendChild(row);
        }

        function toggleHostSslPanel(btn) {
            const panel = btn.parentElement.querySelector('.ssl-override-panel');
            panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
        }

        function sslFileToArea(input, textareaId, textareaEl) {
            const file = input.files && input.files[0];
            if (!file) return;
            const reader = new FileReader();
            reader.onload = e => {
                const ta = textareaEl || document.getElementById(textareaId);
                if (ta) ta.value = e.target.result;
            };
            reader.readAsText(file);
            input.value = '';
        }

        async function saveHostSslOverride(btn) {
            const row = btn.closest('.host-override-row');
            const hostname = row.querySelector('.ho-hostname').value.trim();
            if (!hostname || !selectedSite) return;
            const certPem = row.querySelector('.ho-ssl-cert').value.trim();
            const keyPem = row.querySelector('.ho-ssl-key').value.trim();
            if (!certPem || !keyPem) {
                showNotification('Both certificate and key PEM are required', 'error'); return;
            }
            const resp = await fetch(
                `/api/sites/${encodeURIComponent(selectedSite.name)}/ssl-overrides/${encodeURIComponent(hostname)}`,
                { method: 'PUT', headers: {'Content-Type': 'application/json'},
                  body: JSON.stringify({cert_pem: certPem, key_pem: keyPem}) }
            );
            const data = await resp.json();
            if (data.success) {
                row.querySelector('.ho-ssl-cert').value = '';
                row.querySelector('.ho-ssl-key').value = '';
                const fpEl = row.querySelector('.ssl-override-fp');
                if (fpEl) fpEl.textContent = `Cert: ${data.cert_fingerprint || ''}`;
                showNotification('SSL override saved', 'success');
            } else {
                showNotification(data.message || 'Failed to save SSL override', 'error');
            }
        }

        async function deleteHostSslOverride(btn, hostname) {
            if (!selectedSite || !hostname) return;
            const resp = await fetch(
                `/api/sites/${encodeURIComponent(selectedSite.name)}/ssl-overrides/${encodeURIComponent(hostname)}`,
                { method: 'DELETE' }
            );
            const data = await resp.json();
            if (data.success) {
                const row = btn.closest('.host-override-row');
                const fpEl = row.querySelector('.ssl-override-fp');
                if (fpEl) { fpEl.textContent = 'No SSL cert override'; fpEl.style.color = '#999'; }
                btn.remove();
                showNotification('SSL override removed', 'success');
            } else {
                showNotification(data.message || 'Failed to remove override', 'error');
            }
        }

        function updateSslSectionState() {
            const enabled = document.getElementById('ssl-enabled').checked;
            document.getElementById('ssl-cert-section').style.display = enabled ? '' : 'none';
        }

        async function loadSslConfig(siteName) {
            const [toolsResp, cfgResp, ovResp] = await Promise.all([
                fetch('/api/system/ssl-tools'),
                fetch('/api/sites/' + encodeURIComponent(siteName) + '/ssl-config'),
                fetch('/api/sites/' + encodeURIComponent(siteName) + '/ssl-overrides'),
            ]);
            const toolsData = await toolsResp.json();
            const cfgData = await cfgResp.json();
            const ovData = await ovResp.json();

            const available = toolsData.available;
            const statusEl = document.getElementById('ssl-tools-status');
            const enabledCb = document.getElementById('ssl-enabled');

            if (!available) {
                statusEl.textContent = ` — ${toolsData.path} not found on system`;
                enabledCb.disabled = true;
                enabledCb.checked = false;
            } else {
                statusEl.textContent = '';
                enabledCb.disabled = false;
            }

            if (cfgData.success) {
                enabledCb.checked = cfgData.enabled && available;
                updateSslSectionState();

                const sweepBtn = document.getElementById('ssl-sweep-btn');
                sweepBtn.style.display = (cfgData.enabled && cfgData.has_cert) ? '' : 'none';

                const fpBox = document.getElementById('ssl-cert-fp');
                if (cfgData.cert_fingerprint) {
                    fpBox.style.display = '';
                    fpBox.innerHTML = `<strong>SHA-256:</strong> ${cfgData.cert_fingerprint}<br>` +
                        `<strong>Expires:</strong> ${cfgData.cert_expiry || '—'}`;
                } else {
                    fpBox.style.display = 'none';
                }

                document.getElementById('ssl-schedule-enabled').checked = cfgData.schedule_enabled;
                document.getElementById('ssl-schedule-frequency').value = cfgData.schedule_frequency || 'weekly';
                document.getElementById('ssl-schedule-time').value = cfgData.schedule_time || '02:00';
            }

            return ovData.success ? (ovData.overrides || {}) : {};
        }

        async function saveSslConfig() {
            if (!selectedSite) return;
            const enabled = document.getElementById('ssl-enabled').checked;
            const certPem = document.getElementById('ssl-cert-pem').value.trim();
            const keyPem = document.getElementById('ssl-key-pem').value.trim();
            const scheduleEnabled = document.getElementById('ssl-schedule-enabled').checked;
            const scheduleFrequency = document.getElementById('ssl-schedule-frequency').value;
            const scheduleTime = document.getElementById('ssl-schedule-time').value;

            const payload = {
                enabled, schedule_enabled: scheduleEnabled,
                schedule_frequency: scheduleFrequency, schedule_time: scheduleTime,
            };
            if (certPem || keyPem) { payload.cert_pem = certPem; payload.key_pem = keyPem; }

            const resp = await fetch(
                '/api/sites/' + encodeURIComponent(selectedSite.name) + '/ssl-config',
                { method: 'PUT', headers: {'Content-Type': 'application/json'},
                  body: JSON.stringify(payload) }
            );
            const data = await resp.json();
            if (data.success) {
                document.getElementById('ssl-cert-pem').value = '';
                document.getElementById('ssl-key-pem').value = '';
                if (data.cert_fingerprint) {
                    const fpBox = document.getElementById('ssl-cert-fp');
                    fpBox.style.display = '';
                    fpBox.innerHTML = `<strong>SHA-256:</strong> ${data.cert_fingerprint}<br>` +
                        `<strong>Expires:</strong> ${data.cert_expiry || '—'}`;
                }
                const sweepBtn = document.getElementById('ssl-sweep-btn');
                if (data.cert_fingerprint || enabled) sweepBtn.style.display = '';
                showNotification('SSL settings saved', 'success');
            } else {
                showNotification(data.message || 'Failed to save SSL settings', 'error');
            }
        }

        async function triggerSslSweep() {
            if (!selectedSite) return;
            const resp = await fetch(
                '/api/sites/' + encodeURIComponent(selectedSite.name) + '/ssl-sweep',
                { method: 'POST' }
            );
            const data = await resp.json();
            showNotification(
                data.success ? `SSL sweep queued: ${data.queued} host(s)` : (data.message || 'Failed'),
                data.success ? 'success' : 'error'
            );
        }

        function updateQuadsUrlState() {
            const enabled = document.getElementById('manage-quads-enabled').checked;
            document.getElementById('manage-quads-url').disabled = !enabled;
            document.getElementById('quads-verify-btn').disabled = !enabled;
        }

        async function verifyQuads() {
            const url = document.getElementById('manage-quads-url').value.trim();
            if (!url) { showNotification('Enter a QUADS URL first', 'error'); return; }
            const resp = await fetch('/api/sites/' + encodeURIComponent(selectedSite.name) + '/quads-verify', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({quads_url: url})
            });
            const data = await resp.json();
            showNotification(data.message, data.success ? 'success' : 'error');
        }

        async function saveManage() {
            if (!selectedSite) return;
            const defaults = {
                username: document.getElementById('manage-username').value,
                password: document.getElementById('manage-password').value,
                vnc_port: document.getElementById('manage-vnc-port').value,
                vnc_password: document.getElementById('manage-vnc-password').value,
                conserver_password: document.getElementById('manage-conserver-password').value,
                quads_enabled: document.getElementById('manage-quads-enabled').checked ? 'true' : 'false',
                quads_url: document.getElementById('manage-quads-url').value,
            };

            const hosts = {};
            document.querySelectorAll('#host-overrides-list .host-override-row').forEach(row => {
                const hn = row.querySelector('.ho-hostname').value.trim();
                if (!hn) return;
                const entry = {};
                const u = row.querySelector('.ho-username').value.trim();
                const p = row.querySelector('.ho-password').value.trim();
                const vp = row.querySelector('.ho-vnc-port').value.trim();
                const vpw = row.querySelector('.ho-vnc-password').value.trim();
                if (u) entry.username = u;
                if (p) entry.password = p;
                if (vp) entry.vnc_port = vp;
                if (vpw) entry.vnc_password = vpw;
                if (Object.keys(entry).length > 0) hosts[hn] = entry;
            });

            const allowed_domains = document.getElementById('manage-allowed-domains').value;

            const resp = await fetch('/api/sites/' + encodeURIComponent(selectedSite.name) + '/config', {
                method: 'PUT',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({defaults: defaults, hosts: hosts, allowed_domains: allowed_domains})
            });
            const data = await resp.json();
            if (data.success) {
                hideManagePanel();
                showNotification('Site config saved', 'success');
            } else {
                showNotification(data.message, 'error');
            }
        }

        const _SSL_ATTR_NAMES = new Set(['ssl_self_signed', 'ssl_valid_name', 'ssl_expiry', 'ssl_fingerprint']);

        function _buildCollRow(entry, rowKey, s) {
            // Determine desired-value cell content
            let desiredCell;
            if (rowKey === 'idrac_hostname') {
                desiredCell = '<td><span style="color:#666; font-style:italic; font-size:0.85em;">Matches FQDN (auto)</span></td>';
            } else if (rowKey === 'ssl') {
                desiredCell = '<td></td>';
            } else if (entry && entry.is_writable && entry.choices && entry.choices.length > 0) {
                let opts = '<option value="">— Any —</option>';
                for (const ch of entry.choices) {
                    const sel = s && s.desired_choice_id === ch.id ? ' selected' : '';
                    opts += `<option value="${ch.id}"${sel}>${ch.label}</option>`;
                }
                desiredCell = `<td><select class="coll-desired">${opts}</select></td>`;
            } else {
                desiredCell = '<td></td>';
            }
            const labelText = entry ? entry.label : rowKey;
            const enabled = s && s.enabled ? ' checked' : '';
            const hours = s ? (s.hours || 24) : 24;
            return `<tr data-attr="${rowKey}">
                <td>${labelText}</td>
                <td><input type="checkbox" class="coll-enabled"${enabled}></td>
                <td><input type="number" class="coll-hours" min="1" max="8760" value="${hours}"></td>
                ${desiredCell}
            </tr>`;
        }

        async function loadCollectionSettings(siteName) {
            const resp = await fetch('/api/sites/' + encodeURIComponent(siteName) + '/config-collection');
            const data = await resp.json();
            if (!data.success) return;
            _attrCatalog = data.catalog || [];

            const tbody = document.getElementById('collection-settings-tbody');
            let html = '';
            let sslRowAdded = false;

            for (const entry of _attrCatalog) {
                const isSSL = _SSL_ATTR_NAMES.has(entry.name);
                if (isSSL) {
                    if (!sslRowAdded) {
                        // Aggregate all SSL attrs under a single row keyed 'ssl'
                        // Use ssl_self_signed's site_settings for enabled/hours
                        html += _buildCollRow(entry, 'ssl', entry.site_settings);
                        sslRowAdded = true;
                    }
                    continue;
                }
                html += _buildCollRow(entry, entry.name, entry.site_settings);
            }

            tbody.innerHTML = html || '<tr><td colspan="4" style="color:#888; text-align:center;">No attributes in catalog.</td></tr>';
        }

        async function saveCollectionSettings() {
            if (!selectedSite) return;
            const _SSL_ATTRS = [..._SSL_ATTR_NAMES];
            const rowSettings = {};
            document.querySelectorAll('#collection-settings-tbody tr[data-attr]').forEach(row => {
                const sel = row.querySelector('.coll-desired');
                rowSettings[row.dataset.attr] = {
                    enabled: row.querySelector('.coll-enabled').checked,
                    hours: parseInt(row.querySelector('.coll-hours').value) || 24,
                    desired_choice_id: sel && sel.value ? parseInt(sel.value) : null,
                };
            });
            const payload = _attrCatalog.map(entry => {
                const key = _SSL_ATTRS.includes(entry.name) ? 'ssl' : entry.name;
                const s = rowSettings[key] || {enabled: false, hours: 24, desired_choice_id: null};
                // Single-choice attrs (e.g. idrac_hostname) have an implicit desired value;
                // auto-set it so the push dialog is not greyed out.
                const desiredId = s.desired_choice_id !== null ? s.desired_choice_id
                    : (entry.choices && entry.choices.length === 1 ? entry.choices[0].id : null);
                return {
                    attr_def_id: entry.id,
                    enabled: s.enabled,
                    hours: s.hours,
                    desired_choice_id: desiredId,
                };
            });
            const resp = await fetch('/api/sites/' + encodeURIComponent(selectedSite.name) + '/config-collection', {
                method: 'PUT',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify(payload)
            });
            const data = await resp.json();
            if (data.success) {
                showNotification('Collection settings saved', 'success');
            } else {
                showNotification(data.message || 'Failed to save collection settings', 'error');
            }
        }

        loadSites();
    </script>
</body>
</html>
