import {
    clearAuthState,
    fetchWithAuth,
    logoutSession,
    restoreSession
} from '../auth-session.js';

(async () => {
    const session = await restoreSession();
    if (!session || session.role !== 'TEACHER') {
        window.location.replace('/');
        return;
    }
    const teacherId = session.userId;
    const grid = document.getElementById('schedule-grid');
    const statusLine = document.getElementById('status-line');
    const weekLabel = document.getElementById('week-label');
    const datePicker = document.getElementById('date-picker');
    let weekStart = startOfWeek(new Date());

    document.getElementById('logout-link').addEventListener('click', async (event) => {
        event.preventDefault();
        await logoutSession();
        window.location.replace('/');
    });

    document.getElementById('theme-toggle-local').addEventListener('click', () => {
        const next = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark';
        document.documentElement.dataset.theme = next;
        localStorage.setItem('theme', next);
    });
    document.documentElement.dataset.theme = localStorage.getItem('theme') || 'light';

    document.getElementById('prev-week').addEventListener('click', () => moveWeek(-1));
    document.getElementById('today-week').addEventListener('click', () => {
        weekStart = startOfWeek(new Date());
        loadSchedule();
    });
    document.getElementById('next-week').addEventListener('click', () => moveWeek(1));
    datePicker.addEventListener('change', () => {
        if (datePicker.value) {
            weekStart = startOfWeek(new Date(datePicker.value));
            loadSchedule();
        }
    });

    loadSchedule();

    async function loadSchedule() {
        const startDate = toIsoDate(weekStart);
        const endDate = toIsoDate(addDays(weekStart, 6));
        datePicker.value = startDate;
        weekLabel.textContent = `${formatDate(weekStart)} - ${formatDate(addDays(weekStart, 6))}`;

        if (!teacherId) {
            renderEmptyWeek('Не удалось определить преподавателя');
            showStatus('Выполните вход заново, чтобы получить идентификатор пользователя', true);
            return;
        }

        renderEmptyWeek('Загрузка...');
        try {
            const lessons = await fetchJson(`/api/schedule?teacherId=${encodeURIComponent(teacherId)}&startDate=${startDate}&endDate=${endDate}`);
            renderWeek(lessons);
            showStatus(lessons.length ? `Найдено занятий: ${lessons.length}` : 'На этой неделе занятий нет', false);
        } catch (error) {
            renderEmptyWeek('Ошибка загрузки');
            showStatus(error.message, true);
        }
    }

    function renderWeek(lessons) {
        if (window.matchMedia('(max-width: 980px)').matches) {
            renderMobileWeek(lessons);
            return;
        }

        const slots = collectSlots(lessons);
        const lessonsByKey = new Map();
        lessons.forEach(lesson => {
            lessonsByKey.set(`${lesson.date}:${lesson.timeSlotOrder}`, lesson);
        });

        grid.innerHTML = [
            '<div class="corner"></div>',
            ...daysOfWeek().map(date => renderHead(date)),
            ...slots.flatMap(slot => [
                `<div class="time-cell">${escapeHtml(slot.label)}</div>`,
                ...daysOfWeek().map(date => renderCell(lessonsByKey.get(`${toIsoDate(date)}:${slot.order}`)))
            ])
        ].join('');
    }

    function renderMobileWeek(lessons) {
        const lessonsByDate = new Map();
        lessons.forEach(lesson => {
            if (!lessonsByDate.has(lesson.date)) lessonsByDate.set(lesson.date, []);
            lessonsByDate.get(lesson.date).push(lesson);
        });
        grid.innerHTML = daysOfWeek().map(date => {
            const key = toIsoDate(date);
            const dayLessons = lessonsByDate.get(key) || [];
            return `
                <article class="mobile-day">
                    ${renderHead(date)}
                    <div class="mobile-list">
                        ${dayLessons.length ? dayLessons.map(renderLesson).join('') : '<div class="empty">Занятий нет</div>'}
                    </div>
                </article>
            `;
        }).join('');
    }

    function renderEmptyWeek(message) {
        if (window.matchMedia('(max-width: 980px)').matches) {
            grid.innerHTML = daysOfWeek().map(date => `
                <article class="mobile-day">
                    ${renderHead(date)}
                    <div class="mobile-list"><div class="empty">${escapeHtml(message)}</div></div>
                </article>
            `).join('');
            return;
        }

        grid.innerHTML = [
            '<div class="corner"></div>',
            ...daysOfWeek().map(date => renderHead(date)),
            `<div class="time-cell">Неделя</div>`,
            ...daysOfWeek().map(() => `<div class="day-cell"><div class="empty">${escapeHtml(message)}</div></div>`)
        ].join('');
    }

    function renderHead(date) {
        return `
            <div class="day-head">
                <strong>${escapeHtml(dayName(date))}</strong>
                <span>${escapeHtml(formatDate(date))}</span>
            </div>
        `;
    }

    function renderCell(lesson) {
        return `<div class="day-cell">${lesson ? renderLesson(lesson) : '<div class="empty">Нет занятия</div>'}</div>`;
    }

    function renderLesson(lesson) {
        const groups = Array.isArray(lesson.groupNames) ? lesson.groupNames.join(', ') : '';
        const subgroups = Array.isArray(lesson.subgroupNames) && lesson.subgroupNames.length
            ? lesson.subgroupNames.join(', ')
            : lesson.subgroupName;
        return `
            <div class="lesson">
                <div class="lesson-title">${escapeHtml(lesson.subjectName)}</div>
                <div class="lesson-meta">
                    <span class="chip">${escapeHtml(trimTime(lesson.startTime))} - ${escapeHtml(trimTime(lesson.endTime))}</span>
                    <span class="chip">${escapeHtml(lesson.lessonTypeName)}</span>
                    ${subgroups ? `<span class="chip">${escapeHtml(subgroups)}</span>` : ''}
                    <span class="chip">${escapeHtml(lesson.classroomName)}</span>
                    ${groups ? `<span class="chip">${escapeHtml(groups)}</span>` : ''}
                </div>
            </div>
        `;
    }

    function collectSlots(lessons) {
        const slots = new Map();
        lessons.forEach(lesson => {
            slots.set(lesson.timeSlotOrder, {
                order: lesson.timeSlotOrder,
                label: `${trimTime(lesson.startTime)} - ${trimTime(lesson.endTime)}`
            });
        });
        if (!slots.size) {
            slots.set(1, { order: 1, label: 'Расписание' });
        }
        return [...slots.values()].sort((a, b) => a.order - b.order);
    }

    function moveWeek(delta) {
        weekStart = addDays(weekStart, delta * 7);
        loadSchedule();
    }

    function daysOfWeek() {
        return Array.from({ length: 7 }, (_, index) => addDays(weekStart, index));
    }

    async function fetchJson(url) {
        const response = await fetchWithAuth(url);
        const data = await response.json().catch(() => null);
        if (response.status === 401) {
            clearAuthState();
            window.location.replace('/');
            throw new Error('Требуется повторный вход в систему');
        }
        if (!response.ok) {
            throw new Error(data?.message || `Ошибка HTTP: ${response.status}`);
        }
        return data;
    }

    function showStatus(message, isError) {
        statusLine.textContent = message;
        statusLine.classList.toggle('error', isError);
    }

    function startOfWeek(date) {
        const copy = new Date(date.getFullYear(), date.getMonth(), date.getDate());
        const day = copy.getDay() || 7;
        copy.setDate(copy.getDate() - day + 1);
        return copy;
    }

    function addDays(date, days) {
        const copy = new Date(date);
        copy.setDate(copy.getDate() + days);
        return copy;
    }

    function toIsoDate(date) {
        return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
    }

    function formatDate(date) {
        return date.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: 'numeric' });
    }

    function dayName(date) {
        const value = date.toLocaleDateString('ru-RU', { weekday: 'long' });
        return value.charAt(0).toUpperCase() + value.slice(1);
    }

    function trimTime(value) {
        return String(value || '').slice(0, 5);
    }

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

