from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import HttpResponse
from django.db.models import Q
from django.utils import timezone
from django.utils.dateparse import parse_date
from users.models import Student, Teacher
from .models import RiskPrediction
from .risk_calculator import calculate_student_risk
from assignments.models import Assignment
from core.models import Group, Subject, ScheduleItem, Room, Attendance, AcademicDebt, Olympiad
from datetime import datetime, timedelta


# ==================== РАСПИСАНИЕ ====================

@login_required
def schedule_view(request):
    """Главная страница расписания"""
    groups = Group.objects.all()
    selected_group_id = request.GET.get('group')

    if selected_group_id:
        selected_group = get_object_or_404(Group, id=selected_group_id)
    else:
        selected_group = groups.first()

    if selected_group:
        schedule_items = ScheduleItem.objects.filter(group=selected_group).select_related('subject', 'teacher', 'room')
    else:
        schedule_items = []

    schedule_dict = {}
    for item in schedule_items:
        if item.weekday not in schedule_dict:
            schedule_dict[item.weekday] = {}
        schedule_dict[item.weekday][item.start_time.strftime('%H:%M')] = item

    weekdays = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']
    times = [('09:00', '10:30'), ('10:45', '12:15'), ('12:45', '14:15'), ('14:30', '16:00'), ('16:15', '17:45')]

    context = {
        'groups': groups,
        'selected_group': selected_group,
        'schedule_dict': schedule_dict,
        'schedule_items': schedule_items,
        'weekdays': weekdays,
        'times': times,
        'subjects': Subject.objects.all(),
        'teachers': Teacher.objects.all(),
        'rooms': Room.objects.all(),
    }
    return render(request, 'schedule_new.html', context)


@login_required
def teacher_schedule(request, teacher_id):
    """Расписание конкретного преподавателя"""
    teacher = get_object_or_404(Teacher, id=teacher_id)

    schedule_items = ScheduleItem.objects.filter(teacher=teacher).select_related('group', 'subject', 'room')

    weekdays = [
        {'name': 'Понедельник', 'short': 'ПН', 'number': 1},
        {'name': 'Вторник', 'short': 'ВТ', 'number': 2},
        {'name': 'Среда', 'short': 'СР', 'number': 3},
        {'name': 'Четверг', 'short': 'ЧТ', 'number': 4},
        {'name': 'Пятница', 'short': 'ПТ', 'number': 5},
        {'name': 'Суббота', 'short': 'СБ', 'number': 6},
        {'name': 'Воскресенье', 'short': 'ВС', 'number': 7},
    ]

    schedule_by_weekday = {}
    for day in weekdays:
        schedule_by_weekday[day['number']] = []

    for item in schedule_items:
        schedule_by_weekday[item.weekday].append(item)

    for day in schedule_by_weekday:
        schedule_by_weekday[day].sort(key=lambda x: x.start_time)

    context = {
        'teacher': teacher,
        'weekdays': weekdays,
        'schedule_by_weekday': schedule_by_weekday,
    }
    return render(request, 'teacher_schedule.html', context)


@login_required
def add_schedule_item(request):
    """Добавление занятия (только для преподавателей и админов)"""
    if request.user.role not in ['teacher', 'academic_staff', 'admin'] and not request.user.is_staff:
        messages.error(request, 'У вас нет прав на добавление занятий')
        return redirect('schedule')

    if request.method == 'POST':
        ScheduleItem.objects.create(
            group_id=request.POST.get('group_id'),
            subject_id=request.POST.get('subject_id'),
            teacher_id=request.POST.get('teacher_id'),
            room_id=request.POST.get('room_id') or None,
            weekday=request.POST.get('weekday'),
            start_time=request.POST.get('start_time'),
            end_time=request.POST.get('end_time'),
            is_even_week=request.POST.get('is_even_week') == 'on',
            is_odd_week=request.POST.get('is_odd_week') == 'on',
        )
        messages.success(request, 'Занятие добавлено')
    return redirect('schedule')


@login_required
def delete_schedule_item(request, item_id):
    """Удаление занятия (только для преподавателей и админов)"""
    if request.user.role not in ['teacher', 'academic_staff', 'admin'] and not request.user.is_staff:
        messages.error(request, 'У вас нет прав на удаление занятий')
        return redirect('schedule')

    item = get_object_or_404(ScheduleItem, id=item_id)
    item.delete()
    messages.success(request, 'Занятие удалено')
    return redirect('schedule')


@login_required
def export_schedule(request):
    """Экспорт расписания в Excel"""
    from openpyxl import Workbook
    from openpyxl.styles import Alignment, Font, PatternFill

    group_id = request.GET.get('group')
    if not group_id:
        messages.error(request, 'Выберите группу')
        return redirect('schedule')

    group = get_object_or_404(Group, id=group_id)
    schedule_items = ScheduleItem.objects.filter(group=group).select_related('subject', 'teacher', 'room')

    wb = Workbook()
    ws = wb.active
    ws.title = f"Расписание {group.name}"

    weekdays_rus = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье']
    times = ['09:00-10:30', '10:45-12:15', '12:45-14:15', '14:30-16:00', '16:15-17:45']

    ws['A1'] = f"Расписание группы {group.name}"
    ws['A1'].font = Font(size=16, bold=True)
    ws.merge_cells('A1:H1')

    ws['A3'] = "Время"
    for i, day in enumerate(weekdays_rus, start=2):
        ws.cell(row=3, column=i, value=day)
        ws.cell(row=3, column=i).font = Font(bold=True, color="FFFFFF")
        ws.cell(row=3, column=i).fill = PatternFill(start_color="4395AB", end_color="4395AB", fill_type="solid")

    schedule_dict = {}
    for item in schedule_items:
        if item.weekday not in schedule_dict:
            schedule_dict[item.weekday] = {}
        schedule_dict[item.weekday][item.start_time.strftime('%H:%M')] = item

    for row_idx, (start, end) in enumerate(times, start=4):
        ws.cell(row=row_idx, column=1, value=f"{start}-{end}")
        ws.cell(row=row_idx, column=1).alignment = Alignment(horizontal='center')

        for col_idx, weekday in enumerate(range(1, 8), start=2):
            item = schedule_dict.get(weekday, {}).get(start)
            if item:
                room_name = str(item.room) if item.room else "—"
                if item.room and item.room.is_distance:
                    room_name = "🌐 Дистант"
                cell_value = f"{item.subject.name}\n{item.teacher.last_name} {item.teacher.first_name}\n{room_name}"
                ws.cell(row=row_idx, column=col_idx, value=cell_value)
                ws.cell(row=row_idx, column=col_idx).alignment = Alignment(wrap_text=True, horizontal='center',
                                                                           vertical='center')
                ws.row_dimensions[row_idx].height = 60
            else:
                ws.cell(row=row_idx, column=col_idx, value="—")
                ws.cell(row=row_idx, column=col_idx).alignment = Alignment(horizontal='center')

    for col in range(1, 8):
        ws.column_dimensions[chr(64 + col)].width = 22

    response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    response[
        'Content-Disposition'] = f'attachment; filename="schedule_{group.name}_{datetime.now().strftime("%Y%m%d")}.xlsx"'
    wb.save(response)
    return response


# ==================== ДАШБОРД ====================

@login_required
def dashboard(request):
    """Главная страница с рисками с выбором периода"""
    user = request.user
    today = timezone.now().date()

    # Студент и родитель перенаправляются
    if user.role == 'student':
        return redirect('my_risk')
    if user.role == 'parent':
        return redirect('child_progress')

    # Получаем параметры дат из GET-запроса
    default_from = today - timedelta(days=30)
    date_from_raw = request.GET.get('date_from')
    date_to_raw = request.GET.get('date_to')
    date_from = parse_date(date_from_raw) if date_from_raw else default_from
    date_to = parse_date(date_to_raw) if date_to_raw else today

    if not date_from:
        date_from = default_from
        messages.warning(request, 'Некорректная дата начала периода. Установлен период по умолчанию.')
    if not date_to:
        date_to = today
        messages.warning(request, 'Некорректная дата окончания периода. Установлен период по умолчанию.')
    if date_from > date_to:
        date_from, date_to = date_to, date_from
        messages.info(request, 'Дата начала была больше даты окончания. Период автоматически исправлен.')

    # Определяем группы, которые видит пользователь
    if user.role == 'teacher':
        teacher = get_object_or_404(Teacher, user=user)
        groups = Group.objects.filter(
            Q(curator=teacher) | Q(schedule_items__teacher=teacher)
        ).distinct()
        students = Student.objects.filter(group__in=groups).select_related('group')
    else:  # admin или academic_staff
        students = Student.objects.select_related('group').all()

    stats = {'low': 0, 'medium': 0, 'high': 0, 'critical': 0}
    high_risk_list = []

    for student in students:
        # Получаем риск в выбранном периоде, иначе берем ближайший до конца периода
        latest = student.risk_predictions.filter(
            prediction_date__range=(date_from, date_to)
        ).first()
        if not latest:
            latest = student.risk_predictions.filter(prediction_date__lte=date_to).first()

        if not latest:
            from risk.risk_calculator import calculate_student_risk
            score, level, factors, rec = calculate_student_risk(student)
            latest = RiskPrediction.objects.create(
                student=student, risk_score=score, risk_level=level,
                top_factors=factors, recommended_action=rec,
                prediction_date=date_to
            )
        stats[latest.risk_level] += 1
        if latest.risk_level in ['high', 'critical']:
            high_risk_list.append({'student': student, 'risk': latest})

    high_risk_list.sort(key=lambda item: float(item['risk'].risk_score), reverse=True)
    total = sum(stats.values())
    total_for_percent = total or 1

    context = {
        'today': today,
        'date_from': date_from.strftime('%Y-%m-%d'),
        'date_to': date_to.strftime('%Y-%m-%d'),
        'date_from_display': date_from,
        'date_to_display': date_to,
        'stats': {
            'low': stats['low'], 'medium': stats['medium'],
            'high': stats['high'], 'critical': stats['critical'],
            'low_percent': round(stats['low'] / total_for_percent * 100, 1),
            'medium_percent': round(stats['medium'] / total_for_percent * 100, 1),
            'high_percent': round(stats['high'] / total_for_percent * 100, 1),
            'critical_percent': round(stats['critical'] / total_for_percent * 100, 1),
            'total': total,
        },
        'high_risk_students': high_risk_list,
    }
    return render(request, 'dashboard.html', context)


@login_required
def risk_list(request):
    """Список всех студентов с рисками (только для преподавателей и выше)"""
    if request.user.role not in ['teacher', 'academic_staff', 'admin'] and not request.user.is_staff:
        if request.user.role == 'student':
            return redirect('dashboard')
        return redirect('dashboard')

    students = Student.objects.all()
    risk_data = []
    for student in students:
        pred = student.risk_predictions.first()
        if not pred:
            score, level, factors, rec = calculate_student_risk(student)
            pred = RiskPrediction.objects.create(
                student=student, risk_score=score, risk_level=level,
                top_factors=factors, recommended_action=rec
            )
        risk_data.append({'student': student, 'risk': pred})

    risk_data.sort(key=lambda x: x['risk'].risk_score, reverse=True)
    return render(request, 'risk_list.html', {'risk_list': risk_data})


# ==================== РОДИТЕЛЬ ====================

@login_required
def child_progress(request):
    """Страница успеваемости ребёнка для родителя"""
    if request.user.role != 'parent':
        return redirect('dashboard')

    parent = request.user.parent
    children = parent.children.all()
    selected_child_id = request.GET.get('child')

    if selected_child_id:
        selected_child = get_object_or_404(Student, id=selected_child_id, parents=parent)
    else:
        selected_child = children.first()

    if selected_child:
        pred = selected_child.risk_predictions.first()
        if not pred:
            from .risk_calculator import calculate_student_risk
            score, level, factors, rec = calculate_student_risk(selected_child)
            pred = RiskPrediction.objects.create(
                student=selected_child, risk_score=score, risk_level=level,
                top_factors=factors, recommended_action=rec
            )
    else:
        pred = None

    return render(request, 'child_progress.html', {
        'children': children,
        'selected_child': selected_child,
        'risk': pred,
    })


# ==================== ПОСЕЩАЕМОСТЬ ====================

@login_required
def attendance_view(request):
    """Страница посещаемости"""
    if request.user.role == 'student':
        student = request.user.student
        attendances = Attendance.objects.filter(student=student).select_related('schedule_item__subject')
        return render(request, 'my_attendance.html', {'attendances': attendances, 'student': student})

    groups = Group.objects.all()
    selected_group_id = request.GET.get('group')
    selected_date = request.GET.get('date', datetime.now().strftime('%Y-%m-%d'))

    if selected_group_id:
        selected_group = get_object_or_404(Group, id=selected_group_id)
        schedule_items = []
    else:
        selected_group = groups.first()
        schedule_items = []

    students = Student.objects.filter(group=selected_group) if selected_group else []

    attendances_dict = {}
    for att in Attendance.objects.filter(schedule_item__in=schedule_items):
        attendances_dict[f"{att.schedule_item_id}_{att.student_id}"] = att

    context = {
        'groups': groups,
        'selected_group': selected_group,
        'selected_date': selected_date,
        'schedule_items': schedule_items,
        'students': students,
        'attendances_dict': attendances_dict,
    }
    return render(request, 'attendance.html', context)


@login_required
def mark_attendance(request):
    """Отметка посещаемости"""
    if request.method == 'POST':
        schedule_item_id = request.POST.get('schedule_item_id')
        student_id = request.POST.get('student_id')
        status = request.POST.get('status')
        late_minutes = request.POST.get('late_minutes', 0)

        attendance, created = Attendance.objects.update_or_create(
            schedule_item_id=schedule_item_id,
            student_id=student_id,
            defaults={'status': status, 'late_minutes': late_minutes}
        )

        if request.headers.get('x-requested-with') == 'XMLHttpRequest':
            from django.http import JsonResponse
            return JsonResponse({'status': 'ok'})

        messages.success(request, 'Посещаемость отмечена')

    return redirect('attendance')


@login_required
def my_risk(request):
    """Страница риска для конкретного студента"""
    if request.user.role != 'student':
        return redirect('dashboard')

    student = request.user.student
    pred = student.risk_predictions.first()
    if not pred:
        from .risk_calculator import calculate_student_risk
        score, level, factors, rec = calculate_student_risk(student)
        pred = RiskPrediction.objects.create(
            student=student, risk_score=score, risk_level=level,
            top_factors=factors, recommended_action=rec
        )

    # Ближайшие задания
    from assignments.models import Assignment
    from datetime import datetime
    upcoming_assignments = Assignment.objects.filter(
        group=student.group,
        deadline__gte=datetime.now().date()
    ).order_by('deadline')[:5]

    return render(request, 'my_risk.html', {
        'student': student,
        'risk': pred,
        'upcoming_assignments': upcoming_assignments,
    })