import { api } from '../api.js';
import { escapeHtml, showAlert, hideAlert } from '../utils.js';
import { buildAcademicCalendarTitle } from './academic-calendar-title.js';

async function fetchEducationForms() {
    try {
        return await api.get('/api/education-forms');
    } catch (e) {
        console.error('Не удалось загрузить формы обучения');
        return [];
    }
}

const FILTER_EF_EMPTY_TEXT = 'Выберите форму обучения';

export async function initGroups() {
    const groupsTbody = document.getElementById('groups-tbody');
    const createGroupForm = document.getElementById('create-group-form');
    const newGroupEfSelect = document.getElementById('new-group-ef');
    const newGroupDepartmentSelect = document.getElementById('new-group-department');
    const newGroupSpecialitySelect = document.getElementById('new-group-speciality-code');
    const newGroupProfileSelect = document.getElementById('new-group-profile');
    const filterEfBox = document.getElementById('filter-ef-box');
    const filterEfMenu = document.getElementById('filter-ef-menu');
    const filterEfText = document.getElementById('filter-ef-text');
    const filterEfCheckboxes = document.getElementById('filter-ef-checkboxes');
    
    // Модалка группы
    const modalEditGroup = document.getElementById('modal-edit-group');
    const modalEditGroupClose = document.getElementById('modal-edit-group-close');
    const editGroupForm = document.getElementById('edit-group-form');
    const editGroupEfSelect = document.getElementById('edit-group-ef');
    const editGroupDepartmentSelect = document.getElementById('edit-group-department');
    const editGroupSpecialitySelect = document.getElementById('edit-group-speciality-code');
    const editGroupProfileSelect = document.getElementById('edit-group-profile');

    // Модалка подгрупп
    const modalManageSubgroups = document.getElementById('modal-manage-subgroups');
    const modalManageSubgroupsClose = document.getElementById('modal-manage-subgroups-close');
    const subgroupsGroupContext = document.getElementById('subgroups-group-context');
    const subgroupFormTitle = document.getElementById('subgroup-form-title');
    const manageSubgroupForm = document.getElementById('manage-subgroup-form');
    const manageSubgroupIdInput = document.getElementById('manage-subgroup-id');
    const manageSubgroupGroupIdInput = document.getElementById('manage-subgroup-group-id');
    const manageSubgroupCountSelect = document.getElementById('manage-subgroup-count');
    const manageSubgroupCapacities = document.getElementById('manage-subgroup-capacities');
    const btnSaveSubgroup = document.getElementById('btn-save-subgroup');
    const btnCancelSubgroupEdit = document.getElementById('btn-cancel-subgroup-edit');
    const manageSubgroupsTbody = document.getElementById('manage-subgroups-tbody');

    // Модалка календарей
    const modalManageCalendar = document.getElementById('modal-manage-calendar');
    const modalManageCalendarClose = document.getElementById('modal-manage-calendar-close');
    const calendarGroupContext = document.getElementById('calendar-group-context');
    const manageCalendarForm = document.getElementById('manage-calendar-form');
    const manageCalendarGroupIdInput = document.getElementById('manage-calendar-group-id');
    const manageCalendarYearSelect = document.getElementById('manage-calendar-year');
    const manageCalendarSelect = document.getElementById('manage-calendar-id');
    const manageCalendarTbody = document.getElementById('manage-calendar-tbody');

    let allGroups = [];
    let subgroups = [];
    let educationForms = [];
    let departments = [];
    let specialties = [];
    let profilesBySpecialty = new Map();
    let academicYears = [];
    let calendars = [];
    let currentAssignments = [];
    let activeSubgroupGroup = null;

    bindEvents();
    await loadInitialData();

    function bindEvents() {
        initFilterEfDropdown();
        filterEfCheckboxes.addEventListener('change', handleFilterEfChange);
        newGroupSpecialitySelect.addEventListener('change', () => populateProfileSelect(newGroupProfileSelect, newGroupSpecialitySelect.value));
        editGroupSpecialitySelect.addEventListener('change', () => populateProfileSelect(editGroupProfileSelect, editGroupSpecialitySelect.value));
        
        createGroupForm.addEventListener('submit', createGroup);
        editGroupForm.addEventListener('submit', updateGroup);
        
        // Модалка подгрупп
        manageSubgroupForm.addEventListener('submit', saveSubgroup);
        manageSubgroupCountSelect.addEventListener('change', () => renderSubgroupCapacityFields(Number(manageSubgroupCountSelect.value)));
        btnCancelSubgroupEdit.addEventListener('click', resetSubgroupForm);
        manageSubgroupsTbody.addEventListener('click', handleSubgroupTableClick);

        // Модалка календарей
        manageCalendarForm.addEventListener('submit', saveAssignment);
        manageCalendarYearSelect.addEventListener('change', populateCalendarSelect);

        groupsTbody.addEventListener('click', handleGroupTableClick);
        
        // Закрытие модалок
        modalEditGroupClose.addEventListener('click', () => modalEditGroup.classList.remove('open'));
        modalEditGroup.addEventListener('click', (event) => {
            if (event.target === modalEditGroup) modalEditGroup.classList.remove('open');
        });

        modalManageSubgroupsClose.addEventListener('click', () => modalManageSubgroups.classList.remove('open'));
        modalManageSubgroups.addEventListener('click', (event) => {
            if (event.target === modalManageSubgroups) modalManageSubgroups.classList.remove('open');
        });

        modalManageCalendarClose.addEventListener('click', () => modalManageCalendar.classList.remove('open'));
        modalManageCalendar.addEventListener('click', (event) => {
            if (event.target === modalManageCalendar) modalManageCalendar.classList.remove('open');
        });
    }

    function initFilterEfDropdown() {
        if (!filterEfBox || !filterEfMenu) return;

        const toggleDropdown = (event) => {
            event.stopPropagation();
            const isOpen = filterEfMenu.classList.contains('open');
            document.querySelectorAll('.dropdown-menu').forEach(menu => menu.classList.remove('open'));
            document.querySelectorAll('.select-box').forEach(box => box.classList.remove('active'));

            if (!isOpen) {
                filterEfMenu.classList.add('open');
                filterEfBox.classList.add('active');
                filterEfBox.setAttribute('aria-expanded', 'true');
            } else {
                filterEfBox.setAttribute('aria-expanded', 'false');
            }
        };

        filterEfBox.addEventListener('click', toggleDropdown);
        filterEfBox.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                toggleDropdown(event);
            }
        });

        filterEfMenu.addEventListener('click', (event) => {
            event.stopPropagation();
        });
    }

    async function loadInitialData() {
        try {
            [educationForms, departments, specialties, academicYears, calendars] = await Promise.all([
                fetchEducationForms(),
                api.get('/api/departments'),
                api.get('/api/specialties'),
                api.get('/api/admin/calendar/years'),
                api.get('/api/admin/academic-calendars')
            ]);
            await loadProfiles();
            populateEfSelects(educationForms);
            populateDepartmentSelects(departments);
            populateSpecialitySelects(specialties);
            populateYearSelect();
            await loadGroups();
            await loadSubgroups();
        } catch (error) {
            groupsTbody.innerHTML = `<tr><td colspan="10" class="loading-row">Ошибка загрузки данных: ${escapeHtml(error.message)}</td></tr>`;
        }
    }

    async function loadProfiles() {
        const pairs = await Promise.all(specialties.map(async (speciality) => {
            const profiles = await api.get(`/api/specialties/${speciality.id}/profiles`);
            return [String(speciality.id), profiles];
        }));
        profilesBySpecialty = new Map(pairs);
    }

    async function loadGroups() {
        try {
            allGroups = await api.get('/api/groups?includeArchived=true');
            applyGroupFilter();
        } catch (error) {
            groupsTbody.innerHTML = `<tr><td colspan="10" class="loading-row">Ошибка загрузки: ${escapeHtml(error.message)}</td></tr>`;
        }
    }

    async function loadSubgroups() {
        try {
            subgroups = await api.get('/api/subgroups');
        } catch (error) {
            console.error('Не удалось загрузить подгруппы');
        }
    }

    function applyGroupFilter() {
        const selectedIds = selectedFilterEducationFormIds();
        const filtered = selectedIds.length
            ? allGroups.filter(group => selectedIds.includes(String(group.educationFormId)))
            : allGroups;
        renderGroups(filtered);
    }

    function handleFilterEfChange(event) {
        const changedCheckbox = event.target.closest('input[type="checkbox"]');
        const allCheckbox = filterEfCheckboxes.querySelector('input[value="all"]');

        if (changedCheckbox?.value === 'all' && changedCheckbox.checked) {
            filterEfCheckboxes.querySelectorAll('input[type="checkbox"]:not([value="all"])').forEach(checkbox => {
                checkbox.checked = false;
            });
        } else if (changedCheckbox?.value !== 'all' && changedCheckbox?.checked) {
            allCheckbox.checked = false;
        }

        if (!selectedFilterEducationFormIds().length) {
            allCheckbox.checked = true;
        }

        updateFilterEfText();
        applyGroupFilter();
    }

    function selectedFilterEducationFormIds() {
        const allCheckbox = filterEfCheckboxes.querySelector('input[value="all"]');
        if (allCheckbox?.checked) return [];

        return Array.from(filterEfCheckboxes.querySelectorAll('input[type="checkbox"]:checked:not([value="all"])'))
            .map(checkbox => String(checkbox.value));
    }

    function updateFilterEfText() {
        const allCheckbox = filterEfCheckboxes.querySelector('input[value="all"]');
        const selectedIds = selectedFilterEducationFormIds();
        if (allCheckbox?.checked) {
            filterEfText.textContent = 'Все';
            return;
        }

        if (!selectedIds.length) {
            filterEfText.textContent = FILTER_EF_EMPTY_TEXT;
            return;
        }

        if (selectedIds.length === 1) {
            const form = educationForms.find(item => String(item.id) === selectedIds[0]);
            filterEfText.textContent = form?.name || FILTER_EF_EMPTY_TEXT;
            return;
        }

        filterEfText.textContent = `Выбрано: ${selectedIds.length}`;
    }

    function renderGroups(groups) {
        if (!groups || !groups.length) {
            groupsTbody.innerHTML = '<tr><td colspan="10" class="loading-row">Нет групп</td></tr>';
            return;
        }
        groupsTbody.innerHTML = groups.map(group => `
            <tr>
                <td>${group.id}</td>
                <td><strong>${escapeHtml(group.name)}</strong></td>
                <td>${escapeHtml(String(group.groupSize))}</td>
                <td><span class="badge badge-ef">${escapeHtml(group.educationFormName)}</span></td>
                <td>${escapeHtml(departmentLabel(group.departmentId))}</td>
                <td>${group.course || '-'}</td>
                <td>${escapeHtml(specialityLabel(group.specialtyId || group.specialityCode))}</td>
                <td>${escapeHtml(group.specialtyProfileName || '-')}</td>
                <td><span class="badge ${statusBadgeClass(group)}">${escapeHtml(statusLabel(group))}</span></td>
                <td class="group-actions-cell">
                    <div class="group-actions">
                        <button class="btn btn-sm btn-secondary btn-edit-group group-action-btn" data-id="${group.id}">Изменить</button>
                        <button class="btn btn-sm btn-secondary btn-manage-subgroups group-action-btn" data-id="${group.id}">Подгруппы</button>
                        <button class="btn btn-sm btn-secondary btn-manage-calendar group-action-btn" data-id="${group.id}">Календарь</button>
                        ${group.status === 'ARCHIVED'
                            ? `<button class="btn-restore-group group-action-btn" data-id="${group.id}">Восстановить</button>`
                            : `<button class="btn btn-sm btn-danger-subtle btn-archive-group group-action-btn" data-id="${group.id}">Архив</button>`}
                    </div>
                </td>
            </tr>
        `).join('');
    }

    function populateEfSelects(forms) {
        populateEfSelect(newGroupEfSelect, forms);
        populateEfSelect(editGroupEfSelect, forms);
        renderFilterEfCheckboxes(forms);
    }

    function renderFilterEfCheckboxes(forms) {
        const selectedIds = new Set(selectedFilterEducationFormIds());
        const allChecked = !selectedIds.size;
        filterEfCheckboxes.innerHTML = `
            <label class="checkbox-item">
                <input type="checkbox" value="all" ${allChecked ? 'checked' : ''}>
                <span class="checkmark"></span>
                <span>Все</span>
            </label>
            ${forms.map(form => {
                const id = String(form.id);
                return `
                    <label class="checkbox-item">
                        <input type="checkbox" value="${escapeHtml(id)}" ${selectedIds.has(id) ? 'checked' : ''}>
                        <span class="checkmark"></span>
                        <span>${escapeHtml(form.name)}</span>
                    </label>
                `;
            }).join('')}
        `;
        updateFilterEfText();
    }

    function populateEfSelect(select, forms) {
        const currentVal = select.value;
        select.innerHTML = forms.map(form => `<option value="${form.id}">${escapeHtml(form.name)}</option>`).join('');
        if (currentVal && forms.find(form => form.id == currentVal)) {
            select.value = currentVal;
        }
        syncSelects(select);
    }

    function populateDepartmentSelects(items) {
        populateDepartmentSelect(newGroupDepartmentSelect, items);
        populateDepartmentSelect(editGroupDepartmentSelect, items);
    }

    function populateDepartmentSelect(select, items) {
        const currentVal = select.value;
        select.innerHTML = '<option value="">Выберите кафедру</option>' +
            items.map(department => {
                const name = department.departmentName || department.name || 'Без названия';
                const code = department.departmentCode || department.code || department.id;
                return `<option value="${department.id}">${escapeHtml(name)} (${escapeHtml(String(code))})</option>`;
            }).join('');
        if (currentVal && items.find(department => department.id == currentVal)) {
            select.value = currentVal;
        }
        syncSelects(select);
    }

    function populateSpecialitySelects(items) {
        populateSpecialitySelect(newGroupSpecialitySelect, items);
        populateSpecialitySelect(editGroupSpecialitySelect, items);
        populateProfileSelect(newGroupProfileSelect, newGroupSpecialitySelect.value);
        populateProfileSelect(editGroupProfileSelect, editGroupSpecialitySelect.value);
    }

    function populateSpecialitySelect(select, items) {
        const currentVal = select.value;
        select.innerHTML = '<option value="">Выберите специальность</option>' +
            items.map(speciality => `<option value="${speciality.id}">${escapeHtml(specialityLabel(speciality.id))}</option>`).join('');
        if (currentVal && items.find(speciality => speciality.id == currentVal)) {
            select.value = currentVal;
        }
        syncSelects(select);
    }

    function populateProfileSelect(select, specialtyId, selectedProfileId = null) {
        const profiles = profilesBySpecialty.get(String(specialtyId)) || [];
        select.innerHTML = profiles.length
            ? '<option value="">Выберите профиль</option>' + profiles.map(profile =>
                `<option value="${profile.id}">${escapeHtml(profile.name)}</option>`
            ).join('')
            : '<option value="">Нет профилей</option>';
        if (selectedProfileId && profiles.some(profile => String(profile.id) === String(selectedProfileId))) {
            select.value = selectedProfileId;
        }
        syncSelects(select);
    }

    function populateYearSelect() {
        manageCalendarYearSelect.innerHTML = '<option value="">Выберите учебный год</option>' +
            academicYears.map(year => `<option value="${year.id}">${escapeHtml(year.title)}</option>`).join('');
        if (academicYears.length) {
            manageCalendarYearSelect.value = String(academicYears[0].id);
        }
        syncSelects(manageCalendarYearSelect);
    }

    function populateCalendarSelect() {
        const groupId = manageCalendarGroupIdInput.value;
        const group = allGroups.find(g => g.id == groupId);
        const yearId = manageCalendarYearSelect.value;
        const matching = group && yearId
            ? calendars.filter(calendar =>
                String(calendar.academicYearId) === String(yearId)
                && String(calendar.specialtyId) === String(group.specialtyId || group.specialityCode)
                && String(calendar.specialtyProfileId) === String(group.specialtyProfileId)
                && String(calendar.studyFormId) === String(group.educationFormId)
            )
            : [];
        manageCalendarSelect.innerHTML = matching.length
            ? '<option value="">Выберите график</option>' + matching.map(calendar =>
                `<option value="${calendar.id}">${escapeHtml(buildAcademicCalendarTitle(calendar) || '-')}</option>`
            ).join('')
            : '<option value="">Нет подходящих графиков</option>';
        syncSelects(manageCalendarSelect);
    }

    async function createGroup(event) {
        event.preventDefault();
        hideAlert('create-group-alert');
        const payload = readGroupPayload('new');
        if (!payload) return;

        try {
            const data = await api.post('/api/groups', payload);
            showAlert('create-group-alert', `Группа "${escapeHtml(data.name || payload.name)}" создана`, 'success');
            createGroupForm.reset();
            syncSelects(newGroupEfSelect, newGroupDepartmentSelect, newGroupSpecialitySelect, newGroupProfileSelect);
            await loadGroups();
        } catch (error) {
            showAlert('create-group-alert', error.message || 'Ошибка создания', 'error');
        }
    }

    async function updateGroup(event) {
        event.preventDefault();
        hideAlert('edit-group-alert');
        const id = document.getElementById('edit-group-id').value;
        const payload = readGroupPayload('edit');
        if (!payload) return;

        try {
            const data = await api.put('/api/groups/' + id, payload);
            modalEditGroup.classList.remove('open');
            showAlert('create-group-alert', `Группа "${escapeHtml(data.name || payload.name)}" обновлена`, 'success');
            await loadGroups();
        } catch (error) {
            showAlert('edit-group-alert', error.message || 'Ошибка обновления', 'error');
        }
    }

    function readGroupPayload(prefix) {
        const isEdit = prefix === 'edit';
        const alertId = isEdit ? 'edit-group-alert' : 'create-group-alert';
        const name = document.getElementById(`${prefix}-group-name`).value.trim();
        const groupSize = document.getElementById(`${prefix}-group-size`).value;
        const educationFormId = (isEdit ? editGroupEfSelect : newGroupEfSelect).value;
        const departmentId = (isEdit ? editGroupDepartmentSelect : newGroupDepartmentSelect).value;
        const yearStartStudy = document.getElementById(`${prefix}-group-yearStartStudy`).value;
        const specialtyId = (isEdit ? editGroupSpecialitySelect : newGroupSpecialitySelect).value;
        const specialtyProfileId = (isEdit ? editGroupProfileSelect : newGroupProfileSelect).value;

        if (!name) { showAlert(alertId, 'Введите название группы', 'error'); return null; }
        if (!groupSize) { showAlert(alertId, 'Введите размер группы', 'error'); return null; }
        if (!educationFormId) { showAlert(alertId, 'Выберите форму обучения', 'error'); return null; }
        if (!departmentId) { showAlert(alertId, 'Выберите кафедру', 'error'); return null; }
        if (!yearStartStudy) { showAlert(alertId, 'Введите год начала обучения', 'error'); return null; }
        if (!specialtyId) { showAlert(alertId, 'Выберите специальность', 'error'); return null; }
        if (!specialtyProfileId) { showAlert(alertId, 'Выберите профиль обучения', 'error'); return null; }

        return {
            name,
            groupSize: Number(groupSize),
            educationFormId: Number(educationFormId),
            departmentId: Number(departmentId),
            yearStartStudy: Number(yearStartStudy),
            specialtyId: Number(specialtyId),
            specialtyProfileId: Number(specialtyProfileId)
        };
    }

    async function handleGroupTableClick(event) {
        const btnDelete = event.target.closest('.btn-archive-group');
        const btnEdit = event.target.closest('.btn-edit-group');
        const btnRestore = event.target.closest('.btn-restore-group');
        const btnSubgroups = event.target.closest('.btn-manage-subgroups');
        const btnCalendar = event.target.closest('.btn-manage-calendar');

        if (btnDelete) {
            if (!confirm('Архивировать группу? История расписания сохранится.')) return;
            try {
                await api.delete('/api/groups/' + btnDelete.dataset.id);
                await loadGroups();
            } catch (error) {
                alert(error.message || 'Ошибка архивирования');
            }
        }

        if (btnRestore) {
            try {
                await api.post('/api/groups/' + btnRestore.dataset.id + '/restore', {});
                await loadGroups();
            } catch (error) {
                alert(error.message || 'Ошибка восстановления');
            }
        }

        if (btnEdit) {
            openEditGroupModal(btnEdit.dataset.id);
        }

        if (btnSubgroups) {
            const groupId = btnSubgroups.dataset.id;
            const group = allGroups.find(g => g.id == groupId);
            if (group) openSubgroupsModal(group);
        }

        if (btnCalendar) {
            const groupId = btnCalendar.dataset.id;
            const group = allGroups.find(g => g.id == groupId);
            if (group) openCalendarModal(group);
        }
    }

    function openEditGroupModal(id) {
        const group = allGroups.find(item => item.id == id);
        if (!group) {
            alert('Группа не найдена');
            return;
        }

        document.getElementById('edit-group-id').value = group.id;
        document.getElementById('edit-group-name').value = group.name || '';
        document.getElementById('edit-group-size').value = group.groupSize || '';
        editGroupEfSelect.value = group.educationFormId || '';
        editGroupDepartmentSelect.value = group.departmentId || '';
        document.getElementById('edit-group-yearStartStudy').value = group.yearStartStudy || '';
        editGroupSpecialitySelect.value = group.specialtyId || group.specialityCode || '';
        populateProfileSelect(editGroupProfileSelect, editGroupSpecialitySelect.value, group.specialtyProfileId);
        syncSelects(editGroupEfSelect, editGroupDepartmentSelect, editGroupSpecialitySelect, editGroupProfileSelect);
        hideAlert('edit-group-alert');
        modalEditGroup.classList.add('open');
    }

    // --- Управление подгруппами ---
    function openSubgroupsModal(group) {
        activeSubgroupGroup = group;
        subgroupsGroupContext.textContent = `Группа: ${group.name} (${group.groupSize} чел.)`;
        manageSubgroupGroupIdInput.value = group.id;
        resetSubgroupForm();
        modalManageSubgroups.classList.add('open');
        renderSubgroupsList(group.id);
    }

    function renderSubgroupsList(groupId) {
        const list = subgroups.filter(sub => String(sub.groupId) === String(groupId));
        if (!list.length) {
            manageSubgroupsTbody.innerHTML = '<tr><td colspan="3" class="loading-row">Подгруппы не созданы</td></tr>';
            return;
        }
        const canDeleteSingleSubgroup = list.length === 1;
        const deleteTitle = canDeleteSingleSubgroup
            ? 'Удалить подгруппу'
            : 'Чтобы изменить количество подгрупп, выберите нужный режим выше и нажмите «Применить»';
        manageSubgroupsTbody.innerHTML = list.map(sub => `
            <tr>
                <td>${escapeHtml(sub.name)}</td>
                <td>${escapeHtml(String(sub.studentCapacity ?? '-'))} чел.</td>
                <td>
                    <button class="btn btn-sm btn-secondary btn-edit-subgroup" data-id="${sub.id}">Изменить</button>
                    <button class="btn btn-sm btn-danger btn-delete-subgroup" data-id="${sub.id}"
                        ${canDeleteSingleSubgroup ? '' : 'disabled'}
                        title="${escapeHtml(deleteTitle)}">${canDeleteSingleSubgroup ? 'Удалить' : 'Изменить выше'}</button>
                </td>
            </tr>
        `).join('');
    }

    function resetSubgroupForm() {
        manageSubgroupIdInput.value = '';
        const current = currentGroupSubgroups(manageSubgroupGroupIdInput.value);
        const count = [2, 3].includes(current.length) ? current.length : 0;
        manageSubgroupCountSelect.value = String(count);
        syncSelects(manageSubgroupCountSelect);
        renderSubgroupCapacityFields(count, current.map(item => item.studentCapacity));
        subgroupFormTitle.textContent = 'Настройка подгрупп';
        btnSaveSubgroup.textContent = 'Применить';
        btnCancelSubgroupEdit.hidden = true;
        hideAlert('manage-subgroup-alert');
    }

    function currentGroupSubgroups(groupId) {
        return subgroups
            .filter(sub => String(sub.groupId) === String(groupId))
            .sort((left, right) => naturalSubgroupOrder(left.name).localeCompare(naturalSubgroupOrder(right.name), 'ru'));
    }

    function naturalSubgroupOrder(name) {
        const number = String(name || '').match(/\d+/)?.[0];
        return number ? String(number).padStart(3, '0') : String(name || '');
    }

    function renderSubgroupCapacityFields(count, capacities = []) {
        manageSubgroupCapacities.className = `subgroup-capacity-fields subgroup-capacity-fields-${count}`;
        if (!count) {
            manageSubgroupCapacities.innerHTML = '';
            return;
        }

        const groupSize = Number(activeSubgroupGroup?.groupSize || 0);
        const suggested = suggestedSubgroupCapacities(groupSize, count);
        manageSubgroupCapacities.innerHTML = Array.from({ length: count }, (_, index) => {
            const value = capacities[index] ?? suggested[index] ?? '';
            return `
                <div class="form-group subgroup-capacity-field">
                    <label for="manage-subgroup-capacity-${index + 1}">Численность ${index + 1}</label>
                    <input type="number" id="manage-subgroup-capacity-${index + 1}" class="manage-subgroup-capacity"
                        min="1" max="${groupSize || ''}" value="${escapeHtml(String(value))}" required>
                </div>
            `;
        }).join('');
    }

    function suggestedSubgroupCapacities(groupSize, count) {
        if (!groupSize || !count) return [];
        const base = Math.floor(groupSize / count);
        const remainder = groupSize % count;
        return Array.from({ length: count }, (_, index) => base + (index < remainder ? 1 : 0));
    }

    async function saveSubgroup(event) {
        event.preventDefault();
        hideAlert('manage-subgroup-alert');
        const groupId = manageSubgroupGroupIdInput.value;
        const group = activeSubgroupGroup || allGroups.find(item => String(item.id) === String(groupId));
        const count = Number(manageSubgroupCountSelect.value);
        const existingSubgroups = currentGroupSubgroups(groupId);

        if (!group) {
            showAlert('manage-subgroup-alert', 'Группа не найдена', 'error');
            return;
        }

        if (count === 0) {
            await applyNoSubgroups(groupId, existingSubgroups);
            return;
        }

        const capacities = Array.from(manageSubgroupCapacities.querySelectorAll('.manage-subgroup-capacity'))
            .map(input => Number(input.value));
        const validationError = validateSubgroupCapacities(capacities, Number(group.groupSize), count);
        if (validationError) {
            showAlert('manage-subgroup-alert', validationError, 'error');
            return;
        }

        try {
            await syncSubgroups(groupId, existingSubgroups, capacities);
            showAlert('manage-subgroup-alert', 'Подгруппы сохранены', 'success');
            await loadSubgroups();
            resetSubgroupForm();
            renderSubgroupsList(groupId);
        } catch (error) {
            showAlert('manage-subgroup-alert', error.message || 'Ошибка сохранения подгруппы', 'error');
        }
    }

    function validateSubgroupCapacities(capacities, groupSize, count) {
        if (capacities.length !== count || capacities.some(value => !Number.isInteger(value) || value <= 0)) {
            return 'Укажите положительную численность для каждой подгруппы';
        }

        const total = capacities.reduce((sum, value) => sum + value, 0);
        if (total !== groupSize) {
            return `Сумма численностей подгрупп должна быть равна численности группы (${groupSize} чел.)`;
        }

        return null;
    }

    async function applyNoSubgroups(groupId, existingSubgroups) {
        try {
            for (const subgroup of existingSubgroups) {
                await api.delete(`/api/groups/${groupId}/subgroups/${subgroup.id}`);
            }
            showAlert('manage-subgroup-alert', 'Деление на подгруппы отключено', 'success');
            await loadSubgroups();
            resetSubgroupForm();
            renderSubgroupsList(groupId);
        } catch (error) {
            showAlert('manage-subgroup-alert', error.message || 'Ошибка отключения подгрупп', 'error');
        }
    }

    async function syncSubgroups(groupId, existingSubgroups, capacities) {
        const targetCount = capacities.length;
        const extraSubgroups = existingSubgroups.slice(targetCount);
        for (const subgroup of extraSubgroups) {
            await api.delete(`/api/groups/${groupId}/subgroups/${subgroup.id}`);
        }

        const updates = [];
        const creates = [];
        for (let index = 0; index < targetCount; index += 1) {
            const payload = {
                name: `Подгруппа ${index + 1}`,
                studentCapacity: capacities[index]
            };
            const existing = existingSubgroups[index];
            if (existing) {
                updates.push({ existing, payload });
            } else {
                creates.push(payload);
            }
        }

        updates.sort((left, right) => {
            const leftIncreases = left.payload.studentCapacity > Number(left.existing.studentCapacity || 0);
            const rightIncreases = right.payload.studentCapacity > Number(right.existing.studentCapacity || 0);
            return Number(leftIncreases) - Number(rightIncreases);
        });

        for (const update of updates) {
            await api.put(`/api/groups/${groupId}/subgroups/${update.existing.id}`, update.payload);
        }

        for (const payload of creates) {
            await api.post(`/api/groups/${groupId}/subgroups`, payload);
        }
    }

    async function handleSubgroupTableClick(event) {
        const editButton = event.target.closest('.btn-edit-subgroup');
        const deleteButton = event.target.closest('.btn-delete-subgroup');
        const groupId = manageSubgroupGroupIdInput.value;

        if (editButton) {
            const subgroup = subgroups.find(item => item.id == editButton.dataset.id);
            if (!subgroup) return;

            resetSubgroupForm();
            const inputIndex = currentGroupSubgroups(groupId).findIndex(item => item.id === subgroup.id);
            const input = manageSubgroupCapacities.querySelectorAll('.manage-subgroup-capacity')[inputIndex];
            input?.focus();
            hideAlert('manage-subgroup-alert');
            return;
        }

        if (deleteButton) {
            if (deleteButton.disabled) {
                showAlert('manage-subgroup-alert', 'Чтобы изменить количество подгрупп, выберите нужный режим выше и нажмите «Применить»', 'error');
                return;
            }
            if (!confirm('Удалить подгруппу?')) return;
            try {
                await api.delete(`/api/groups/${groupId}/subgroups/${deleteButton.dataset.id}`);
                showAlert('manage-subgroup-alert', 'Подгруппа удалена', 'success');
                resetSubgroupForm();
                await loadSubgroups();
                renderSubgroupsList(groupId);
            } catch (error) {
                showAlert('manage-subgroup-alert', error.message || 'Ошибка удаления подгруппы', 'error');
            }
        }
    }

    // --- Управление календарными графиками ---
    async function openCalendarModal(group) {
        calendarGroupContext.textContent = `Группа: ${group.name} (${specialityLabel(group.specialtyId || group.specialityCode)})`;
        manageCalendarGroupIdInput.value = group.id;
        hideAlert('manage-calendar-alert');
        populateCalendarSelect();
        modalManageCalendar.classList.add('open');
        await loadAssignmentsList(group.id);
    }

    async function loadAssignmentsList(groupId) {
        manageCalendarTbody.innerHTML = '<tr><td colspan="4" class="loading-row">Загрузка...</td></tr>';
        try {
            currentAssignments = await api.get(`/api/groups/${groupId}/calendar-assignments`);
            renderAssignmentsList();
        } catch (error) {
            manageCalendarTbody.innerHTML = `<tr><td colspan="4" class="loading-row">Ошибка: ${escapeHtml(error.message)}</td></tr>`;
        }
    }

    function renderAssignmentsList() {
        if (!currentAssignments.length) {
            manageCalendarTbody.innerHTML = '<tr><td colspan="4" class="loading-row">Календарные графики не назначены</td></tr>';
            return;
        }
        manageCalendarTbody.innerHTML = currentAssignments.map(assignment => `
            <tr>
                <td>${escapeHtml(assignment.academicYearTitle)}</td>
                <td>${escapeHtml(assignmentCalendarTitle(assignment))}</td>
                <td>${renderAssignmentSubjects(assignment.subjects || [])}</td>
                <td>
                    <button class="btn btn-sm btn-danger btn-delete-assignment" data-id="${assignment.id}">Удалить</button>
                </td>
            </tr>
        `).join('');
    }

    function assignmentCalendarTitle(assignment) {
        const calendar = calendars.find(item =>
            String(item.id) === String(assignment.calendarId)
        );
        return buildAcademicCalendarTitle(calendar) || assignment.calendarTitle || '-';
    }

    function renderAssignmentSubjects(subjects) {
        if (!subjects.length) {
            return '<span class="muted">Не привязаны</span>';
        }
        const grouped = subjects.reduce((acc, subject) => {
            const key = String(subject.semesterNumber || '-');
            if (!acc.has(key)) acc.set(key, []);
            acc.get(key).push(subject);
            return acc;
        }, new Map());
        return `<div class="assignment-subjects">${Array.from(grouped.entries())
            .sort(([a], [b]) => Number(a) - Number(b))
            .map(([semesterNumber, items]) => `
                <div class="assignment-subject-semester">
                    <strong>${escapeHtml(semesterNumber)} семестр</strong>
                    <span>${items.map(subject => escapeHtml(subjectLabel(subject))).join(', ')}</span>
                </div>
            `).join('')}</div>`;
    }

    async function saveAssignment(event) {
        event.preventDefault();
        hideAlert('manage-calendar-alert');
        const groupId = manageCalendarGroupIdInput.value;
        const academicYearId = manageCalendarYearSelect.value;
        const calendarId = manageCalendarSelect.value;

        if (!academicYearId || !calendarId) {
            showAlert('manage-calendar-alert', 'Выберите учебный год и график', 'error');
            return;
        }

        try {
            await api.put(`/api/groups/${groupId}/calendar-assignments`, {
                academicYearId: Number(academicYearId),
                calendarId: Number(calendarId)
            });
            showAlert('manage-calendar-alert', 'Календарный график назначен', 'success');
            await loadAssignmentsList(groupId);
        } catch (error) {
            showAlert('manage-calendar-alert', error.message || 'Ошибка назначения графика', 'error');
        }
    }

    manageCalendarTbody.addEventListener('click', async (event) => {
        const deleteButton = event.target.closest('.btn-delete-assignment');
        if (!deleteButton) return;
        if (!confirm('Удалить назначение графика?')) return;
        const groupId = manageCalendarGroupIdInput.value;

        try {
            await api.delete(`/api/groups/${groupId}/calendar-assignments/${deleteButton.dataset.id}`);
            showAlert('manage-calendar-alert', 'Назначение удалено', 'success');
            await loadAssignmentsList(groupId);
        } catch (error) {
            showAlert('manage-calendar-alert', error.message || 'Ошибка удаления назначения', 'error');
        }
    });


    // --- Вспомогательные функции ---
    function departmentLabel(departmentId) {
        const department = departments.find(item => item.id == departmentId);
        if (!department) return departmentId || '-';
        return department.departmentName || department.name || departmentId;
    }

    function specialityLabel(specialityId) {
        const speciality = specialties.find(item => item.id == specialityId);
        if (!speciality) return specialityId || '-';
        const code = speciality.specialityCode || speciality.specialtyCode || speciality.specialty_code || speciality.id;
        const name = speciality.specialityName || speciality.name || '';
        return name ? `${code} — ${name}` : code;
    }

    function subjectLabel(subject) {
        const code = subject.subjectCode ? `${subject.subjectCode} · ` : '';
        return `${code}${subject.subjectName || subject.subjectId || 'Без названия'}`;
    }

    function statusLabel(group) {
        if (group.status === 'ARCHIVED') return 'Архив';
        return group.studyStateName || (group.active ? 'Активна' : 'Неактивна');
    }

    function statusBadgeClass(group) {
        if (group.status === 'ARCHIVED' || group.studyState === 'GRADUATED' || group.studyState === 'INACTIVE') {
            return 'badge-unavailable';
        }
        if (group.studyState === 'NOT_STARTED') {
            return 'badge-ef';
        }
        return 'badge-available';
    }

    function syncSelects(...selects) {
        selects.filter(Boolean).forEach(select => {
            select.dispatchEvent(new Event('change', { bubbles: true }));
        });
    }
}
