import { api, getSession } from '../api.js';
import { escapeHtml, formatLocalDate, showAlert, hideAlert } from '../utils.js';

const ROLE_DEPARTMENT = 'DEPARTMENT';

export async function initDepartmentWorkspace() {
    const session = getSession();
    const role = session?.role;
    const userDepartmentId = session?.departmentId;
    const departmentField = document.getElementById('department-workspace-department-field');
    const departmentSelect = document.getElementById('department-workspace-department');
    const startInput = document.getElementById('department-workspace-start');
    const endInput = document.getElementById('department-workspace-end');
    const refreshButton = document.getElementById('department-workspace-refresh');
    const importForm = document.getElementById('department-subject-import-form');
    const importRowsContainer = document.getElementById('subject-import-rows');
    const importAddButton = document.getElementById('subject-import-add');
    const assignTeacherForm = document.getElementById('department-teacher-assign-form');
    const assignTeacherSelect = document.getElementById('department-teacher-select');
    const assignTeacherComment = document.getElementById('department-teacher-assign-comment');
    const teacherRequestForm = document.getElementById('department-teacher-request-form');
    const teacherRequestsTbody = document.getElementById('department-teacher-requests-tbody');
    const teacherRequestCount = document.getElementById('department-teacher-request-count');
    const subjectsTbody = document.getElementById('department-subjects-tbody');
    const subjectCount = document.getElementById('department-subject-count');
    const commentsCard = document.getElementById('department-comments-card');
    const commentsTitle = document.getElementById('department-comments-title');
    const commentsList = document.getElementById('department-comment-list');
    const commentsForm = document.getElementById('department-comment-form');
    const commentsSubjectInput = document.getElementById('department-comment-subject-id');
    const commentsTextInput = document.getElementById('department-comment-text');
    const commentsCloseButton = document.getElementById('department-comments-close');
    let lastTeachers = null;
    let lastWorkload = null;
    let allTeachers = [];
    let teacherRequests = null;
    let teachersErrorMessage = '';
    let workloadErrorMessage = '';

    setDefaultDates(startInput, endInput);
    refreshButton?.addEventListener('click', loadWorkspace);
    departmentSelect?.addEventListener('change', loadWorkspace);
    startInput?.addEventListener('change', handleStartDateChange);
    endInput?.addEventListener('change', loadWorkload);
    importForm?.addEventListener('submit', importSubjects);
    assignTeacherForm?.addEventListener('submit', assignTeacherToDepartment);
    teacherRequestForm?.addEventListener('submit', submitTeacherRequest);
    importAddButton?.addEventListener('click', () => renderImportRows([...readImportRows(), { code: '', name: '' }]));
    importRowsContainer?.addEventListener('click', (event) => {
        const removeBtn = event.target.closest('.subject-import-remove');
        if (removeBtn) {
            const rows = readImportRows();
            rows.splice(Number(removeBtn.dataset.index), 1);
            renderImportRows(rows.length ? rows : [{ code: '', name: '' }]);
        }
    });
    commentsForm?.addEventListener('submit', saveComment);
    commentsCloseButton?.addEventListener('click', () => {
        commentsCard.hidden = true;
        commentsSubjectInput.value = '';
    });
    subjectsTbody?.addEventListener('click', event => {
        const button = event.target.closest('.department-comments-open');
        if (button) {
            openComments(button.dataset.subjectId, button.dataset.subjectName);
        }
    });

    try {
        await loadDepartments(role, userDepartmentId);
        if (role === ROLE_DEPARTMENT) {
            departmentField.hidden = true;
            departmentSelect.value = userDepartmentId || '';
        }
        await loadAllTeachers();
        renderImportRows([{ code: '', name: '' }]);
        await loadWorkspace();
    } catch (error) {
        showAlert('department-workspace-alert', error.message || 'Ошибка загрузки кабинета кафедры', 'error');
    }

    async function loadWorkspace() {
        hideAlert('department-workspace-alert');
        lastTeachers = null;
        lastWorkload = null;
        teachersErrorMessage = '';
        workloadErrorMessage = '';
        renderTeachers();
        teacherRequests = null;
        renderTeacherRequests();
        await Promise.all([loadSubjects(), loadTeachers(), loadWorkload(), loadTeacherRequests()]);
    }

    async function loadSubjects() {
        const departmentId = selectedDepartmentId();
        subjectsTbody.innerHTML = '<tr><td colspan="4" class="loading-row">Загрузка...</td></tr>';
        subjectCount.textContent = 'Загрузка...';
        try {
            const subjects = await api.get(`/api/department/subjects?departmentId=${encodeURIComponent(departmentId || '')}`);
            subjectCount.textContent = subjectCountLabel(subjects.length);
            if (!subjects.length) {
                subjectsTbody.innerHTML = '<tr><td colspan="4" class="loading-row">Дисциплины не найдены</td></tr>';
                return;
            }
            subjectsTbody.innerHTML = subjects.map(subject => `
                <tr>
                    <td>${escapeHtml(subject.code || '-')}</td>
                    <td>${escapeHtml(subject.name || '-')}</td>
                    <td>${escapeHtml(subject.description || '-')}</td>
                    <td>
                        <button type="button" class="btn btn-sm btn-secondary department-comments-open"
                                data-subject-id="${escapeHtml(subject.id)}"
                                data-subject-name="${escapeHtml(subject.name || '')}">
                            Открыть
                        </button>
                    </td>
                </tr>
            `).join('');
        } catch (error) {
            subjectsTbody.innerHTML = `<tr><td colspan="4" class="loading-row">${escapeHtml(error.message || 'Ошибка загрузки дисциплин')}</td></tr>`;
            subjectCount.textContent = '0 дисциплин';
        }
    }

    function renderImportRows(rows) {
        if (!importRowsContainer) return;
        importRowsContainer.innerHTML = (rows || [{ code: '', name: '' }]).map((row, index) => `
            <div class="subject-import-row" data-index="${index}">
                <div class="form-group">
                    <label>Код</label>
                    <input type="text" class="subject-import-code" value="${escapeHtml(row.code || '')}" placeholder="DB201">
                </div>
                <div class="form-group">
                    <label>Название</label>
                    <input type="text" class="subject-import-name" value="${escapeHtml(row.name || '')}" placeholder="Базы данных">
                </div>
                <button type="button" class="btn btn-sm btn-danger subject-import-remove" data-index="${index}">Удалить</button>
            </div>
        `).join('');
    }

    function readImportRows() {
        if (!importRowsContainer) return [];
        return Array.from(importRowsContainer.querySelectorAll('.subject-import-row')).map(row => ({
            code: (row.querySelector('.subject-import-code')?.value || '').trim(),
            name: (row.querySelector('.subject-import-name')?.value || '').trim()
        }));
    }

    async function importSubjects(event) {
        event.preventDefault();
        const alertId = 'department-subject-import-alert';
        hideAlert(alertId);
        const departmentId = selectedDepartmentId();
        const rows = readImportRows()
            .filter(item => item.name)
            .map(item => ({
                code: item.code,
                name: item.name,
                departmentId: Number(departmentId)
            }));

        if (!departmentId) {
            showAlert(alertId, 'Выберите кафедру', 'error');
            return;
        }
        if (!rows.length) {
            showAlert(alertId, 'Заполните название хотя бы одной дисциплины', 'error');
            return;
        }

        try {
            const result = await api.post('/api/department/subjects/import', rows);
            showAlert(alertId, result.message || 'Дисциплины загружены', 'success');
            renderImportRows([{ code: '', name: '' }]);
            await loadSubjects();
        } catch (error) {
            showAlert(alertId, error.message || 'Ошибка загрузки дисциплин', 'error');
        }
    }

    async function assignTeacherToDepartment(event) {
        event.preventDefault();
        const alertId = 'department-teacher-assign-alert';
        hideAlert(alertId);
        const teacherId = assignTeacherSelect?.value;
        const departmentId = selectedDepartmentId();
        if (!departmentId) {
            showAlert(alertId, 'Выберите кафедру', 'error');
            return;
        }
        if (!teacherId) {
            showAlert(alertId, 'Выберите преподавателя', 'error');
            return;
        }

        try {
            await api.post(`/api/department/teachers/${encodeURIComponent(teacherId)}/assignments`, {
                departmentId: Number(departmentId),
                comment: assignTeacherComment?.value.trim() || null
            });
            showAlert(alertId, 'Преподаватель привязан к кафедре', 'success');
            if (assignTeacherComment) assignTeacherComment.value = '';
            await Promise.all([loadTeachers(), loadWorkload()]);
        } catch (error) {
            showAlert(alertId, error.message || 'Ошибка привязки преподавателя', 'error');
        }
    }

    async function submitTeacherRequest(event) {
        event.preventDefault();
        const alertId = 'department-teacher-request-alert';
        hideAlert(alertId);
        const departmentId = selectedDepartmentId();
        const username = document.getElementById('teacher-request-username')?.value.trim();
        const fullName = document.getElementById('teacher-request-fullname')?.value.trim();
        const jobTitle = document.getElementById('teacher-request-jobtitle')?.value.trim();
        const comment = document.getElementById('teacher-request-comment')?.value.trim();
        if (!departmentId) {
            showAlert(alertId, 'Выберите кафедру', 'error');
            return;
        }
        if (!username || !fullName) {
            showAlert(alertId, 'Заполните логин и ФИО преподавателя', 'error');
            return;
        }

        try {
            await api.post('/api/department/teacher-requests', {
                departmentId: Number(departmentId),
                username,
                fullName,
                jobTitle,
                comment
            });
            showAlert(alertId, 'Заявка отправлена администратору', 'success');
            teacherRequestForm.reset();
            await loadTeacherRequests();
        } catch (error) {
            showAlert(alertId, error.message || 'Ошибка отправки заявки', 'error');
        }
    }

    async function openComments(subjectId, subjectName) {
        commentsCard.hidden = false;
        commentsTitle.textContent = `Комментарии: ${subjectName || 'дисциплина'}`;
        commentsSubjectInput.value = subjectId;
        commentsTextInput.value = '';
        hideAlert('department-comment-alert');
        commentsList.textContent = 'Загрузка...';

        try {
            const comments = await api.get(`/api/department/subjects/${subjectId}/comments`);
            commentsList.innerHTML = comments.length
                ? comments.map(comment => `
                    <article class="department-comment-item">
                        <strong>${escapeHtml(comment.authorName || 'Автор не указан')}</strong>
                        <span>${escapeHtml(formatDateTime(comment.createdAt))}</span>
                        <p>${escapeHtml(comment.comment)}</p>
                    </article>
                `).join('')
                : '<div class="loading-row">Комментариев пока нет</div>';
        } catch (error) {
            commentsList.innerHTML = `<div class="loading-row">${escapeHtml(error.message || 'Ошибка загрузки комментариев')}</div>`;
        }
    }

    async function saveComment(event) {
        event.preventDefault();
        const subjectId = commentsSubjectInput.value;
        const comment = commentsTextInput.value.trim();
        if (!subjectId) {
            showAlert('department-comment-alert', 'Выберите дисциплину', 'error');
            return;
        }
        if (!comment) {
            showAlert('department-comment-alert', 'Комментарий не должен быть пустым', 'error');
            return;
        }

        try {
            await api.post(`/api/department/subjects/${subjectId}/comments`, { comment });
            showAlert('department-comment-alert', 'Комментарий сохранён', 'success');
            await openComments(subjectId, commentsTitle.textContent.replace('Комментарии: ', ''));
        } catch (error) {
            showAlert('department-comment-alert', error.message || 'Ошибка сохранения комментария', 'error');
        }
    }

    async function loadTeachers() {
        lastTeachers = null;
        teachersErrorMessage = '';
        renderTeachers();
        renderTeacherSelect();
        try {
            const teachers = await api.get(`/api/department/teachers?departmentId=${encodeURIComponent(selectedDepartmentId() || '')}`);
            lastTeachers = Array.isArray(teachers) ? teachers : [];
            renderTeachers();
            renderTeacherSelect();
        } catch (error) {
            lastTeachers = [];
            teachersErrorMessage = error.message || 'Ошибка загрузки преподавателей';
            renderTeachers();
            renderTeacherSelect();
        }
    }

    async function loadAllTeachers() {
        try {
            const teachers = await api.get('/api/users/teachers');
            allTeachers = Array.isArray(teachers) ? teachers : [];
            renderTeacherSelect();
        } catch (error) {
            allTeachers = [];
            if (assignTeacherSelect) {
                assignTeacherSelect.innerHTML = `<option value="">${escapeHtml(error.message || 'Ошибка загрузки преподавателей')}</option>`;
            }
        }
    }

    async function loadTeacherRequests() {
        teacherRequests = null;
        renderTeacherRequests();
        try {
            const requests = await api.get(`/api/department/teacher-requests?departmentId=${encodeURIComponent(selectedDepartmentId() || '')}`);
            teacherRequests = Array.isArray(requests) ? requests : [];
            renderTeacherRequests();
        } catch (error) {
            teacherRequests = [];
            if (teacherRequestsTbody) {
                teacherRequestsTbody.innerHTML = `<tr><td colspan="6" class="loading-row">${escapeHtml(error.message || 'Ошибка загрузки заявок')}</td></tr>`;
            }
            if (teacherRequestCount) teacherRequestCount.textContent = '0 заявок';
        }
    }

    async function loadWorkload() {
        if (!startInput.value || !endInput.value) {
            lastWorkload = [];
            workloadErrorMessage = 'Выберите начало и окончание периода';
            renderTeachers();
            return;
        }

        const params = new URLSearchParams({
            startDate: startInput.value,
            endDate: endInput.value
        });
        if (selectedDepartmentId()) {
            params.set('departmentId', selectedDepartmentId());
        }
        lastWorkload = null;
        workloadErrorMessage = '';
        renderTeachers();
        try {
            const workload = await api.get(`/api/workload/teachers?${params}`);
            lastWorkload = Array.isArray(workload) ? workload : [];
            renderTeachers();
        } catch (error) {
            lastWorkload = [];
            workloadErrorMessage = error.message || 'Ошибка расчёта нагрузки';
            renderTeachers();
        }
    }

    async function handleStartDateChange() {
        if (startInput.value && endInput.value && startInput.value > endInput.value) {
            endInput.value = '';
        }
        await loadWorkload();
    }

    function renderTeachers() {
        const container = document.getElementById('department-teachers-list');
        if (!container) return;

        if (lastTeachers === null || lastWorkload === null) {
            container.textContent = 'Загрузка...';
            return;
        }

        const teachers = Array.isArray(lastTeachers) ? lastTeachers : [];
        const workload = Array.isArray(lastWorkload) ? lastWorkload : [];
        const workloadByTeacher = new Map();
        const usedWorkloadKeys = new Set();

        workload
            .filter(item => item && (item.id || item.name))
            .forEach(item => {
                workloadKeys(item).forEach(key => {
                    if (!workloadByTeacher.has(key)) {
                        workloadByTeacher.set(key, item);
                    }
                });
            });

        const rows = teachers.map(teacher => {
            const workloadItem = workloadKeys(teacher)
                .map(key => workloadByTeacher.get(key))
                .find(Boolean);
            if (workloadItem) {
                workloadKeys(workloadItem).forEach(key => usedWorkloadKeys.add(key));
            }
            return renderTeacherMetric({
                name: teacher.fullName || teacher.username || '-',
                meta: teacher.jobTitle || 'Должность не указана',
                workload: workloadItem
            }, workloadErrorMessage);
        });

        workload
            .filter(item => item && (item.id || item.name))
            .filter(item => workloadKeys(item).every(key => !usedWorkloadKeys.has(key)))
            .forEach(item => {
                rows.push(renderTeacherMetric({
                    name: item.name || '-',
                    meta: 'Есть занятия в расписании кафедры',
                    workload: item
                }, workloadErrorMessage));
            });

        if (rows.length) {
            container.innerHTML = rows.join('');
            return;
        }

        container.innerHTML = `<div class="loading-row">${escapeHtml(teachersErrorMessage || 'Преподаватели не найдены')}</div>`;
    }

    function renderTeacherSelect() {
        if (!assignTeacherSelect) return;
        if (lastTeachers === null) {
            assignTeacherSelect.innerHTML = '<option value="">Загрузка...</option>';
            return;
        }
        const assignedIds = new Set((lastTeachers || []).map(teacher => String(teacher.id)));
        const availableTeachers = allTeachers.filter(teacher => !assignedIds.has(String(teacher.id)));
        assignTeacherSelect.innerHTML = '<option value="">Выберите преподавателя</option>' +
            availableTeachers.map(teacher => `
                <option value="${escapeHtml(teacher.id)}">
                    ${escapeHtml(teacher.fullName || teacher.username || `ID ${teacher.id}`)}
                </option>
            `).join('');
        if (!availableTeachers.length) {
            assignTeacherSelect.innerHTML = '<option value="">Нет доступных преподавателей</option>';
        }
    }

    function renderTeacherRequests() {
        if (!teacherRequestsTbody) return;
        if (teacherRequests === null) {
            teacherRequestsTbody.innerHTML = '<tr><td colspan="6" class="loading-row">Загрузка...</td></tr>';
            if (teacherRequestCount) teacherRequestCount.textContent = 'Загрузка...';
            return;
        }
        if (teacherRequestCount) teacherRequestCount.textContent = requestCountLabel(teacherRequests.length);
        if (!teacherRequests.length) {
            teacherRequestsTbody.innerHTML = '<tr><td colspan="6" class="loading-row">Заявок пока нет</td></tr>';
            return;
        }
        teacherRequestsTbody.innerHTML = teacherRequests.map(request => `
            <tr>
                <td><span class="badge ${requestStatusClass(request.status)}">${escapeHtml(requestStatusLabel(request.status))}</span></td>
                <td>${escapeHtml(request.username || '-')}</td>
                <td>${escapeHtml(request.fullName || '-')}</td>
                <td>${escapeHtml(request.jobTitle || '-')}</td>
                <td>${escapeHtml(request.comment || '-')}</td>
                <td>${escapeHtml(request.reviewComment || formatDateTime(request.reviewedAt) || '-')}</td>
            </tr>
        `).join('');
    }

    function selectedDepartmentId() {
        return role === ROLE_DEPARTMENT ? userDepartmentId : departmentSelect.value;
    }
}

async function loadDepartments(role, userDepartmentId) {
    const departments = await api.get('/api/departments');
    fillSelect('department-workspace-department', departments, item => item.id, item => item.departmentName, 'Выберите кафедру');
    if (role === ROLE_DEPARTMENT && userDepartmentId) {
        document.getElementById('department-workspace-department').value = userDepartmentId;
    } else if (!document.getElementById('department-workspace-department').value && departments.length) {
        document.getElementById('department-workspace-department').value = departments[0].id;
    }
}

function fillSelect(id, items, valueFn, labelFn, emptyLabel) {
    const select = document.getElementById(id);
    if (!select) return;
    select.innerHTML = `<option value="">${escapeHtml(emptyLabel)}</option>` +
        (items || []).map(item => `<option value="${escapeHtml(valueFn(item))}">${escapeHtml(labelFn(item))}</option>`).join('');
}

function setDefaultDates(startInput, endInput) {
    const today = new Date();
    const nextWeek = new Date(today);
    nextWeek.setDate(today.getDate() + 7);
    startInput.value = formatLocalDate(today);
    endInput.value = formatLocalDate(nextWeek);
}

function formatDateTime(value) {
    if (!value) return '-';
    return String(value).replace('T', ' ').slice(0, 16);
}

function subjectCountLabel(count) {
    const tail = count % 100;
    if (tail >= 11 && tail <= 14) return `${count} дисциплин`;
    if (count % 10 === 1) return `${count} дисциплина`;
    if ([2, 3, 4].includes(count % 10)) return `${count} дисциплины`;
    return `${count} дисциплин`;
}

function requestCountLabel(count) {
    const tail = count % 100;
    if (tail >= 11 && tail <= 14) return `${count} заявок`;
    if (count % 10 === 1) return `${count} заявка`;
    if ([2, 3, 4].includes(count % 10)) return `${count} заявки`;
    return `${count} заявок`;
}

function requestStatusLabel(status) {
    return {
        PENDING: 'На рассмотрении',
        APPROVED: 'Одобрена',
        REJECTED: 'Отклонена'
    }[status] || status || '-';
}

function requestStatusClass(status) {
    return {
        PENDING: 'badge-ef',
        APPROVED: 'badge-student',
        REJECTED: 'badge-admin'
    }[status] || 'badge-ef';
}

function renderTeacherMetric(item, workloadErrorMessage) {
    return `
        <article class="metric-card">
            <strong>${escapeHtml(item.name || '-')}</strong>
            <span>${escapeHtml(item.meta || 'Должность не указана')}</span>
            <small>${escapeHtml(workloadLabel(item.workload, workloadErrorMessage))}</small>
        </article>
    `;
}

function workloadLabel(item, workloadErrorMessage) {
    if (workloadErrorMessage) {
        return workloadErrorMessage;
    }
    if (!item) {
        return '0 ак. ч., 0 занятий за период';
    }
    const hours = String(item.academicHours ?? 0);
    const lessons = String(item.lessonCount ?? 0);
    return `${hours} ак. ч., ${lessons} занятий за период`;
}

function workloadKeys(item) {
    return [
        item.id == null ? null : `id:${item.id}`,
        normalizeTeacherName(item.fullName || item.name || item.username)
    ].filter(Boolean);
}

function normalizeTeacherName(value) {
    return value ? `name:${String(value).trim().toLowerCase()}` : null;
}
