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

(async () => {
    const session = await restoreSession();
    if (!session || session.role !== 'STUDENT') {
        window.location.replace('/');
        return;
    }
    const groupSelect = document.getElementById('group-select');
    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();
        }
    });
    groupSelect.addEventListener('change', () => {
        localStorage.setItem('studentGroupId', groupSelect.value);
        loadSchedule();
    });

    init();

    async function init() {
        await loadGroups();
        await loadSchedule();
    }

    async function loadGroups() {
        try {
            const groups = await fetchJson('/api/groups');
            if (!groups.length) {
                groupSelect.innerHTML = '<option value="">Группы не найдены</option>';
                return;
            }
            const savedGroupId = localStorage.getItem('studentGroupId');
            groupSelect.innerHTML = groups.map(group => (
                `<option value="${escapeHtml(group.id)}">${escapeHtml(group.name)}</option>`
            )).join('');
            groupSelect.value = savedGroupId && groups.some(group => String(group.id) === savedGroupId)
                ? savedGroupId
                : String(groups[0].id);
        } catch (error) {
            groupSelect.innerHTML = '<option value="">Ошибка загрузки групп</option>';
            showStatus(error.message, true);
        }
    }

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

        renderEmptyWeek('Загрузка...');
        if (!groupId) {
            showStatus('Выберите группу', false);
            renderEmptyWeek('Нет выбранной группы');
            return;
        }

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

    function renderWeek(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 renderDay(date, dayLessons);
        }).join('');
    }

    function renderEmptyWeek(message) {
        grid.innerHTML = daysOfWeek().map(date => renderDay(date, [], message)).join('');
    }

    function renderDay(date, lessons, emptyMessage = 'Занятий нет') {
        return `
            <article class="day">
                <div class="day-head">
                    <div class="day-name">${escapeHtml(dayName(date))}</div>
                    <div class="day-date">${escapeHtml(formatDate(date))}</div>
                </div>
                <div class="lesson-list">
                    ${lessons.length ? lessons.map(renderLesson).join('') : `<div class="empty">${escapeHtml(emptyMessage)}</div>`}
                </div>
            </article>
        `;
    }

    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-time">${escapeHtml(trimTime(lesson.startTime))} - ${escapeHtml(trimTime(lesson.endTime))}</div>
                <div class="lesson-title">${escapeHtml(lesson.subjectName)}</div>
                <div class="lesson-meta">
                    <span class="chip">${escapeHtml(lesson.lessonTypeName)}</span>
                    ${subgroups ? `<span class="chip">${escapeHtml(subgroups)}</span>` : ''}
                    <span class="chip">${escapeHtml(lesson.lessonFormat)}</span>
                    <span class="chip">${escapeHtml(lesson.teacherName)}</span>
                    <span class="chip">${escapeHtml(lesson.classroomName)}</span>
                    ${groups ? `<span class="chip">${escapeHtml(groups)}</span>` : ''}
                </div>
            </div>
        `;
    }

    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;');
    }
})();

