(function () {
    const state = {
        satellites: [],
        requests: [],
        selectedSatelliteIds: new Set(),
        bookings: []
    };

    const el = (id) => document.getElementById(id);

    document.addEventListener('DOMContentLoaded', () => {
        setDefaultInterval();
        bindEvents();
        loadOptions().then(() => loadBookings());
    });

    function bindEvents() {
        el('bookings-refresh')?.addEventListener('click', () => loadBookings());
        el('bookings-reset')?.addEventListener('click', resetFilters);
        el('bookings-satellites-clear')?.addEventListener('click', () => {
            selectVisibleSatellites();
        });
        el('bookings-satellite-search')?.addEventListener('input', renderSatellites);
        el('bookings-request')?.addEventListener('change', () => loadBookings());
        el('bookings-time-start')?.addEventListener('change', () => loadBookings());
        el('bookings-time-stop')?.addEventListener('change', () => loadBookings());
    }

    function setDefaultInterval() {
        const now = new Date();
        now.setMinutes(0, 0, 0);
        const stop = new Date(now.getTime());
        stop.setDate(stop.getDate() + 7);
        if (el('bookings-time-start')) el('bookings-time-start').value = toDateTimeLocal(now);
        if (el('bookings-time-stop')) el('bookings-time-stop').value = toDateTimeLocal(stop);
    }

    function resetFilters() {
        state.selectedSatelliteIds.clear();
        if (el('bookings-request')) el('bookings-request').value = '';
        if (el('bookings-satellite-search')) el('bookings-satellite-search').value = '';
        setDefaultInterval();
        renderSatellites();
        loadBookings();
    }

    async function loadOptions() {
        try {
            const options = await fetchJson('/api/bookings/options');
            state.satellites = Array.isArray(options.satellites) ? options.satellites : [];
            state.requests = Array.isArray(options.requests) ? options.requests : [];
            renderRequests();
            renderSatellites();
        } catch (error) {
            showAlert(error.message || 'Не удалось загрузить справочники страницы бронирований.', 'danger');
        }
    }

    async function loadBookings() {
        setTableLoading();
        const params = new URLSearchParams();
        const timeStart = el('bookings-time-start')?.value;
        const timeStop = el('bookings-time-stop')?.value;
        const requestId = el('bookings-request')?.value;

        if (timeStart) params.set('timeStart', PcpUtcTime.toUtcIsoFromInput(timeStart));
        if (timeStop) params.set('timeStop', PcpUtcTime.toUtcIsoFromInput(timeStop));
        if (requestId) params.set('requestId', requestId);
        state.selectedSatelliteIds.forEach((id) => params.append('satelliteIds', id));

        try {
            const items = await fetchJson(`/api/bookings?${params.toString()}`);
            state.bookings = Array.isArray(items) ? items : [];
            renderBookings();
        } catch (error) {
            state.bookings = [];
            renderBookings();
            showAlert(error.message || 'Не удалось загрузить забронированные слоты.', 'danger');
        }
    }

    function visibleSatellites() {
        const query = (el('bookings-satellite-search')?.value || '').trim().toLowerCase();
        return state.satellites.filter((satellite) => satelliteMatches(satellite, query));
    }

    function selectVisibleSatellites() {
        const satellites = visibleSatellites();
        satellites.forEach((satellite) => {
            const id = Number(satellite.id);
            if (!Number.isNaN(id)) {
                state.selectedSatelliteIds.add(id);
            }
        });
        renderSatellites();
        loadBookings();
    }

    function renderRequests() {
        const select = el('bookings-request');
        if (!select) return;
        const current = select.value;
        select.innerHTML = '<option value="">Все заявки</option>' + state.requests.map((request) => {
            const title = request.name ? `${request.name} / ${request.id}` : request.id;
            return `<option value="${escapeHtml(request.id)}">${escapeHtml(title)}</option>`;
        }).join('');
        select.value = current;
    }

    function renderSatellites() {
        const tbody = el('bookings-satellites-body');
        if (!tbody) return;
        const satellites = visibleSatellites();

        if (!satellites.length) {
            tbody.innerHTML = emptyRow(3, 'Спутники не найдены.');
            return;
        }

        tbody.innerHTML = satellites.map((satellite) => {
            const selected = state.selectedSatelliteIds.has(Number(satellite.id));
            return `
                <tr class="${selected ? 'bookings-selected-row' : ''}" data-satellite-id="${escapeHtml(satellite.id)}">
                    <td><input class="form-check-input" type="checkbox" ${selected ? 'checked' : ''} aria-label="Выбрать спутник"></td>
                    <td class="bookings-id">${escapeHtml(satellite.id ?? '—')}</td>
                    <td>
                        <div class="bookings-main-text">${escapeHtml(satellite.name || satellite.code || 'КА')}</div>
                        <div class="bookings-sub-text">${escapeHtml([satellite.code, satellite.typeCode, satellite.noradId ? `NORAD ${satellite.noradId}` : null].filter(Boolean).join(' / ') || '—')}</div>
                    </td>
                </tr>`;
        }).join('');

        tbody.querySelectorAll('tr[data-satellite-id]').forEach((row) => {
            row.addEventListener('click', (event) => {
                event.preventDefault();
                const id = Number(row.dataset.satelliteId);
                if (state.selectedSatelliteIds.has(id)) {
                    state.selectedSatelliteIds.delete(id);
                } else {
                    state.selectedSatelliteIds.add(id);
                }
                renderSatellites();
                loadBookings();
            });
        });
    }

    function renderBookings() {
        const tbody = el('bookings-body');
        const empty = el('bookings-empty');
        const wrap = el('bookings-table-wrap');
        if (!tbody) return;

        if (!state.bookings.length) {
            tbody.innerHTML = '';
            empty?.classList.remove('d-none');
            wrap?.classList.add('d-none');
            updateSummary();
            return;
        }

        empty?.classList.add('d-none');
        wrap?.classList.remove('d-none');
        tbody.innerHTML = state.bookings.map((booking) => `
            <tr>
                <td class="bookings-id">${escapeHtml(booking.bookedSlotId ?? '—')}</td>
                <td>
                    <div class="bookings-main-text">${escapeHtml(booking.satelliteName || booking.satelliteCode || `КА ${booking.satelliteId}`)}</div>
                    <div class="bookings-sub-text">ID ${escapeHtml(booking.satelliteId)}${booking.satelliteTypeCode ? ` / ${escapeHtml(booking.satelliteTypeCode)}` : ''}</div>
                </td>
                <td>
                    <div>Слот ${escapeHtml(booking.slotNum ?? '—')}</div>
                    <div class="bookings-sub-text">Цикл ${escapeHtml(booking.cycle ?? '—')}</div>
                </td>
                <td class="bookings-time-cell">
                    <div>${formatDateTime(booking.timeStart)}</div>
                    <div class="bookings-sub-text">${formatDateTime(booking.timeStop)}${booking.durationSeconds != null ? ` / ${formatNumber(booking.durationSeconds)} c` : ''}</div>
                </td>
                <td>
                    <div>${escapeHtml(booking.revolution ?? '—')}</div>
                    <div class="bookings-sub-text">${escapeHtml(booking.revolutionSign || '—')}</div>
                </td>
                <td>${formatNumber(booking.roll)}</td>
                <td><span class="bookings-badge ${statusClass(booking.status)}">${escapeHtml(booking.status || '—')}</span></td>
                <td>${formatRequestIds(booking.requestIds)}</td>
            </tr>`).join('');
        updateSummary();
    }

    function updateSummary() {
        const summary = el('bookings-summary');
        if (!summary) return;
        const requestId = el('bookings-request')?.value;
        const satellites = state.selectedSatelliteIds.size ? `, спутников: ${state.selectedSatelliteIds.size}` : '';
        const request = requestId ? `, заявка: ${requestId}` : '';
        summary.textContent = `Найдено бронирований: ${state.bookings.length}${satellites}${request}`;
    }

    function setTableLoading() {
        el('bookings-empty')?.classList.add('d-none');
        el('bookings-table-wrap')?.classList.remove('d-none');
        const tbody = el('bookings-body');
        if (tbody) tbody.innerHTML = emptyRow(8, 'Загрузка бронирований...');
        const summary = el('bookings-summary');
        if (summary) summary.textContent = 'Загрузка данных...';
    }

    async function fetchJson(url, options = {}) {
        const response = await fetch(url, {
            headers: { 'Accept': 'application/json', ...(options.headers || {}) },
            ...options
        });
        if (!response.ok) {
            const text = await response.text();
            throw new Error(extractError(text) || `HTTP ${response.status}`);
        }
        if (response.status === 204) return null;
        return response.json();
    }

    function satelliteMatches(satellite, query) {
        if (!query) return true;
        return [satellite.id, satellite.noradId, satellite.code, satellite.name, satellite.typeCode]
            .filter((value) => value !== undefined && value !== null)
            .some((value) => String(value).toLowerCase().includes(query));
    }

    function emptyRow(colspan, text) {
        return `<tr><td colspan="${colspan}" class="catalog-empty">${escapeHtml(text)}</td></tr>`;
    }

    function formatRequestIds(ids) {
        if (!Array.isArray(ids) || !ids.length) return '—';
        return ids.map((id) => `<span class="bookings-badge">${escapeHtml(id)}</span>`).join(' ');
    }

    function statusClass(status) {
        if (!status) return '';
        return `bookings-status-${String(status).toLowerCase()}`;
    }

    function formatDateTime(value) {
        return value ? PcpUtcTime.formatDateTime(value) : '—';
    }

    function formatNumber(value) {
        if (value === null || value === undefined || value === '') return '—';
        const number = Number(value);
        if (Number.isNaN(number)) return escapeHtml(value);
        return number.toLocaleString('ru-RU', { maximumFractionDigits: 3 });
    }

    function toDateTimeLocal(date) {
        return PcpUtcTime.toLocalInputValue(date);
    }

    function showAlert(message, type = 'info') {
        const box = el('bookings-alert');
        if (!box) return;
        box.innerHTML = `<div class="alert alert-${type} alert-dismissible fade show" role="alert">
            ${escapeHtml(message)}
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Закрыть"></button>
        </div>`;
    }

    function extractError(text) {
        if (!text) return '';
        try {
            const json = JSON.parse(text);
            return json.message || json.error || text;
        } catch (_) {
            return text;
        }
    }

    function escapeHtml(value) {
        return String(value ?? '')
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
    }
})();
