"""
Представления (views) для системы проверки домашних заданий.
Содержит все представления для:
- Авторизации и регистрации пользователей
- Dashboard студента и преподавателя
- Управления домашними заданиями
- Отправки и проверки работ
"""
import os
from django.contrib import messages
from django.contrib.auth import authenticate, get_user_model, login, logout
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from .decorators import student_required, teacher_required
from .forms import GradeForm, HomeworkForm, RegisterForm, SubmissionForm
from .models import Course, CourseEnrollmentRequest, Homework, Submission
User = get_user_model()
# ============= Авторизация =============
[документация]
def register_view(request):
    """Регистрация нового пользователя"""
    if request.user.is_authenticated:
        return redirect("dashboard")
    if request.method == "POST":
        form = RegisterForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            messages.success(request, f"Добро пожаловать, {user.first_name}!")
            return redirect("dashboard")
    else:
        form = RegisterForm()
    return render(request, "assignments/register.html", {"form": form}) 
[документация]
def login_view(request):
    """Вход в систему"""
    if request.user.is_authenticated:
        return redirect("dashboard")
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        user = authenticate(request, username=username, password=password)
        if user is not None:
            login(request, user)
            messages.success(request, f"Добро пожаловать, {user.first_name}!")
            return redirect("dashboard")
        messages.error(request, "Неверный логин или пароль")
    return render(request, "assignments/login.html") 
[документация]
@login_required
def logout_view(request):
    """Выход из системы"""
    logout(request)
    messages.info(request, "Вы вышли из системы")
    return redirect("login") 
# ============= Dashboard =============
[документация]
@login_required
def dashboard_view(request):
    """Главная страница - перенаправление в зависимости от роли"""
    if request.user.profile.is_student:
        return redirect("student_dashboard")
    if request.user.profile.is_teacher:
        return redirect("teacher_dashboard")
    return redirect("login") 
# ============= Студент =============
[документация]
@login_required
@student_required
def student_dashboard(request):
    """Dashboard студента - список курсов"""
    courses = request.user.enrolled_courses.all()
    # Статистика по всем курсам
    all_homeworks = Homework.objects.filter(course__in=courses)
    student_submissions = Submission.objects.filter(student=request.user)
    context = {
        "courses": courses,
        "total_courses": courses.count(),
        "total_homeworks": all_homeworks.count(),
        "submitted_count": student_submissions.count(),
        "graded_count": student_submissions.filter(grade__isnull=False).count(),
    }
    return render(request, "assignments/student_dashboard.html", context) 
[документация]
@login_required
@student_required
def course_detail(request, pk):
    """Детальная страница курса для студента"""
    course = get_object_or_404(Course, pk=pk)
    # Проверка доступа - студент должен быть записан на курс
    if request.user not in course.students.all():
        messages.error(request, "У вас нет доступа к этому курсу")
        return redirect("student_dashboard")
    homeworks = course.homeworks.all().order_by("-created_at")
    course_submissions = Submission.objects.filter(student=request.user, homework__course=course)
    # Добавляем информацию о том, сдал ли студент каждое ДЗ
    homework_status = []
    for hw in homeworks:
        submission = course_submissions.filter(homework=hw).first()
        homework_status.append(
            {
                "homework": hw,
                "submission": submission,
                "is_overdue": hw.due_date < timezone.now(),
            }
        )
    context = {
        "course": course,
        "homework_status": homework_status,
        "total_homeworks": homeworks.count(),
        "submitted_count": course_submissions.count(),
    }
    return render(request, "assignments/course_detail.html", context) 
[документация]
@login_required
@student_required
def homework_detail(request, pk):
    """Детальная страница задания для студента"""
    homework = get_object_or_404(Homework, pk=pk)
    # Проверка доступа - студент должен быть записан на курс
    if request.user not in homework.course.students.all():
        messages.error(request, "У вас нет доступа к этому заданию")
        return redirect("student_dashboard")
    submission = Submission.objects.filter(homework=homework, student=request.user).first()
    if request.method == "POST":
        # Разрешаем переотправку работы (замену файла)
        if submission:
            # Обновляем существующую отправку
            form = SubmissionForm(request.POST, request.FILES, instance=submission)
            if form.is_valid():
                # Удаляем старый файл перед сохранением нового
                if submission.solution_file and os.path.isfile(submission.solution_file.path):
                    os.remove(submission.solution_file.path)
                submission = form.save(commit=False)
                # Сбрасываем оценку при переотправке
                submission.grade = None
                submission.feedback = ""
                submission.save()
                messages.success(request, "Работа успешно переотправлена! Оценка сброшена.")
                return redirect("course_detail", pk=homework.course.pk)
        else:
            # Создаём новую отправку
            form = SubmissionForm(request.POST, request.FILES)
            if form.is_valid():
                submission = form.save(commit=False)
                submission.homework = homework
                submission.student = request.user
                submission.save()
                messages.success(request, "Работа успешно отправлена!")
                return redirect("course_detail", pk=homework.course.pk)
    else:
        form = SubmissionForm(instance=submission) if submission else SubmissionForm()
    context = {
        "homework": homework,
        "submission": submission,
        "form": form,
        "is_overdue": homework.due_date < timezone.now(),
    }
    return render(request, "assignments/homework_detail.html", context) 
[документация]
@login_required
@student_required
def my_submissions(request):
    """Список всех отправленных работ студента"""
    submissions = Submission.objects.filter(student=request.user).order_by("-submitted_at")
    context = {
        "submissions": submissions,
    }
    return render(request, "assignments/my_submissions.html", context) 
[документация]
@login_required
@student_required
def my_grades(request):
    """Таблица оценок студента по всем курсам"""
    courses = request.user.enrolled_courses.all()
    grades_data = []
    for course in courses:
        homeworks = course.homeworks.all().order_by("due_date")
        course_grades = {"course": course, "homeworks": []}
        for hw in homeworks:
            submission = Submission.objects.filter(homework=hw, student=request.user).first()
            course_grades["homeworks"].append(
                {
                    "homework": hw,
                    "submission": submission,
                    "grade": submission.grade if submission else None,
                    "status": ("Оценено" if submission and submission.grade else "На проверке" if submission else "Не сдано"),
                }
            )
        grades_data.append(course_grades)
    context = {
        "grades_data": grades_data,
    }
    return render(request, "assignments/my_grades.html", context) 
[документация]
@login_required
@student_required
def available_courses(request):
    """Список всех доступных курсов для студента"""
    # Курсы, на которые студент уже записан
    enrolled_courses = request.user.enrolled_courses.all()
    # Все курсы
    all_courses = Course.objects.all()
    # Заявки студента
    student_requests = CourseEnrollmentRequest.objects.filter(student=request.user)
    requests_dict = {req.course_id: req for req in student_requests}
    # Подготавливаем информацию о каждом курсе
    courses_info = []
    for course in all_courses:
        is_enrolled = course in enrolled_courses
        request_status = None
        enrollment_request = requests_dict.get(course.id)
        if enrollment_request:
            request_status = enrollment_request.status
        courses_info.append(
            {
                "course": course,
                "is_enrolled": is_enrolled,
                "request_status": request_status,
                "request_id": enrollment_request.id if enrollment_request else None,
            }
        )
    context = {
        "courses_info": courses_info,
    }
    return render(request, "assignments/available_courses.html", context) 
[документация]
@login_required
@student_required
def request_enrollment(request, course_pk):
    """Подать заявку на зачисление на курс"""
    course = get_object_or_404(Course, pk=course_pk)
    # Проверяем, не записан ли студент уже на курс
    if request.user in course.students.all():
        messages.warning(request, "Вы уже записаны на этот курс")
        return redirect("available_courses")
    # Проверяем, нет ли уже активной заявки
    existing_request = CourseEnrollmentRequest.objects.filter(course=course, student=request.user, status="pending").first()
    if existing_request:
        messages.warning(request, "Вы уже подали заявку на этот курс")
        return redirect("available_courses")
    if request.method == "POST":
        message = request.POST.get("message", "")
        CourseEnrollmentRequest.objects.create(course=course, student=request.user, message=message)
        messages.success(request, f'Заявка на курс "{course.title}" успешно подана!')
        return redirect("available_courses")
    context = {"course": course}
    return render(request, "assignments/request_enrollment.html", context) 
[документация]
@login_required
@student_required
def cancel_enrollment_request(request, request_pk):
    """Отменить заявку на зачисление"""
    enrollment_request = get_object_or_404(CourseEnrollmentRequest, pk=request_pk)
    # Проверка доступа
    if enrollment_request.student != request.user:
        messages.error(request, "У вас нет доступа к этой заявке")
        return redirect("available_courses")
    # Можно отменить только заявки со статусом "pending"
    if enrollment_request.status != "pending":
        messages.error(request, "Эту заявку нельзя отменить")
        return redirect("available_courses")
    if request.method == "POST":
        course_title = enrollment_request.course.title
        enrollment_request.delete()
        messages.success(request, f'Заявка на курс "{course_title}" отменена')
        return redirect("available_courses")
    return redirect("available_courses") 
# ============= Преподаватель =============
[документация]
@login_required
@teacher_required
def teacher_dashboard(request):
    """Dashboard преподавателя - список его курсов"""
    courses = request.user.teaching_courses.all()
    # Статистика
    all_homeworks = Homework.objects.filter(course__in=courses)
    all_submissions = Submission.objects.filter(homework__in=all_homeworks)
    pending_submissions = all_submissions.filter(grade__isnull=True)
    context = {
        "courses": courses,
        "total_courses": courses.count(),
        "total_homeworks": all_homeworks.count(),
        "total_submissions": all_submissions.count(),
        "pending_count": pending_submissions.count(),
    }
    return render(request, "assignments/teacher_dashboard.html", context) 
[документация]
@login_required
@teacher_required
def teacher_course_detail(request, pk):
    """Детальная страница курса для преподавателя"""
    course = get_object_or_404(Course, pk=pk)
    # Проверка доступа
    if request.user not in course.teachers.all():
        messages.error(request, "У вас нет доступа к этому курсу")
        return redirect("teacher_dashboard")
    homeworks = course.homeworks.all().order_by("-created_at")
    all_submissions = Submission.objects.filter(homework__course=course)
    context = {
        "course": course,
        "homeworks": homeworks,
        "students_count": course.students.count(),
        "total_submissions": all_submissions.count(),
        "pending_count": all_submissions.filter(grade__isnull=True).count(),
    }
    return render(request, "assignments/teacher_course_detail.html", context) 
[документация]
@login_required
@teacher_required
def create_course(request):
    """Создание нового курса"""
    if request.method == "POST":
        title = request.POST.get("title")
        description = request.POST.get("description")
        if title and description:
            course = Course.objects.create(title=title, description=description)
            course.teachers.add(request.user)
            messages.success(request, f'Курс "{course.title}" успешно создан!')
            return redirect("teacher_course_detail", pk=course.pk)
        messages.error(request, "Заполните все обязательные поля")
    return render(request, "assignments/create_course.html") 
[документация]
@login_required
@teacher_required
def edit_course(request, pk):
    """Редактирование курса"""
    course = get_object_or_404(Course, pk=pk)
    # Проверка доступа
    if request.user not in course.teachers.all():
        messages.error(request, "У вас нет доступа к этому курсу")
        return redirect("teacher_dashboard")
    if request.method == "POST":
        course.title = request.POST.get("title", course.title)
        course.description = request.POST.get("description", course.description)
        course.save()
        messages.success(request, "Курс успешно обновлен!")
        return redirect("teacher_course_detail", pk=course.pk)
    context = {"course": course}
    return render(request, "assignments/edit_course.html", context) 
[документация]
@login_required
@teacher_required
def manage_students(request, pk):
    """Управление студентами курса - просмотр зачисленных студентов и заявок"""
    course = get_object_or_404(Course, pk=pk)
    # Проверка доступа
    if request.user not in course.teachers.all():
        messages.error(request, "У вас нет доступа к этому курсу")
        return redirect("teacher_dashboard")
    # Текущие студенты
    current_students = course.students.all()
    # Заявки на зачисление
    pending_requests = CourseEnrollmentRequest.objects.filter(course=course, status="pending").order_by("-created_at")
    # История заявок (одобренные и отклоненные)
    processed_requests = CourseEnrollmentRequest.objects.filter(course=course, status__in=["approved", "rejected"]).order_by(
        "-processed_at"
    )[
        :20
    ]  # Показываем последние 20
    context = {
        "course": course,
        "current_students": current_students,
        "pending_requests": pending_requests,
        "processed_requests": processed_requests,
        "pending_count": pending_requests.count(),
    }
    return render(request, "assignments/manage_students.html", context) 
[документация]
@login_required
@teacher_required
def approve_enrollment_request(request, request_pk):
    """Одобрить заявку на зачисление"""
    enrollment_request = get_object_or_404(CourseEnrollmentRequest, pk=request_pk)
    # Проверка доступа
    if request.user not in enrollment_request.course.teachers.all():
        messages.error(request, "У вас нет доступа к этой заявке")
        return redirect("teacher_dashboard")
    # Проверка статуса
    if enrollment_request.status != "pending":
        messages.warning(request, "Эта заявка уже обработана")
        return redirect("manage_students", pk=enrollment_request.course.pk)
    if request.method == "POST":
        # Обновляем статус заявки
        enrollment_request.status = "approved"
        enrollment_request.processed_at = timezone.now()
        enrollment_request.processed_by = request.user
        enrollment_request.save()
        # Добавляем студента на курс
        enrollment_request.course.students.add(enrollment_request.student)
        messages.success(
            request,
            f'Студент {enrollment_request.student.get_full_name()} зачислен на курс "{enrollment_request.course.title}"',
        )
        return redirect("manage_students", pk=enrollment_request.course.pk)
    return redirect("manage_students", pk=enrollment_request.course.pk) 
[документация]
@login_required
@teacher_required
def reject_enrollment_request(request, request_pk):
    """Отклонить заявку на зачисление"""
    enrollment_request = get_object_or_404(CourseEnrollmentRequest, pk=request_pk)
    # Проверка доступа
    if request.user not in enrollment_request.course.teachers.all():
        messages.error(request, "У вас нет доступа к этой заявке")
        return redirect("teacher_dashboard")
    # Проверка статуса
    if enrollment_request.status != "pending":
        messages.warning(request, "Эта заявка уже обработана")
        return redirect("manage_students", pk=enrollment_request.course.pk)
    if request.method == "POST":
        # Обновляем статус заявки
        enrollment_request.status = "rejected"
        enrollment_request.processed_at = timezone.now()
        enrollment_request.processed_by = request.user
        enrollment_request.save()
        messages.info(request, f"Заявка от {enrollment_request.student.get_full_name()} отклонена")
        return redirect("manage_students", pk=enrollment_request.course.pk)
    return redirect("manage_students", pk=enrollment_request.course.pk) 
[документация]
@login_required
@teacher_required
def remove_student_from_course(request, course_pk, student_pk):
    """Удалить студента с курса"""
    course = get_object_or_404(Course, pk=course_pk)
    # Проверка доступа
    if request.user not in course.teachers.all():
        messages.error(request, "У вас нет доступа к этому курсу")
        return redirect("teacher_dashboard")
    student = get_object_or_404(User, pk=student_pk)
    if request.method == "POST":
        course.students.remove(student)
        messages.success(request, f"Студент {student.get_full_name()} удален с курса")
        return redirect("manage_students", pk=course.pk)
    return redirect("manage_students", pk=course.pk) 
[документация]
@login_required
@teacher_required
def teacher_create_homework(request, course_pk):
    """Создание домашнего задания"""
    course = get_object_or_404(Course, pk=course_pk)
    # Проверка доступа
    if request.user not in course.teachers.all():
        messages.error(request, "У вас нет доступа к этому курсу")
        return redirect("teacher_dashboard")
    if request.method == "POST":
        form = HomeworkForm(request.POST)
        if form.is_valid():
            homework = form.save(commit=False)
            homework.course = course
            homework.save()
            messages.success(request, f'Задание "{homework.title}" создано!')
            return redirect("teacher_course_detail", pk=course.pk)
    else:
        form = HomeworkForm()
    context = {"form": form, "course": course}
    return render(request, "assignments/teacher_create_homework.html", context) 
[документация]
@login_required
@teacher_required
def teacher_edit_homework(request, pk):
    """Редактирование домашнего задания"""
    homework = get_object_or_404(Homework, pk=pk)
    # Проверка доступа
    if request.user not in homework.course.teachers.all():
        messages.error(request, "У вас нет доступа к этому заданию")
        return redirect("teacher_dashboard")
    if request.method == "POST":
        form = HomeworkForm(request.POST, instance=homework)
        if form.is_valid():
            form.save()
            messages.success(request, "Задание успешно обновлено!")
            return redirect("teacher_course_detail", pk=homework.course.pk)
    else:
        form = HomeworkForm(instance=homework)
    context = {"form": form, "homework": homework}
    return render(request, "assignments/teacher_edit_homework.html", context) 
[документация]
@login_required
@teacher_required
def teacher_homework_submissions(request, pk):
    """Список отправок по домашнему заданию"""
    homework = get_object_or_404(Homework, pk=pk)
    # Проверка доступа
    if request.user not in homework.course.teachers.all():
        messages.error(request, "У вас нет доступа к этому заданию")
        return redirect("teacher_dashboard")
    submissions = homework.submissions.all().order_by("-submitted_at")
    context = {
        "homework": homework,
        "submissions": submissions,
        "total_count": submissions.count(),
        "graded_count": submissions.filter(grade__isnull=False).count(),
        "pending_count": submissions.filter(grade__isnull=True).count(),
    }
    return render(request, "assignments/teacher_homework_submissions.html", context) 
[документация]
@login_required
@teacher_required
def teacher_grade_submission(request, pk):
    """Проверка и выставление оценки"""
    submission = get_object_or_404(Submission, pk=pk)
    # Проверка доступа
    if request.user not in submission.homework.course.teachers.all():
        messages.error(request, "У вас нет доступа к этой работе")
        return redirect("teacher_dashboard")
    if request.method == "POST":
        form = GradeForm(request.POST, instance=submission)
        if form.is_valid():
            form.save()
            messages.success(request, f"Оценка для {submission.student.get_full_name()} выставлена!")
            return redirect("teacher_homework_submissions", pk=submission.homework.pk)
    else:
        form = GradeForm(instance=submission)
    context = {
        "submission": submission,
        "form": form,
    }
    return render(request, "assignments/teacher_grade_submission.html", context) 
[документация]
@login_required
@teacher_required
def teacher_all_submissions(request):
    """Все отправки преподавателя"""
    courses = request.user.teaching_courses.all()
    submissions = Submission.objects.filter(homework__course__in=courses).order_by("-submitted_at")
    # Фильтрация
    status_filter = request.GET.get("status", "all")
    course_filter = request.GET.get("course", "all")
    if status_filter == "pending":
        submissions = submissions.filter(grade__isnull=True)
    elif status_filter == "graded":
        submissions = submissions.filter(grade__isnull=False)
    if course_filter != "all":
        submissions = submissions.filter(homework__course_id=course_filter)
    context = {
        "submissions": submissions,
        "status_filter": status_filter,
        "course_filter": course_filter,
        "courses": courses,
    }
    return render(request, "assignments/teacher_all_submissions.html", context) 
[документация]
@login_required
@teacher_required
def delete_course(request, pk):
    """Удаление курса"""
    course = get_object_or_404(Course, pk=pk)
    # Проверка доступа
    if request.user not in course.teachers.all():
        messages.error(request, "У вас нет доступа к этому курсу")
        return redirect("teacher_dashboard")
    if request.method == "POST":
        course_title = course.title
        course.delete()
        messages.success(request, f'Курс "{course_title}" успешно удалён!')
        return redirect("teacher_dashboard")
    return redirect("teacher_course_detail", pk=pk) 
[документация]
@login_required
@teacher_required
def delete_homework(request, pk):
    """Удаление домашнего задания"""
    homework = get_object_or_404(Homework, pk=pk)
    # Проверка доступа
    if request.user not in homework.course.teachers.all():
        messages.error(request, "У вас нет доступа к этому заданию")
        return redirect("teacher_dashboard")
    if request.method == "POST":
        course_pk = homework.course.pk
        homework_title = homework.title
        homework.delete()
        messages.success(request, f'Задание "{homework_title}" успешно удалено!')
        return redirect("teacher_course_detail", pk=course_pk)
    return redirect("teacher_course_detail", pk=homework.course.pk) 
[документация]
@login_required
@teacher_required
def teacher_grades_table(request, course_pk):
    """Сводная таблица оценок студентов по курсу"""
    course = get_object_or_404(Course, pk=course_pk)
    # Проверка доступа
    if request.user not in course.teachers.all():
        messages.error(request, "У вас нет доступа к этому курсу")
        return redirect("teacher_dashboard")
    # Получаем всех студентов курса и все задания
    students = course.students.all().order_by("last_name", "first_name")
    homeworks = course.homeworks.all().order_by("due_date")
    # Формируем таблицу оценок
    grades_table = []
    for student in students:
        student_row = {
            "student": student,
            "grades": [],
            "total": 0,
            "average": 0,
            "completed": 0,
        }
        total_grade = 0
        graded_count = 0
        for hw in homeworks:
            submission = Submission.objects.filter(homework=hw, student=student).first()
            grade_info = {
                "homework": hw,
                "submission": submission,
                "grade": submission.grade if submission else None,
                "status": (
                    "graded" if submission and submission.grade is not None else "submitted" if submission else "missing"
                ),
            }
            student_row["grades"].append(grade_info)
            if submission and submission.grade is not None:
                total_grade += submission.grade
                graded_count += 1
        if graded_count > 0:
            student_row["average"] = round(total_grade / graded_count, 1)
        student_row["completed"] = graded_count
        student_row["total"] = total_grade
        grades_table.append(student_row)
    context = {
        "course": course,
        "homeworks": homeworks,
        "grades_table": grades_table,
        "students_count": students.count(),
        "homeworks_count": homeworks.count(),
    }
    return render(request, "assignments/teacher_grades_table.html", context) 
# ============= Общие =============
[документация]
def home_view(request):
    """Главная страница для неавторизованных пользователей"""
    if request.user.is_authenticated:
        return redirect("dashboard")
    return render(request, "assignments/home.html")