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, JsonResponse
from .models import Group, Subject, ScheduleItem, Room, Attendance, AcademicDebt, Olympiad
from users.models import Teacher, Student
from risk.models import RiskPrediction
from datetime import datetime, timedelta
import calendar


# ==================== РАСПИСАНИЕ ====================

@login_required
def schedule_view(request):
    """Главная страница расписания с календарём"""
    groups = Group.objects.all()
    selected_group_id = request.GET.get('group')
    selected_date = request.GET.get('date')

    # Студент видит только свою группу
    if request.user.role == 'student':
        student = request.user.student
        groups = Group.objects.filter(id=student.group.id)
        selected_group = student.group
    elif request.user.role == 'parent':
        parent = request.user.parent
        if parent.children.exists():
            groups = Group.objects.filter(students__in=parent.children.all()).distinct()
            selected_group = groups.first()
        else:
            selected_group = None
    else:
        if selected_group_id:
            selected_group = get_object_or_404(Group, id=selected_group_id)
        else:
            selected_group = groups.first()

    # Если дата не выбрана — сегодня
    if not selected_date:
        selected_date = datetime.now().strftime('%Y-%m-%d')

    if selected_group:
        schedule_items = ScheduleItem.objects.filter(
            group=selected_group,
            date=selected_date
        ).select_related('subject', 'teacher', 'room').order_by('start_time')
    else:
        schedule_items = []

    # Генерация недели для календаря
    current_date = datetime.strptime(selected_date, '%Y-%m-%d')
    week_start = current_date - timedelta(days=current_date.weekday())
    week_dates = [week_start + timedelta(days=i) for i in range(7)]

    context = {
        'groups': groups,
        'selected_group': selected_group,
        'selected_date': selected_date,
        'week_dates': week_dates,
        'schedule_items': schedule_items,
        'subjects': Subject.objects.all(),
        'teachers': Teacher.objects.all(),
        'rooms': Room.objects.all(),
        'today': datetime.now().date(),
    }
    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':
        group_id = request.POST.get('group_id')
        date = request.POST.get('date')
        start_time = request.POST.get('start_time')

        # Проверка на существующее занятие
        exists = ScheduleItem.objects.filter(
            group_id=group_id,
            date=date,
            start_time=start_time
        ).exists()

        if exists:
            messages.error(request, 'В это время уже есть занятие!')
            return redirect('schedule')

        ScheduleItem.objects.create(
            group_id=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,
            date=date,
            start_time=start_time,
            end_time=request.POST.get('end_time'),
            topic=request.POST.get('topic', ''),
        )
        messages.success(request, 'Занятие добавлено')
    return redirect('schedule')


@login_required
def edit_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)

    if request.method == 'POST':
        item.subject_id = request.POST.get('subject_id')
        item.teacher_id = request.POST.get('teacher_id')
        item.room_id = request.POST.get('room_id') or None
        item.date = request.POST.get('date')
        item.start_time = request.POST.get('start_time')
        item.end_time = request.POST.get('end_time')
        item.topic = request.POST.get('topic', '')
        item.save()
        messages.success(request, 'Занятие обновлено')
        return redirect('schedule')

    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 get_schedule_item_json(request, item_id):
    item = get_object_or_404(ScheduleItem, id=item_id)
    data = {
        'id': item.id,
        'start_time': item.start_time.strftime('%H:%M'),
        'end_time': item.end_time.strftime('%H:%M'),
        'subject_id': item.subject.id,
        'teacher_id': item.teacher.id,
        'room_id': item.room.id if item.room else '',
        'topic': item.topic,
    }
    return JsonResponse(data)


@login_required
def export_schedule(request):
    """Экспорт расписания в Excel на выбранную неделю"""
    from openpyxl import Workbook
    from openpyxl.styles import Alignment, Font, PatternFill, Border, Side
    from datetime import datetime, timedelta

    group_id = request.GET.get('group')
    date_str = request.GET.get('date')  # Получаем дату из запроса

    if not group_id:
        messages.error(request, 'Выберите группу')
        return redirect('schedule')

    group = get_object_or_404(Group, id=group_id)

    # Если дата не указана - используем сегодня
    if date_str:
        current_date = datetime.strptime(date_str, '%Y-%m-%d').date()
    else:
        current_date = datetime.now().date()

    # Вычисляем начало недели (понедельник)
    week_start = current_date - timedelta(days=current_date.weekday())
    week_dates = [week_start + timedelta(days=i) for i in range(7)]

    # Получаем расписание на всю неделю
    schedule_items = ScheduleItem.objects.filter(
        group=group,
        date__gte=week_start,
        date__lte=week_start + timedelta(days=6)
    ).select_related('subject', 'teacher', 'room').order_by('date', 'start_time')

    # Группируем по датам
    schedule_by_date = {}
    for item in schedule_items:
        date_str_item = item.date.strftime('%Y-%m-%d')
        if date_str_item not in schedule_by_date:
            schedule_by_date[date_str_item] = []
        schedule_by_date[date_str_item].append(item)

    wb = Workbook()
    ws = wb.active
    ws.title = f"Расписание {group.name}"

    # Заголовок
    ws['A1'] = f"Расписание группы {group.name}"
    ws['A1'].font = Font(size=16, bold=True)
    ws.merge_cells('A1:H1')

    ws['A2'] = f"Неделя с {week_start.strftime('%d.%m.%Y')} по {(week_start + timedelta(days=6)).strftime('%d.%m.%Y')}"
    ws['A2'].font = Font(size=12, italic=True)
    ws.merge_cells('A2:H2')

    # Заголовки дней недели
    weekdays_rus = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье']

    # Стиль для заголовков
    header_font = Font(bold=True, color="FFFFFF")
    header_fill = PatternFill(start_color="4395AB", end_color="4395AB", fill_type="solid")
    header_alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)

    for i, (date, weekday_name) in enumerate(zip(week_dates, weekdays_rus), start=2):
        cell = ws.cell(row=4, column=i, value=f"{weekday_name}\n{date.strftime('%d.%m')}")
        cell.font = header_font
        cell.fill = header_fill
        cell.alignment = header_alignment
        ws.column_dimensions[chr(64 + i)].width = 25

    ws.cell(row=4, column=1, value="Время")
    ws.cell(row=4, column=1).font = header_font
    ws.cell(row=4, column=1).fill = header_fill
    ws.cell(row=4, column=1).alignment = header_alignment
    ws.column_dimensions['A'].width = 15

    # Временные слоты
    time_slots = [
        ('09:00', '10:30'), ('10:45', '12:15'),
        ('12:45', '14:15'), ('14:30', '16:00'),
        ('16:15', '17:45'), ('18:00', '19:30')
    ]

    # Создаем словарь для быстрого доступа
    schedule_dict = {}
    for date in week_dates:
        date_key = date.strftime('%Y-%m-%d')
        schedule_dict[date_key] = {}
        for item in schedule_by_date.get(date_key, []):
            start_key = item.start_time.strftime('%H:%M')
            schedule_dict[date_key][start_key] = item

    # Заполняем расписание
    border = Border(
        left=Side(style='thin'),
        right=Side(style='thin'),
        top=Side(style='thin'),
        bottom=Side(style='thin')
    )

    for row_idx, (start, end) in enumerate(time_slots, start=5):
        ws.cell(row=row_idx, column=1, value=f"{start}-{end}")
        ws.cell(row=row_idx, column=1).alignment = Alignment(horizontal='center', vertical='center')
        ws.cell(row=row_idx, column=1).border = border

        for col_idx, date in enumerate(week_dates, start=2):
            date_key = date.strftime('%Y-%m-%d')
            item = schedule_dict.get(date_key, {}).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}"
                if item.topic:
                    cell_value += f"\n{item.topic}"

                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.cell(row=row_idx, column=col_idx).border = border
                ws.row_dimensions[row_idx].height = 80
            else:
                ws.cell(row=row_idx, column=col_idx, value="—")
                ws.cell(row=row_idx, column=col_idx).alignment = Alignment(horizontal='center', vertical='center')
                ws.cell(row=row_idx, column=col_idx).border = border

    response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    response[
        'Content-Disposition'] = f'attachment; filename="schedule_{group.name}_{week_start.strftime("%Y%m%d")}.xlsx"'
    wb.save(response)
    return response

# ==================== ПОСЕЩАЕМОСТЬ ====================

@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_str = request.GET.get('selected_date')

    # Если дата не выбрана - сегодня
    if not selected_date_str:
        selected_date = datetime.now().date()
    else:
        selected_date = datetime.strptime(selected_date_str, '%Y-%m-%d').date()

    selected_group = None
    schedule_items = []

    if selected_group_id:
        selected_group = get_object_or_404(Group, id=selected_group_id)
        schedule_items = ScheduleItem.objects.filter(
            group=selected_group,
            date=selected_date
        ).select_related('subject', 'teacher', 'room').order_by('start_time')

    context = {
        'groups': groups,
        'selected_group': selected_group,
        'selected_date': selected_date,
        'schedule_items': schedule_items,
    }
    return render(request, 'attendance_mark.html', context)


@login_required
def mark_attendance(request):
    """Страница отметки посещаемости для конкретного занятия"""
    schedule_item_id = request.GET.get('schedule_item_id')

    if not schedule_item_id:
        messages.error(request, 'Занятие не выбрано')
        return redirect('attendance_view')

    schedule_item = get_object_or_404(ScheduleItem, id=schedule_item_id)
    students = Student.objects.filter(group=schedule_item.group)

    # Создаем список студентов с их отметками
    students_with_attendance = []
    for student in students:
        att = Attendance.objects.filter(schedule_item=schedule_item, student=student).first()
        students_with_attendance.append({
            'student': student,
            'attendance': att,
        })

    if request.method == 'POST':
        for student in students:
            status = request.POST.get(f'status_{student.id}', 'present')
            late_minutes = int(request.POST.get(f'late_{student.id}', 0))

            Attendance.objects.update_or_create(
                schedule_item=schedule_item,
                student=student,
                defaults={'status': status, 'late_minutes': late_minutes}
            )
        messages.success(request, 'Посещаемость сохранена')
        return redirect('attendance_view')

    context = {
        'schedule_item': schedule_item,
        'students_with_attendance': students_with_attendance,
    }
    return render(request, 'mark_attendance.html', context)


@login_required
def get_schedule_json(request):
    """Получение расписания для выбранной группы и дня недели (AJAX)"""
    group_id = request.GET.get('group')
    weekday = request.GET.get('weekday')

    if not group_id or not weekday:
        return JsonResponse([], safe=False)

    schedule_items = ScheduleItem.objects.filter(
        group_id=group_id,
        weekday=weekday
    ).select_related('subject')

    data = [{
        'id': item.id,
        'subject_name': item.subject.name,
        'start_time': item.start_time.strftime('%H:%M'),
        'end_time': item.end_time.strftime('%H:%M'),
    } for item in schedule_items]

    return JsonResponse(data, safe=False)


@login_required
def get_students_for_attendance(request):
    """Получение списка студентов для отметки посещаемости (AJAX)"""
    schedule_id = request.GET.get('schedule')
    schedule_item = get_object_or_404(ScheduleItem, id=schedule_id)

    students = Student.objects.filter(group=schedule_item.group)

    # Получаем текущие отметки
    attendances = {att.student_id: att for att in Attendance.objects.filter(schedule_item=schedule_item)}

    data = {
        'schedule_item_id': schedule_item.id,
        'group_name': schedule_item.group.name,
        'weekday': schedule_item.weekday,
        'start_time': schedule_item.start_time.strftime('%H:%M'),
        'end_time': schedule_item.end_time.strftime('%H:%M'),
        'subject_name': schedule_item.subject.name,
        'students': [{
            'id': s.id,
            'name': f"{s.last_name} {s.first_name}",
            'status': attendances[s.id].status if s.id in attendances else 'present',
            'late_minutes': attendances[s.id].late_minutes if s.id in attendances else 0,
        } for s in students]
    }

    return JsonResponse(data)


# ==================== ДАШБОРД ====================

@login_required
def dashboard(request):
    """Главная страница с рисками (только для преподавателей и выше)"""
    # Студент и родитель перенаправляются
    if request.user.role == 'student':
        return redirect('my_risk')
    if request.user.role == 'parent':
        return redirect('child_progress')

    students = Student.objects.select_related('user', 'group').all()

    stats = {'low': 0, 'medium': 0, 'high': 0, 'critical': 0}
    high_risk_list = []

    for student in students:
        latest = student.risk_predictions.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
            )
        stats[latest.risk_level] += 1
        if latest.risk_level in ['high', 'critical']:
            high_risk_list.append({'student': student, 'risk': latest})

    total = sum(stats.values()) or 1

    context = {
        'today': datetime.now(),
        'stats': {
            'low': stats['low'], 'medium': stats['medium'],
            'high': stats['high'], 'critical': stats['critical'],
            'low_percent': round(stats['low'] / total * 100, 1),
            'medium_percent': round(stats['medium'] / total * 100, 1),
            'high_percent': round(stats['high'] / total * 100, 1),
            'critical_percent': round(stats['critical'] / total * 100, 1),
        },
        '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:
        return redirect('dashboard')

    students = Student.objects.all()
    risk_data = []
    for student in students:
        pred = student.risk_predictions.first()
        if not pred:
            from risk.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
            )
        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 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.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
    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,
    })


# ==================== РОДИТЕЛЬ ====================

@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.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

    # Расписание группы ребёнка
    schedule_items = []
    if selected_child and selected_child.group:
        schedule_items = ScheduleItem.objects.filter(group=selected_child.group).select_related('subject', 'teacher',
                                                                                                'room')[:5]

    return render(request, 'child_progress.html', {
        'children': children,
        'selected_child': selected_child,
        'risk': pred,
        'schedule_items': schedule_items,
    })