from uuid import UUID

from rest_framework import permissions, status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from vbv_lernwelt.core.serializers import UserSerializer
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
from vbv_lernwelt.iam.permissions import has_role_in_course, is_course_session_member
from vbv_lernwelt.learning_mentor.content.praxis_assignment import (
    get_praxis_assignments,
)
from vbv_lernwelt.learning_mentor.content.self_evaluation_feedback import (
    get_self_feedback_evaluation,
)
from vbv_lernwelt.learning_mentor.models import LearningMentor, MentorInvitation
from vbv_lernwelt.learning_mentor.serializers import (
    InvitationSerializer,
    MentorAssignmentStatusSerializer,
    MentorSerializer,
)
from vbv_lernwelt.learnpath.models import Circle
from vbv_lernwelt.notify.email.email_services import EmailTemplate, send_email


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def mentor_summary(request, course_session_id: int):
    course_session = CourseSession.objects.get(id=course_session_id)

    mentor = get_object_or_404(
        LearningMentor, mentor=request.user, course=course_session.course
    )

    participants = mentor.participants.filter(course_session=course_session)
    users = [p.user for p in participants]

    assignments = []
    circle_ids = set()

    praxis_assignments, praxis_assignments_circle_ids = get_praxis_assignments(
        course_session=course_session,
        participants=users,
        evaluation_user=request.user,  # noqa
    )

    (
        self_evaluation_feedbacks,
        self_evaluation_feedback_circle_ids,
    ) = get_self_feedback_evaluation(
        participants=users,
        evaluation_user=request.user,  # noqa
        course=course_session.course,
    )

    circle_ids.update(praxis_assignments_circle_ids)
    circle_ids.update(self_evaluation_feedback_circle_ids)

    assignments.extend(
        MentorAssignmentStatusSerializer(praxis_assignments, many=True).data
    )
    assignments.extend(
        MentorAssignmentStatusSerializer(self_evaluation_feedbacks, many=True).data
    )

    assignments.sort(
        key=lambda x: (-x.get("pending_evaluations", 0), x.get("title", "").lower())
    )
    return Response(
        {
            "participants": [UserSerializer(user).data for user in users],
            "circles": list(
                Circle.objects.filter(id__in=circle_ids).values("id", "title")
            ),
            "assignments": assignments,
        }
    )


class CourseSessionMember(permissions.BasePermission):
    def has_permission(self, request, view):
        return is_course_session_member(
            request.user, view.kwargs.get("course_session_id")
        )


@api_view(["GET"])
@permission_classes([IsAuthenticated, CourseSessionMember])
def list_invitations(request, course_session_id: int):
    course_session = get_object_or_404(CourseSession, id=course_session_id)
    course_session_user = get_object_or_404(
        CourseSessionUser, user=request.user, course_session=course_session
    )
    invitations = MentorInvitation.objects.filter(participant=course_session_user)
    serializer = InvitationSerializer(invitations, many=True)
    return Response(serializer.data)


@api_view(["DELETE"])
@permission_classes([IsAuthenticated, CourseSessionMember])
def delete_invitation(request, course_session_id: int, invitation_id: UUID):
    course_session = get_object_or_404(CourseSession, id=course_session_id)
    course_session_user = get_object_or_404(
        CourseSessionUser, user=request.user, course_session=course_session
    )
    get_object_or_404(
        MentorInvitation, id=invitation_id, participant=course_session_user
    ).delete()

    return Response(status=status.HTTP_204_NO_CONTENT)


@api_view(["POST"])
@permission_classes([IsAuthenticated, CourseSessionMember])
def create_invitation(request, course_session_id: int):
    user = request.user

    course_session = get_object_or_404(CourseSession, id=course_session_id)
    course_session_user = get_object_or_404(
        CourseSessionUser, user=user, course_session=course_session
    )

    serializer = InvitationSerializer(
        data=request.data, context={"course_session_user": course_session_user}
    )

    if not serializer.is_valid():
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    invitation = serializer.save()

    target_url = f"/lernbegleitung/{course_session_id}/invitation/{invitation.id}"

    send_email(
        recipient_email=invitation.email,
        template=EmailTemplate.LEARNING_MENTOR_INVITATION,
        template_data={
            "inviter_name": f"{user.first_name} {user.last_name}",
            "inviter_email": user.email,
            "target_url": f"https://my.vbv-afa.ch{target_url}",
        },
        template_language=request.user.language,
        fail_silently=True,
    )

    return Response(serializer.data)


@api_view(["GET"])
@permission_classes([IsAuthenticated, CourseSessionMember])
def list_user_mentors(request, course_session_id: int):
    course_session = get_object_or_404(CourseSession, id=course_session_id)

    course_session_user = get_object_or_404(
        CourseSessionUser, user=request.user, course_session=course_session
    )

    mentors = LearningMentor.objects.filter(
        course=course_session.course, participants=course_session_user
    )

    return Response(MentorSerializer(mentors, many=True).data)


@api_view(["DELETE"])
@permission_classes([IsAuthenticated, CourseSessionMember])
def remove_self_from_mentor(request, course_session_id: int, mentor_id: int):
    course_session = get_object_or_404(CourseSession, id=course_session_id)
    course_session_user = get_object_or_404(
        CourseSessionUser, user=request.user, course_session=course_session
    )

    mentor = get_object_or_404(LearningMentor, id=mentor_id)

    mentor.participants.remove(course_session_user)

    return Response(status=status.HTTP_204_NO_CONTENT)


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def accept_invitation(request, course_session_id: int):
    course_session = get_object_or_404(CourseSession, id=course_session_id)
    invitation = get_object_or_404(
        MentorInvitation, id=request.data.get("invitation_id")
    )

    if invitation.participant.course_session != course_session:
        return Response(
            data={"message": "Invalid invitation", "code": "invalidInvitation"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    if LearningMentor.objects.filter(
        mentor=request.user, course=course_session.course
    ).exists():
        mentor = LearningMentor.objects.get(
            mentor=request.user, course=course_session.course
        )
    else:
        if has_role_in_course(request.user, course_session.course):
            return Response(
                data={
                    "message": "User already has a role in this course",
                    "code": "existingRole",
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        mentor = LearningMentor.objects.create(
            mentor=request.user, course=course_session.course
        )

    mentor.participants.add(invitation.participant)
    invitation.delete()

    return Response(
        {
            "course_slug": course_session.course.slug,
            "user": UserSerializer(invitation.participant.user).data,
        }
    )
