// Device groups: members (MAC ids) + Wi‑Fi driver defaults; persisted via /groups.
// Without ``profile_id``, a group is shared across all profiles; with ``profile_id`` it is listed only for that profile.

async function getCurrentProfileIdForGroups() {
    try {
        const res = await fetch('/profiles/current', {
            headers: { Accept: 'application/json' },
            credentials: 'same-origin',
        });
        if (!res.ok) return null;
        const data = await res.json();
        const id = data && (data.id || (data.profile && data.profile.id));
        return id != null ? String(id) : null;
    } catch {
        return null;
    }
}

async function fetchGroupsMap() {
    try {
        const response = await fetch('/groups', {
            headers: { Accept: 'application/json' },
            credentials: 'same-origin',
        });
        if (!response.ok) return {};
        const data = await response.json();
        return data && typeof data === 'object' ? data : {};
    } catch (e) {
        console.error('fetchGroupsMap:', e);
        return {};
    }
}

async function fetchDevicesMapForGroups() {
    try {
        const response = await fetch('/devices', { headers: { Accept: 'application/json' } });
        if (!response.ok) return {};
        const data = await response.json();
        return data && typeof data === 'object' ? data : {};
    } catch (e) {
        console.error('fetchDevicesMapForGroups:', e);
        return {};
    }
}

function renderGroupDevicesEditor(containerEl, macRows, devicesMap) {
    if (!containerEl) return;
    containerEl.innerHTML = '';
    const entries = Object.entries(devicesMap || {}).sort(([a], [b]) => a.localeCompare(b));

    macRows.forEach((row, idx) => {
        const div = document.createElement('div');
        div.className = 'zone-device-row profiles-row';
        const label = document.createElement('span');
        label.className = 'zone-device-row-label';
        const strong = document.createElement('strong');
        strong.textContent = row.label || row.mac || '—';
        label.appendChild(strong);
        label.appendChild(document.createTextNode(' '));
        const sub = document.createElement('span');
        sub.className = 'muted-text';
        sub.textContent = row.mac || '';
        label.appendChild(sub);

        const rm = document.createElement('button');
        rm.type = 'button';
        rm.className = 'btn btn-danger btn-small';
        rm.textContent = 'Remove';
        rm.addEventListener('click', () => {
            macRows.splice(idx, 1);
            renderGroupDevicesEditor(containerEl, macRows, devicesMap);
        });
        div.appendChild(label);
        div.appendChild(rm);
        containerEl.appendChild(div);
    });

    const macsInRows = new Set(macRows.map((r) => r.mac).filter(Boolean));
    const addWrap = document.createElement('div');
    addWrap.className = 'zone-devices-add profiles-actions';
    const sel = document.createElement('select');
    sel.className = 'zone-device-add-select';
    sel.appendChild(new Option('Add device…', ''));
    entries.forEach(([mac, d]) => {
        if (macsInRows.has(mac)) return;
        const labelName = d && d.name ? String(d.name).trim() : '';
        const optLabel = labelName ? `${labelName} — ${mac}` : mac;
        sel.appendChild(new Option(optLabel, mac));
    });
    const addBtn = document.createElement('button');
    addBtn.type = 'button';
    addBtn.className = 'btn btn-primary btn-small';
    addBtn.textContent = 'Add';
    addBtn.addEventListener('click', () => {
        const mac = sel.value;
        if (!mac || !devicesMap[mac]) return;
        const n = String((devicesMap[mac].name || '').trim() || mac);
        macRows.push({ mac, label: n });
        sel.value = '';
        renderGroupDevicesEditor(containerEl, macRows, devicesMap);
    });
    addWrap.appendChild(sel);
    addWrap.appendChild(addBtn);
    containerEl.appendChild(addWrap);
    refreshEditGroupDebug();
}

function collectGroupEditPayload() {
    const idInput = document.getElementById('edit-group-id');
    const nameInput = document.getElementById('edit-group-name');
    const gid = idInput && idInput.value;
    const rows = window.__editGroupDeviceRows || [];
    const devices = rows.map((r) => r.mac).filter(Boolean);
    const payload = {
        name: nameInput ? nameInput.value.trim() : '',
        devices,
    };
    const dn = document.getElementById('edit-group-wifi-driver-name');
    const nl = document.getElementById('edit-group-wifi-num-leds');
    const co = document.getElementById('edit-group-wifi-color-order');
    const ws = document.getElementById('edit-group-wifi-startup-mode');
    if (dn && dn.value.trim()) payload.wifi_driver_display_name = dn.value.trim();
    else payload.wifi_driver_display_name = null;
    if (nl && nl.value !== '') {
        const n = parseInt(nl.value, 10);
        if (!Number.isNaN(n) && n >= 1) payload.wifi_driver_num_leds = n;
        else payload.wifi_driver_num_leds = null;
    } else payload.wifi_driver_num_leds = null;
    if (co && co.value) payload.wifi_color_order = co.value;
    if (ws && ws.value) payload.wifi_startup_mode = ws.value;
    const gob = document.getElementById('edit-group-output-brightness');
    if (gob && gob.value !== '') {
        const nb = parseInt(gob.value, 10);
        if (!Number.isNaN(nb)) payload.output_brightness = Math.max(0, Math.min(255, nb));
    }
    return { gid, payload };
}

function refreshEditGroupDebug() {
    const ta = document.getElementById('edit-group-debug');
    if (!ta) return;
    try {
        const { gid, payload } = collectGroupEditPayload();
        const loaded = window.__editGroupLoadedSnapshot;
        ta.value = JSON.stringify(
            {
                group_id: gid || null,
                loaded_from_server: loaded != null ? loaded : null,
                save_payload_preview: payload,
            },
            null,
            2,
        );
    } catch (e) {
        ta.value = String(e);
    }
}

function syncGroupShareCheckboxFromDoc(g) {
    const cb = document.getElementById('edit-group-share-all-profiles');
    if (!cb) return;
    const raw = g && (g.profile_id != null ? g.profile_id : g.profileId);
    const scoped = raw != null && String(raw).trim() !== '';
    cb.checked = !scoped;
}

function loadWifiFieldsFromGroup(g) {
    const wName = document.getElementById('edit-group-wifi-driver-name');
    const wLeds = document.getElementById('edit-group-wifi-num-leds');
    const wCo = document.getElementById('edit-group-wifi-color-order');
    const wStart = document.getElementById('edit-group-wifi-startup-mode');
    if (wName) {
        const v = g && Object.prototype.hasOwnProperty.call(g, 'wifi_driver_display_name')
            ? g.wifi_driver_display_name
            : null;
        wName.value = v != null && String(v).trim() !== '' ? String(v).trim() : '';
    }
    if (wLeds) {
        const v = g && g.wifi_driver_num_leds;
        wLeds.value =
            v != null && v !== '' && String(v).trim() !== ''
                ? String(v)
                : '';
    }
    if (wCo) {
        const co = (g && g.wifi_color_order) || 'rgb';
        wCo.value = ['rgb', 'rbg', 'grb', 'gbr', 'brg', 'bgr'].includes(String(co).toLowerCase())
            ? String(co).toLowerCase()
            : 'rgb';
    }
    if (wStart) {
        const sm = (g && g.wifi_startup_mode) || 'default';
        wStart.value = ['default', 'last', 'off'].includes(String(sm).toLowerCase())
            ? String(sm).toLowerCase()
            : 'default';
    }
    const gob = document.getElementById('edit-group-output-brightness');
    const gobv = document.getElementById('edit-group-output-brightness-value');
    if (gob) {
        let bv = 255;
        if (g && g.output_brightness != null && g.output_brightness !== '') {
            const n = parseInt(String(g.output_brightness), 10);
            if (!Number.isNaN(n)) bv = Math.max(0, Math.min(255, n));
        }
        gob.value = String(bv);
        if (gobv) gobv.textContent = String(bv);
    }
}

async function openEditGroupModal(groupId, groupDoc) {
    const modal = document.getElementById('edit-group-modal');
    const idInput = document.getElementById('edit-group-id');
    const nameInput = document.getElementById('edit-group-name');
    const editor = document.getElementById('edit-group-devices-editor');

    let g = groupDoc;
    if (!g || typeof g !== 'object') {
        try {
            const response = await fetch(`/groups/${encodeURIComponent(groupId)}`, {
                credentials: 'same-origin',
                headers: { Accept: 'application/json' },
            });
            if (response.ok) g = await response.json();
        } catch (e) {
            console.error(e);
        }
    }
    g = g || {};
    try {
        window.__editGroupLoadedSnapshot = JSON.parse(JSON.stringify(g));
    } catch (e) {
        window.__editGroupLoadedSnapshot = g;
    }

    if (idInput) idInput.value = groupId;
    if (nameInput) nameInput.value = g.name || '';

    const dm = await fetchDevicesMapForGroups();
    const macs = Array.isArray(g.devices) ? g.devices : [];
    window.__editGroupDeviceRows = macs.map((m) => {
        const mac = String(m).trim().toLowerCase().replace(/:/g, '').replace(/-/g, '');
        const d = dm[mac];
        return {
            mac,
            label: d && d.name ? String(d.name).trim() : mac,
        };
    });
    renderGroupDevicesEditor(editor, window.__editGroupDeviceRows, dm);
    loadWifiFieldsFromGroup(g);
    syncGroupShareCheckboxFromDoc(g);
    refreshEditGroupDebug();
    if (modal) modal.classList.add('active');
}

async function loadGroupsModal() {
    const container = document.getElementById('groups-list-modal');
    if (!container) return;
    container.innerHTML = '<span class="muted-text">Loading...</span>';
    try {
        const data = await fetchGroupsMap();
        renderGroupsList(data || {});
    } catch (e) {
        console.error('loadGroupsModal:', e);
        container.innerHTML = '<span class="muted-text">Failed to load groups.</span>';
    }
}

function renderGroupsList(groups) {
    const container = document.getElementById('groups-list-modal');
    if (!container) return;
    container.innerHTML = '';
    const ids = Object.keys(groups).filter((k) => groups[k] && typeof groups[k] === 'object');
    if (ids.length === 0) {
        const p = document.createElement('p');
        p.className = 'muted-text';
        p.textContent = 'No groups yet. Create one to assign devices and Wi‑Fi defaults.';
        container.appendChild(p);
        return;
    }
    ids.sort((a, b) => parseInt(a, 10) - parseInt(b, 10));
    ids.forEach((gid) => {
        const g = groups[gid];
        const row = document.createElement('div');
        row.className = 'profiles-row';
        row.style.display = 'flex';
        row.style.alignItems = 'center';
        row.style.gap = '0.5rem';
        row.style.flexWrap = 'wrap';

        const label = document.createElement('span');
        const devs = Array.isArray(g.devices) ? g.devices : [];
        label.textContent = `${g.name || gid} (${devs.length} device${devs.length === 1 ? '' : 's'})`;

        const meta = document.createElement('div');
        meta.className = 'muted-text';
        meta.style.fontSize = '0.8em';
        const rawPid = g.profile_id != null ? g.profile_id : g.profileId;
        const scoped = rawPid != null && String(rawPid).trim() !== '';
        meta.textContent = scoped ? `This profile only (${rawPid})` : 'Shared across profiles';
        const editBtn = document.createElement('button');
        editBtn.className = 'btn btn-secondary btn-small';
        editBtn.textContent = 'Edit';
        editBtn.addEventListener('click', () => openEditGroupModal(gid, g));

        const brightBtn = document.createElement('button');
        brightBtn.className = 'btn btn-secondary btn-small';
        brightBtn.type = 'button';
        brightBtn.textContent = 'Apply brightness';
        brightBtn.title = 'Push group output brightness to Wi‑Fi drivers in this group';
        brightBtn.addEventListener('click', async () => {
            try {
                const res = await fetch(`/groups/${encodeURIComponent(gid)}/brightness`, {
                    method: 'POST',
                    credentials: 'same-origin',
                    headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
                    body: JSON.stringify({}),
                });
                const data = await res.json().catch(() => ({}));
                if (!res.ok) {
                    alert(data.error || 'Apply brightness failed');
                    return;
                }
                const n = typeof data.sent === 'number' ? data.sent : 0;
                alert(
                    n
                        ? `Sent brightness to ${n} driver(s).`
                        : 'No Wi‑Fi drivers received brightness (check connections).',
                );
            } catch (err) {
                console.error(err);
                alert('Apply brightness failed');
            }
        });

        const applyBtn = document.createElement('button');
        applyBtn.className = 'btn btn-primary btn-small';
        applyBtn.type = 'button';
        applyBtn.textContent = 'Apply defaults to drivers';
        applyBtn.title = 'Push Wi‑Fi defaults to each connected driver in this group';
        applyBtn.addEventListener('click', async () => {
            try {
                const res = await fetch(`/groups/${encodeURIComponent(gid)}/driver-config`, {
                    method: 'POST',
                    credentials: 'same-origin',
                    headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
                    body: JSON.stringify({}),
                });
                const data = await res.json().catch(() => ({}));
                if (!res.ok) {
                    alert(data.error || 'Apply failed');
                    return;
                }
                const n = typeof data.sent === 'number' ? data.sent : 0;
                alert(
                    n
                        ? `Sent defaults to ${n} driver(s).`
                        : 'No Wi‑Fi drivers received the config (check defaults and connections).',
                );
            } catch (err) {
                console.error(err);
                alert('Apply failed');
            }
        });

        const identifyBtn = document.createElement('button');
        identifyBtn.className = 'btn btn-secondary btn-small';
        identifyBtn.type = 'button';
        identifyBtn.textContent = 'Identify';
        identifyBtn.title =
            'Identify all devices in this group at once (red blink at 10 Hz)';
        identifyBtn.addEventListener('click', async () => {
            await identifyGroupById(gid);
        });

        const delBtn = document.createElement('button');
        delBtn.className = 'btn btn-danger btn-small';
        delBtn.textContent = 'Delete';
        delBtn.addEventListener('click', async () => {
            if (!confirm(`Delete group "${g.name || gid}"? Zones referencing it may need updating.`)) return;
            try {
                const res = await fetch(`/groups/${encodeURIComponent(gid)}`, {
                    method: 'DELETE',
                    credentials: 'same-origin',
                });
                if (res.ok) await loadGroupsModal();
                else {
                    const data = await res.json().catch(() => ({}));
                    alert(data.error || 'Delete failed');
                }
            } catch (err) {
                console.error(err);
                alert('Delete failed');
            }
        });

        const left = document.createElement('div');
        left.style.flex = '1';
        left.style.minWidth = '0';
        left.appendChild(label);
        left.appendChild(meta);
        row.appendChild(left);
        row.appendChild(editBtn);
        row.appendChild(brightBtn);
        row.appendChild(applyBtn);
        row.appendChild(identifyBtn);
        row.appendChild(delBtn);
        container.appendChild(row);
    });
}

async function identifyGroupById(gid) {
    if (!gid) return;
    try {
        const res = await fetch(`/groups/${encodeURIComponent(gid)}/identify`, {
            method: 'POST',
            credentials: 'same-origin',
            headers: { Accept: 'application/json' },
        });
        const data = await res.json().catch(() => ({}));
        if (!res.ok) {
            alert(data.error || 'Identify failed');
            return;
        }
        const n = typeof data.sent === 'number' ? data.sent : 0;
        const errs = Array.isArray(data.errors) ? data.errors : [];
        const failed = errs.filter((e) => e && e.error).length;
        let msg = n ? `Identify sent to ${n} device(s).` : 'No devices received identify.';
        if (failed) {
            msg += ` ${failed} failed — see console for details.`;
            console.warn('Group identify errors', errs);
        }
        alert(msg);
    } catch (e) {
        console.error(e);
        alert('Identify failed');
    }
}

document.addEventListener('DOMContentLoaded', () => {
    const groupsBtn = document.getElementById('groups-btn');
    const groupsModal = document.getElementById('groups-modal');
    const groupsCloseBtn = document.getElementById('groups-close-btn');
    const newNameInput = document.getElementById('new-group-name');
    const createBtn = document.getElementById('create-group-btn');
    const editForm = document.getElementById('edit-group-form');
    const editCloseBtn = document.getElementById('edit-group-close-btn');
    const editModal = document.getElementById('edit-group-modal');

    if (groupsBtn && groupsModal) {
        groupsBtn.addEventListener('click', () => {
            groupsModal.classList.add('active');
            loadGroupsModal();
        });
    }
    if (groupsCloseBtn && groupsModal) {
        groupsCloseBtn.addEventListener('click', () => groupsModal.classList.remove('active'));
    }

    const grpOutBr = document.getElementById('edit-group-output-brightness');
    const grpOutBrVal = document.getElementById('edit-group-output-brightness-value');
    if (grpOutBr && grpOutBrVal) {
        grpOutBr.addEventListener('input', () => {
            grpOutBrVal.textContent = grpOutBr.value;
        });
    }

    const editIdentifyBtn = document.getElementById('edit-group-identify-btn');
    if (editIdentifyBtn) {
        editIdentifyBtn.addEventListener('click', async () => {
            const idInput = document.getElementById('edit-group-id');
            const gid = idInput && idInput.value;
            if (!gid) return;
            await identifyGroupById(gid);
        });
    }

    const createHandler = async () => {
        const name = newNameInput && newNameInput.value.trim();
        if (!name) return;
        const profileOnly = document.getElementById('new-group-profile-only');
        try {
            const res = await fetch('/groups', {
                method: 'POST',
                credentials: 'same-origin',
                headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
                body: JSON.stringify({
                    name,
                    profile_scoped: !!(profileOnly && profileOnly.checked),
                }),
            });
            const data = await res.json().catch(() => ({}));
            if (!res.ok) {
                alert(data.error || 'Create failed');
                return;
            }
            if (newNameInput) newNameInput.value = '';
            if (profileOnly) profileOnly.checked = false;
            await loadGroupsModal();
        } catch (e) {
            console.error(e);
            alert('Create failed');
        }
    };
    if (createBtn) createBtn.addEventListener('click', createHandler);
    if (newNameInput) {
        newNameInput.addEventListener('keypress', (ev) => {
            if (ev.key === 'Enter') createHandler();
        });
    }

    if (editForm) {
        editForm.addEventListener('input', () => refreshEditGroupDebug());
        editForm.addEventListener('change', () => refreshEditGroupDebug());
        editForm.addEventListener('submit', async (e) => {
            e.preventDefault();
            const { gid, payload } = collectGroupEditPayload();
            if (!gid) return;

            const shareCb = document.getElementById('edit-group-share-all-profiles');
            if (shareCb && shareCb.checked) {
                payload.profile_id = null;
            } else {
                const pid = await getCurrentProfileIdForGroups();
                payload.profile_id = pid || null;
            }

            try {
                const res = await fetch(`/groups/${encodeURIComponent(gid)}`, {
                    method: 'PUT',
                    credentials: 'same-origin',
                    headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
                    body: JSON.stringify(payload),
                });
                const data = await res.json().catch(() => ({}));
                if (!res.ok) {
                    alert(data.error || 'Save failed');
                    return;
                }
                try {
                    await fetch(`/groups/${encodeURIComponent(gid)}/brightness`, {
                        method: 'POST',
                        credentials: 'same-origin',
                        headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
                        body: JSON.stringify({}),
                    });
                } catch (_) {
                    /* ignore push errors after save */
                }
                if (editModal) editModal.classList.remove('active');
                await loadGroupsModal();
            } catch (err) {
                console.error(err);
                alert('Save failed');
            }
        });
    }
    if (editCloseBtn && editModal) {
        editCloseBtn.addEventListener('click', () => editModal.classList.remove('active'));
    }

    window.openDeviceGroupsModal = async () => {
        const gm = document.getElementById('groups-modal');
        if (!gm) return;
        gm.classList.add('active');
        try {
            await loadGroupsModal();
        } catch (e) {
            console.error('openDeviceGroupsModal', e);
        }
    };
});
