(function () {
    const pageRoot = document.getElementById('catalog-page');
    if (!pageRoot) {
        return;
    }

    const page = pageRoot.dataset.page;
    const apiBase = '/api/catalog';

    function showAlert(containerId, message, type = 'danger') {
        const container = document.getElementById(containerId);
        if (!container) return;
        if (!message) {
            container.innerHTML = '';
            return;
        }
        container.innerHTML = `<div class="alert alert-${type} mb-3" role="alert">${message}</div>`;
    }

    async function requestJson(url, options = {}) {
        const response = await fetch(url, {
            headers: {
                'Content-Type': 'application/json'
            },
            ...options
        });

        if (response.status === 204) {
            return null;
        }

        const isJson = response.headers.get('content-type')?.includes('application/json');
        const payload = isJson ? await response.json() : await response.text();

        if (!response.ok) {
            if (payload && typeof payload === 'object') {
                if (payload.error) {
                    throw new Error(payload.error);
                }
                throw new Error(Object.values(payload).join('; '));
            }
            throw new Error(payload || `HTTP ${response.status}`);
        }

        return payload;
    }

    function toNullableNumber(value) {
        return value === '' || value === null || value === undefined ? null : Number(value);
    }

    function formatDateTimeInput(value) {
        const date = PcpUtcTime.parseApiDate(value);
        if (!date) return value || '';
        const pad = (number, length = 2) => String(number).padStart(length, '0');
        return `${pad(date.getDate())}.${pad(date.getMonth() + 1)}.${date.getFullYear()} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}.${pad(date.getMilliseconds(), 3)}`;
    }

    function parseDateTimeInput(value, fieldName, required = false) {
        const text = value?.trim() ?? '';
        if (!text) {
            if (required) {
                throw new Error(`${fieldName}: укажите время в формате dd.mm.yyyy hh:mm:ss.zzz`);
            }
            return null;
        }

        const displayMatch = text.match(/^(\d{2})\.(\d{2})\.(\d{4})\s+(\d{2}):(\d{2}):(\d{2})[.,](\d{1,3})$/);
        if (displayMatch) {
            const [, day, month, year, hour, minute, second, millis] = displayMatch;
            validateDateTimeParts(day, month, year, hour, minute, second, fieldName);
            return PcpUtcTime.toUtcIsoFromRussianDateTime(`${day}.${month}.${year} ${hour}:${minute}:${second}.${millis.padEnd(3, '0')}`);
        }

        const isoMatch = text.match(/^(\d{4})-(\d{2})-(\d{2})[T\s](\d{2}):(\d{2})(?::(\d{2})(?:[.,](\d{1,3}))?)?$/);
        if (isoMatch) {
            const [, year, month, day, hour, minute, second = '00', millis = '000'] = isoMatch;
            validateDateTimeParts(day, month, year, hour, minute, second, fieldName);
            return PcpUtcTime.toUtcIsoFromRussianDateTime(`${day}.${month}.${year} ${hour}:${minute}:${second}.${millis.padEnd(3, '0')}`);
        }

        throw new Error(`${fieldName}: укажите время в формате dd.mm.yyyy hh:mm:ss.zzz`);
    }

    function validateDateTimeParts(day, month, year, hour, minute, second, fieldName) {
        const date = new Date(
            Number(year),
            Number(month) - 1,
            Number(day),
            Number(hour),
            Number(minute),
            Number(second)
        );
        const isValid = date.getFullYear() === Number(year) &&
            date.getMonth() === Number(month) - 1 &&
            date.getDate() === Number(day) &&
            date.getHours() === Number(hour) &&
            date.getMinutes() === Number(minute) &&
            date.getSeconds() === Number(second);

        if (!isValid) {
            throw new Error(`${fieldName}: некорректная дата или время`);
        }
    }

    function formatDisplayDateTime(value) {
        if (!value) return '—';
        return formatDateTimeInput(value);
    }

    function buildRepeatedQueryParam(name, values) {
        const params = new URLSearchParams();
        values.forEach(value => params.append(name, String(value)));
        return params.toString();
    }

    function parseAngles(text) {
        const lines = text
            .split('\n')
            .map(line => line.trim())
            .filter(Boolean);

        return lines.map((line, index) => {
            const parts = line.split(',').map(part => part.trim());
            if (parts.length !== 2) {
                throw new Error(`Строка ${index + 1} должна содержать два числа через запятую`);
            }
            const angleBegin = Number(parts[0]);
            const angleEnd = Number(parts[1]);
            if (Number.isNaN(angleBegin) || Number.isNaN(angleEnd)) {
                throw new Error(`Строка ${index + 1} содержит некорректный диапазон углов`);
            }
            return { angleBegin, angleEnd };
        });
    }

    function renderChips(items) {
        if (!items.length) {
            return '<span class="text-muted">Пусто</span>';
        }
        return items.map(item => `<span class="catalog-chip">${item}</span>`).join('');
    }

    function initGroupsPage() {
        const state = {
            groups: [],
            satellites: [],
            selectedGroupId: null
        };

        const groupTableBody = document.getElementById('groups-table-body');
        const groupForm = document.getElementById('group-form');
        const satelliteChecklist = document.getElementById('group-satellite-checklist');
        const title = document.getElementById('group-form-title');

        function renderSatelliteChecklist() {
            satelliteChecklist.innerHTML = '';
            state.satellites.forEach(satellite => {
                const wrapper = document.createElement('div');
                wrapper.className = 'form-check';
                wrapper.innerHTML = `
                    <input class="form-check-input" type="checkbox" value="${satellite.id}" id="group-satellite-${satellite.id}">
                    <label class="form-check-label" for="group-satellite-${satellite.id}">
                        ${satellite.name} (${satellite.code}, ${satellite.id})
                    </label>
                `;
                satelliteChecklist.appendChild(wrapper);
            });
        }

        function selectedSatelliteIds() {
            return Array.from(satelliteChecklist.querySelectorAll('input:checked'))
                .map(input => Number(input.value));
        }

        function setSelectedSatelliteIds(ids) {
            const selected = new Set(ids);
            satelliteChecklist.querySelectorAll('input').forEach(input => {
                input.checked = selected.has(Number(input.value));
            });
        }

        function renderGroups() {
            groupTableBody.innerHTML = '';
            if (!state.groups.length) {
                groupTableBody.innerHTML = '<tr><td colspan="4" class="text-center text-muted py-4">Группировки не найдены</td></tr>';
                return;
            }

            state.groups.forEach(group => {
                const tr = document.createElement('tr');
                if (group.id === state.selectedGroupId) {
                    tr.classList.add('table-active');
                }
                tr.innerHTML = `
                    <td>${group.id}</td>
                    <td>${group.name}</td>
                    <td>${group.satelliteIds.length}</td>
                    <td>${renderChips(group.satelliteIds.map(String))}</td>
                `;
                tr.addEventListener('click', () => selectGroup(group.id));
                groupTableBody.appendChild(tr);
            });
        }

        function resetForm() {
            groupForm.reset();
            document.getElementById('group-id').value = '';
            state.selectedGroupId = null;
            setSelectedSatelliteIds([]);
            title.textContent = 'Новая группировка';
            renderGroups();
            showAlert('groups-alert', '');
        }

        function fillForm(group) {
            document.getElementById('group-id').value = String(group.id);
            document.getElementById('group-name').value = group.name;
            setSelectedSatelliteIds(group.satelliteIds);
            title.textContent = `Группировка #${group.id}`;
        }

        function selectGroup(groupId) {
            const group = state.groups.find(item => item.id === groupId);
            if (!group) return;
            state.selectedGroupId = groupId;
            fillForm(group);
            renderGroups();
            showAlert('groups-alert', '');
        }

        async function loadData() {
            showAlert('groups-alert', '');
            const [satellites, groups] = await Promise.all([
                requestJson(`${apiBase}/satellites`),
                requestJson(`${apiBase}/groups`)
            ]);
            state.satellites = satellites;
            state.groups = groups;
            renderSatelliteChecklist();
            renderGroups();
            if (state.selectedGroupId) {
                const selected = state.groups.find(item => item.id === state.selectedGroupId);
                if (selected) {
                    fillForm(selected);
                } else {
                    resetForm();
                }
            }
        }

        document.getElementById('groups-refresh').addEventListener('click', async () => {
            try {
                await loadData();
            } catch (error) {
                showAlert('groups-alert', error.message);
            }
        });

        document.getElementById('groups-new').addEventListener('click', resetForm);

        groupForm.addEventListener('submit', async event => {
            event.preventDefault();
            try {
                const groupId = document.getElementById('group-id').value;
                const payload = {
                    name: document.getElementById('group-name').value.trim(),
                    satelliteIds: selectedSatelliteIds()
                };

                const result = groupId
                    ? await requestJson(`${apiBase}/groups/${groupId}`, { method: 'PUT', body: JSON.stringify(payload) })
                    : await requestJson(`${apiBase}/groups`, { method: 'POST', body: JSON.stringify(payload) });

                state.selectedGroupId = result.id;
                await loadData();
                showAlert('groups-alert', 'Группировка сохранена', 'success');
            } catch (error) {
                showAlert('groups-alert', error.message);
            }
        });

        document.getElementById('groups-delete').addEventListener('click', async () => {
            const groupId = document.getElementById('group-id').value;
            if (!groupId) {
                showAlert('groups-alert', 'Сначала выберите группировку для удаления');
                return;
            }
            if (!window.confirm(`Удалить группировку #${groupId}?`)) {
                return;
            }
            try {
                await requestJson(`${apiBase}/groups/${groupId}`, { method: 'DELETE' });
                resetForm();
                await loadData();
                showAlert('groups-alert', 'Группировка удалена', 'success');
            } catch (error) {
                showAlert('groups-alert', error.message);
            }
        });

        loadData().catch(error => showAlert('groups-alert', error.message));
    }

    function initSatellitesPage() {
        const state = {
            summaries: [],
            selectedSatelliteId: null,
            selectedSatellite: null,
            selectedSatelliteInitialConditions: null,
            selectedSlotCalculationSummary: null,
            createDraftMode: false,
            slotSummariesBySatelliteId: new Map()
        };

        const tableBody = document.getElementById('satellites-table-body');
        const searchInput = document.getElementById('satellite-search');

        function updateColorPreview() {
            const red = Number(document.getElementById('satellite-red').value || 0);
            const green = Number(document.getElementById('satellite-green').value || 0);
            const blue = Number(document.getElementById('satellite-blue').value || 0);
            document.getElementById('satellite-color-preview').style.background = `rgb(${red}, ${green}, ${blue})`;
        }

        function renderList() {
            const query = searchInput.value.trim().toLowerCase();
            const items = state.summaries.filter(item =>
                !query ||
                String(item.id).includes(query) ||
                item.name.toLowerCase().includes(query) ||
                item.code.toLowerCase().includes(query)
            );

            tableBody.innerHTML = '';
            if (!items.length) {
                tableBody.innerHTML = '<tr><td colspan="5" class="text-center text-muted py-4">Спутники не найдены</td></tr>';
                return;
            }

            items.forEach(satellite => {
                const slotSummary = state.slotSummariesBySatelliteId.get(Number(satellite.id));
                const tr = document.createElement('tr');
                if (satellite.id === state.selectedSatelliteId) {
                    tr.classList.add('table-active');
                }
                tr.innerHTML = `
                    <td>${satellite.id}</td>
                    <td>${satellite.code}</td>
                    <td>${satellite.name}</td>
                    <td>${satellite.typeCode}</td>
                    <td>${renderSlotIndicator(slotSummary)}</td>
                `;
                tr.addEventListener('click', () => selectSatellite(satellite.id));
                tableBody.appendChild(tr);
            });
        }

        function renderSlotIndicator(summary) {
            const calculated = Boolean(summary?.calculated);
            const title = calculated
                ? 'Рассчитанные слоты есть'
                : 'Рассчитанные слоты отсутствуют';
            return `<span class="catalog-slot-indicator ${calculated ? 'catalog-slot-indicator-active' : ''}" title="${title}"></span>`;
        }

        function renderSlotCalculationSummary(summary) {
            const container = document.getElementById('slot-calculation-summary');
            if (!container) return;

            if (!summary?.calculated) {
                container.innerHTML = `
                    <div class="catalog-empty mb-0">
                        Рассчитанные слоты отсутствуют.
                    </div>
                `;
                return;
            }

            container.innerHTML = `
                <div class="catalog-section-title mb-3">Рассчитанные слоты</div>
                <div class="catalog-slot-summary-grid">
                    <div>
                        <div class="catalog-summary-label">Минимальное время</div>
                        <div class="catalog-summary-value">${formatDisplayDateTime(summary.minTime)}</div>
                    </div>
                    <div>
                        <div class="catalog-summary-label">Максимальное время</div>
                        <div class="catalog-summary-value">${formatDisplayDateTime(summary.maxTime)}</div>
                    </div>
                    <div>
                        <div class="catalog-summary-label">Интервал витков</div>
                        <div class="catalog-summary-value">${summary.revolutionInterval ?? '—'}</div>
                    </div>
                </div>
            `;
        }

        function resetBaseForm() {
            document.getElementById('satellite-form').reset();
            document.getElementById('satellite-id').disabled = false;
            document.getElementById('satellite-active').checked = true;
            document.getElementById('satellite-scan-tle').checked = false;
            document.getElementById('satellite-red').value = 255;
            document.getElementById('satellite-green').value = 0;
            document.getElementById('satellite-blue').value = 0;
            document.getElementById('satellite-form-title').textContent = 'Новый спутник';
            state.selectedSatelliteId = null;
            state.selectedSatellite = null;
            state.selectedSatelliteInitialConditions = null;
            state.selectedSlotCalculationSummary = null;
            state.createDraftMode = false;
            clearProfiles();
            updateColorPreview();
            renderList();
        }

        function clearProfiles() {
            document.getElementById('observation-form').reset();
            document.getElementById('slot-form').reset();
            document.getElementById('slot-ic-form').reset();
            document.getElementById('slot-default-angles').value = '';
            document.getElementById('slot-tn-calc').value = '';
            document.getElementById('slot-ic-time').value = '';
            document.getElementById('slot-ic-status').textContent = 'Начальные условия не заданы.';
            renderSlotCalculationSummary(null);
        }

        function fillProfiles(satellite, initialConditions, slotCalculationSummary) {
            const observation = satellite.observationProfile;
            document.getElementById('observation-capture-angle').value = observation?.captureAngle ?? '';
            document.getElementById('observation-sun-angle-min').value = observation?.sunAngleMin ?? '';
            document.getElementById('observation-duration-min').value = observation?.durationMinSeconds ?? '';
            document.getElementById('observation-duration-max').value = observation?.durationMaxSeconds ?? '';
            document.getElementById('observation-mmi').value = observation?.mmiSeconds ?? '';
            document.getElementById('observation-daily-max').value = observation?.dailyMaxDurationSeconds ?? '';
            document.getElementById('observation-revolution-max').value = observation?.revolutionMaxDurationSeconds ?? '';

            const slotProfile = satellite.slotProfile;
            document.getElementById('slot-cycle-revs').value = slotProfile?.cycleRevs ?? '';
            document.getElementById('slot-tn-calc').value = formatDateTimeInput(slotProfile?.tnCalc);
            document.getElementById('slot-duration').value = slotProfile?.slotDuration ?? '';
            document.getElementById('slot-duration-calc-days').value = slotProfile?.durationCalcDays ?? '';
            document.getElementById('slot-max-chain-length').value = slotProfile?.maxChainLength ?? '';
            document.getElementById('slot-default-angles').value = slotProfile?.defaultAngles?.map(angle => `${angle.angleBegin}, ${angle.angleEnd}`).join('\n') ?? '';

            document.getElementById('slot-ic-time').value = formatDateTimeInput(initialConditions?.ic?.orbPoint?.time);
            document.getElementById('slot-ic-revolution').value = initialConditions?.ic?.orbPoint?.revolution ?? '';
            document.getElementById('slot-ic-s-ball').value = initialConditions?.ic?.sBall ?? '';
            document.getElementById('slot-ic-f81').value = initialConditions?.ic?.f81 ?? '';
            document.getElementById('slot-ic-x').value = initialConditions?.ic?.orbPoint?.x ?? '';
            document.getElementById('slot-ic-y').value = initialConditions?.ic?.orbPoint?.y ?? '';
            document.getElementById('slot-ic-z').value = initialConditions?.ic?.orbPoint?.z ?? '';
            document.getElementById('slot-ic-vx').value = initialConditions?.ic?.orbPoint?.vx ?? '';
            document.getElementById('slot-ic-vy').value = initialConditions?.ic?.orbPoint?.vy ?? '';
            document.getElementById('slot-ic-vz').value = initialConditions?.ic?.orbPoint?.vz ?? '';
            document.getElementById('slot-ic-status').textContent = initialConditions
                ? 'Начальные условия загружены из slot-service.'
                : 'Начальные условия не заданы.';
            renderSlotCalculationSummary(slotCalculationSummary);
        }

        function fillSatelliteForm(satellite, createMode = false, initialConditions = state.selectedSatelliteInitialConditions, slotCalculationSummary = state.selectedSlotCalculationSummary) {
            document.getElementById('satellite-id').value = createMode ? '' : satellite.id;
            document.getElementById('satellite-id').disabled = !createMode;
            document.getElementById('satellite-norad-id').value = satellite.noradId ?? '';
            document.getElementById('satellite-code').value = satellite.code;
            document.getElementById('satellite-name').value = satellite.name;
            document.getElementById('satellite-type-code').value = satellite.typeCode;
            document.getElementById('satellite-active').checked = satellite.active;
            document.getElementById('satellite-scan-tle').checked = satellite.scanTle;
            document.getElementById('satellite-red').value = satellite.visualization.red;
            document.getElementById('satellite-green').value = satellite.visualization.green;
            document.getElementById('satellite-blue').value = satellite.visualization.blue;
            document.getElementById('satellite-form-title').textContent = createMode ? 'Новый спутник' : `Спутник #${satellite.id}`;
            fillProfiles(
                satellite,
                initialConditions,
                slotCalculationSummary
            );
            updateColorPreview();
        }

        function newSatelliteFromSelected() {
            if (!state.selectedSatellite) {
                resetBaseForm();
                return;
            }

            state.selectedSatelliteId = null;
            state.selectedSatellite = null;
            state.selectedSatelliteInitialConditions = null;
            state.selectedSlotCalculationSummary = null;
            state.createDraftMode = true;
            document.getElementById('satellite-id').value = '';
            document.getElementById('satellite-id').disabled = false;
            document.getElementById('satellite-form-title').textContent = 'Новый спутник';
            document.getElementById('slot-ic-status').textContent = 'Начальные условия скопированы из выбранного спутника.';
            renderSlotCalculationSummary(null);
            renderList();
        }

        async function loadSummaries() {
            state.summaries = await requestJson(`${apiBase}/satellites`);
            const satelliteIds = state.summaries.map(satellite => satellite.id);
            renderList();

            try {
                const slotSummaries = satelliteIds.length
                    ? await requestJson(`${apiBase}/satellites/slot-calculation-summaries?${buildRepeatedQueryParam('satelliteIds', satelliteIds)}`)
                    : [];
                state.slotSummariesBySatelliteId = new Map(
                    slotSummaries.map(summary => [Number(summary.satelliteId), summary])
                );
            } catch (error) {
                console.warn('Slot calculation summaries are unavailable', error);
                state.slotSummariesBySatelliteId = new Map();
            }
            renderList();
        }

        async function selectSatellite(id) {
            try {
                const [satellite, initialConditions] = await Promise.all([
                    requestJson(`${apiBase}/satellites/${id}`),
                    requestJson(`${apiBase}/satellites/${id}/initial-conditions`)
                ]);
                let slotCalculationSummary = null;
                try {
                    slotCalculationSummary = await requestJson(`${apiBase}/satellites/${id}/slot-calculation-summary`);
                } catch (error) {
                    console.warn(`Slot calculation summary is unavailable for satellite ${id}`, error);
                }
                state.selectedSatelliteId = id;
                state.selectedSatellite = satellite;
                state.selectedSatelliteInitialConditions = initialConditions;
                state.selectedSlotCalculationSummary = slotCalculationSummary;
                state.createDraftMode = false;
                state.slotSummariesBySatelliteId.set(Number(id), slotCalculationSummary);
                fillSatelliteForm(satellite);
                renderList();
                showAlert('satellites-alert', '');
            } catch (error) {
                showAlert('satellites-alert', error.message);
            }
        }

        function basePayload() {
            return {
                noradId: toNullableNumber(document.getElementById('satellite-norad-id').value),
                code: document.getElementById('satellite-code').value.trim(),
                name: document.getElementById('satellite-name').value.trim(),
                typeCode: document.getElementById('satellite-type-code').value.trim(),
                active: document.getElementById('satellite-active').checked,
                scanTle: document.getElementById('satellite-scan-tle').checked,
                visualization: {
                    red: Number(document.getElementById('satellite-red').value),
                    green: Number(document.getElementById('satellite-green').value),
                    blue: Number(document.getElementById('satellite-blue').value)
                }
            };
        }

        function observationPayload() {
            return {
                captureAngle: Number(document.getElementById('observation-capture-angle').value),
                sunAngleMin: Number(document.getElementById('observation-sun-angle-min').value),
                durationMinSeconds: Number(document.getElementById('observation-duration-min').value),
                durationMaxSeconds: Number(document.getElementById('observation-duration-max').value),
                mmiSeconds: Number(document.getElementById('observation-mmi').value),
                dailyMaxDurationSeconds: Number(document.getElementById('observation-daily-max').value),
                revolutionMaxDurationSeconds: Number(document.getElementById('observation-revolution-max').value)
            };
        }

        function slotPayload() {
            return {
                cycleRevs: Number(document.getElementById('slot-cycle-revs').value),
                tnCalc: parseDateTimeInput(document.getElementById('slot-tn-calc').value, 'TN calc'),
                slotDuration: Number(document.getElementById('slot-duration').value),
                durationCalcDays: Number(document.getElementById('slot-duration-calc-days').value),
                maxChainLength: Number(document.getElementById('slot-max-chain-length').value),
                defaultAngles: parseAngles(document.getElementById('slot-default-angles').value)
            };
        }

        function initialConditionsPayload() {
            return {
                orbPoint: {
                    time: parseDateTimeInput(document.getElementById('slot-ic-time').value, 'Time', true),
                    revolution: Number(document.getElementById('slot-ic-revolution').value),
                    vx: Number(document.getElementById('slot-ic-vx').value),
                    vy: Number(document.getElementById('slot-ic-vy').value),
                    vz: Number(document.getElementById('slot-ic-vz').value),
                    x: Number(document.getElementById('slot-ic-x').value),
                    y: Number(document.getElementById('slot-ic-y').value),
                    z: Number(document.getElementById('slot-ic-z').value)
                },
                sBall: Number(document.getElementById('slot-ic-s-ball').value),
                f81: Number(document.getElementById('slot-ic-f81').value)
            };
        }

        document.getElementById('satellites-refresh').addEventListener('click', async () => {
            try {
                await loadSummaries();
                if (state.selectedSatelliteId) {
                    await selectSatellite(state.selectedSatelliteId);
                }
            } catch (error) {
                showAlert('satellites-alert', error.message);
            }
        });

        document.getElementById('satellites-new').addEventListener('click', () => {
            newSatelliteFromSelected();
            showAlert('satellites-alert', '');
        });

        searchInput.addEventListener('input', renderList);
        ['satellite-red', 'satellite-green', 'satellite-blue'].forEach(id => {
            document.getElementById(id).addEventListener('input', updateColorPreview);
        });

        document.getElementById('satellite-form').addEventListener('submit', async event => {
            event.preventDefault();
            try {
                const idField = document.getElementById('satellite-id');
                const isCreate = !state.selectedSatelliteId;
                const satelliteId = Number(idField.value);

                const result = isCreate
                    ? await requestJson(`${apiBase}/satellites`, {
                        method: 'POST',
                        body: JSON.stringify({ id: satelliteId, ...basePayload() })
                    })
                    : await requestJson(`${apiBase}/satellites/${satelliteId}`, {
                        method: 'PUT',
                        body: JSON.stringify(basePayload())
                    });

                await loadSummaries();
                if (isCreate && state.createDraftMode) {
                    state.selectedSatelliteId = result.id;
                    state.selectedSatellite = result;
                    state.selectedSatelliteInitialConditions = null;
                    state.selectedSlotCalculationSummary = null;
                    document.getElementById('satellite-id').value = result.id;
                    document.getElementById('satellite-id').disabled = true;
                    document.getElementById('satellite-form-title').textContent = `Спутник #${result.id}`;
                    renderList();
                } else {
                    await selectSatellite(result.id);
                }
                showAlert('satellites-alert', 'Спутник сохранён', 'success');
            } catch (error) {
                showAlert('satellites-alert', error.message);
            }
        });

        document.getElementById('satellite-delete').addEventListener('click', async () => {
            if (!state.selectedSatelliteId) {
                showAlert('satellites-alert', 'Сначала выберите спутник для удаления');
                return;
            }
            if (!window.confirm(`Удалить спутник #${state.selectedSatelliteId}?`)) {
                return;
            }
            try {
                await requestJson(`${apiBase}/satellites/${state.selectedSatelliteId}`, { method: 'DELETE' });
                await loadSummaries();
                resetBaseForm();
                showAlert('satellites-alert', 'Спутник удалён', 'success');
            } catch (error) {
                showAlert('satellites-alert', error.message);
            }
        });

        document.getElementById('observation-form').addEventListener('submit', async event => {
            event.preventDefault();
            if (!state.selectedSatelliteId) {
                showAlert('satellites-alert', 'Сначала сохраните спутник');
                return;
            }
            try {
                const create = !state.selectedSatellite?.observationProfile;
                await requestJson(`${apiBase}/satellites/${state.selectedSatelliteId}/observation-profile?create=${create}`, {
                    method: 'POST',
                    body: JSON.stringify(observationPayload())
                });
                if (state.createDraftMode) {
                    state.selectedSatellite = {
                        ...state.selectedSatellite,
                        observationProfile: observationPayload()
                    };
                } else {
                    await selectSatellite(state.selectedSatelliteId);
                }
                showAlert('satellites-alert', 'Observation profile сохранён', 'success');
            } catch (error) {
                showAlert('satellites-alert', error.message);
            }
        });

        document.getElementById('observation-delete').addEventListener('click', async () => {
            if (!state.selectedSatelliteId || !state.selectedSatellite?.observationProfile) {
                showAlert('satellites-alert', 'Observation profile отсутствует');
                return;
            }
            try {
                await requestJson(`${apiBase}/satellites/${state.selectedSatelliteId}/observation-profile`, { method: 'DELETE' });
                await selectSatellite(state.selectedSatelliteId);
                showAlert('satellites-alert', 'Observation profile удалён', 'success');
            } catch (error) {
                showAlert('satellites-alert', error.message);
            }
        });

        document.getElementById('slot-form').addEventListener('submit', async event => {
            event.preventDefault();
            if (!state.selectedSatelliteId) {
                showAlert('satellites-alert', 'Сначала сохраните спутник');
                return;
            }
            try {
                const create = !state.selectedSatellite?.slotProfile;
                await requestJson(`${apiBase}/satellites/${state.selectedSatelliteId}/slot-profile?create=${create}`, {
                    method: 'POST',
                    body: JSON.stringify(slotPayload())
                });
                if (state.createDraftMode) {
                    state.selectedSatellite = {
                        ...state.selectedSatellite,
                        slotProfile: slotPayload()
                    };
                } else {
                    await selectSatellite(state.selectedSatelliteId);
                }
                showAlert('satellites-alert', 'Slot profile сохранён', 'success');
            } catch (error) {
                showAlert('satellites-alert', error.message);
            }
        });

        document.getElementById('slot-delete').addEventListener('click', async () => {
            if (!state.selectedSatelliteId || !state.selectedSatellite?.slotProfile) {
                showAlert('satellites-alert', 'Slot profile отсутствует');
                return;
            }
            try {
                await requestJson(`${apiBase}/satellites/${state.selectedSatelliteId}/slot-profile`, { method: 'DELETE' });
                await selectSatellite(state.selectedSatelliteId);
                showAlert('satellites-alert', 'Slot profile удалён', 'success');
            } catch (error) {
                showAlert('satellites-alert', error.message);
            }
        });

        document.getElementById('slot-calculate').addEventListener('click', async () => {
            if (!state.selectedSatelliteId) {
                showAlert('satellites-alert', 'Сначала сохраните спутник');
                return;
            }
            try {
                await requestJson(`${apiBase}/satellites/${state.selectedSatelliteId}/slot-calculation`, {
                    method: 'POST',
                    body: JSON.stringify(slotPayload())
                });
                await loadSummaries();
                await selectSatellite(state.selectedSatelliteId);
                showAlert('satellites-alert', 'Расчет слотов запущен', 'success');
            } catch (error) {
                showAlert('satellites-alert', error.message);
            }
        });

        document.getElementById('slot-ic-form').addEventListener('submit', async event => {
            event.preventDefault();
            if (!state.selectedSatelliteId) {
                showAlert('satellites-alert', 'Сначала сохраните спутник');
                return;
            }
            try {
                const create = !state.selectedSatelliteInitialConditions;
                await requestJson(`${apiBase}/satellites/${state.selectedSatelliteId}/initial-conditions?create=${create}`, {
                    method: 'POST',
                    body: JSON.stringify(initialConditionsPayload())
                });
                if (state.createDraftMode) {
                    state.selectedSatelliteInitialConditions = {
                        satelliteId: state.selectedSatelliteId,
                        ic: initialConditionsPayload()
                    };
                    document.getElementById('slot-ic-status').textContent = 'Начальные условия сохранены в slot-service.';
                } else {
                    await selectSatellite(state.selectedSatelliteId);
                }
                showAlert('satellites-alert', 'Начальные условия сохранены', 'success');
            } catch (error) {
                showAlert('satellites-alert', error.message);
            }
        });

        loadSummaries()
            .then(() => {
                updateColorPreview();
                if (state.summaries.length) {
                    return selectSatellite(state.summaries[0].id);
                }
                resetBaseForm();
                return null;
            })
            .catch(error => showAlert('satellites-alert', error.message));
    }

    if (page === 'groups') {
        initGroupsPage();
    }

    if (page === 'satellites') {
        initSatellitesPage();
    }
})();
