from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.models import Course, CourseSession, CourseSessionUser
from vbv_lernwelt.course_session_group.models import CourseSessionGroup
from vbv_lernwelt.learning_mentor.models import LearningMentor
from vbv_lernwelt.learnpath.models import LearningSequence


def has_course_access_by_page_request(request, obj):
    return has_course_access(request.user, obj.specific.get_course().id)


def has_course_access(user, course_id):
    if user.is_superuser:
        return True

    if CourseSessionGroup.objects.filter(
        course_session__course_id=course_id, supervisor=user
    ).exists():
        return True

    if LearningMentor.objects.filter(course_id=course_id, mentor=user).exists():
        return True

    return CourseSessionUser.objects.filter(
        course_session__course_id=course_id, user=user
    ).exists()


def has_course_session_access(user, course_session_id: int):
    if user.is_superuser:
        return True

    return CourseSessionUser.objects.filter(
        course_session_id=course_session_id, user=user
    ).exists()


def is_user_mentor(mentor: User, participant_user_id: str, course_session_id: int):
    csu = CourseSessionUser.objects.filter(
        course_session_id=course_session_id, user_id=participant_user_id
    ).first()

    if csu is None:
        return False

    return LearningMentor.objects.filter(
        course_id=csu.course_session.course_id, mentor=mentor, participants=csu
    ).exists()


def is_course_session_expert(user, course_session_id: int):
    if user.is_superuser:
        return True

    course_session = CourseSession.objects.get(id=course_session_id)

    is_supervisor = CourseSessionGroup.objects.filter(
        supervisor=user, course_session=course_session
    ).exists()

    is_expert = CourseSessionUser.objects.filter(
        course_session=course_session,
        user=user,
        role=CourseSessionUser.Role.EXPERT,
    ).exists()

    return is_supervisor or is_expert


def is_course_session_member(user, course_session_id: int | None = None):
    if course_session_id is None:
        return False

    return CourseSessionUser.objects.filter(
        course_session_id=course_session_id,
        user=user,
        role=CourseSessionUser.Role.MEMBER,
    ).exists()


def can_evaluate_assignments(
    evaluation_user: User, course_session_id: int, assignment_user_id: str | None = None
):
    if evaluation_user.is_superuser:
        return True

    is_supervisor = CourseSessionGroup.objects.filter(
        supervisor=evaluation_user, course_session__id=course_session_id
    ).exists()

    is_expert = CourseSessionUser.objects.filter(
        course_session_id=course_session_id,
        user=evaluation_user,
        role=CourseSessionUser.Role.EXPERT,
    ).exists()

    is_mentor = is_user_mentor(
        mentor=evaluation_user,
        participant_user_id=assignment_user_id,
        course_session_id=course_session_id,
    )

    return is_supervisor or is_expert or is_mentor


def course_sessions_for_user_qs(user):
    if user.is_superuser:
        return CourseSession.objects.all()

    course_sessions = CourseSession.objects.filter(coursesessionuser__user=user)

    return course_sessions


def is_circle_expert(user, course_session_id: int, learning_sequence_id: int) -> bool:
    if user.is_superuser:
        return True

    try:
        learning_sequence = LearningSequence.objects.get(id=learning_sequence_id)
    except LearningSequence.DoesNotExist:
        return False

    circle_id = learning_sequence.get_parent().circle.id

    return CourseSessionUser.objects.filter(
        course_session_id=course_session_id,
        user=user,
        role=CourseSessionUser.Role.EXPERT,
        expert__id=circle_id,
    ).exists()


def can_view_course_session_group_statistics(
    user: User, group: CourseSessionGroup
) -> bool:
    if user.is_superuser:
        return True

    return user in group.supervisor.all()


def can_view_course_session_progress(user: User, course_session: CourseSession) -> bool:
    return CourseSessionUser.objects.filter(
        course_session=course_session,
        user=user,
        role=CourseSessionUser.Role.MEMBER,
    ).exists()


def can_view_course_session(user: User, course_session: CourseSession) -> bool:
    if user.is_superuser:
        return True

    if CourseSessionGroup.objects.filter(
        course_session=course_session, supervisor=user
    ).exists():
        return True

    return CourseSessionUser.objects.filter(
        course_session=course_session,
        user=user,
    ).exists()


def has_role_in_course(user: User, course: Course) -> bool:
    if CourseSessionUser.objects.filter(
        course_session__course=course, user=user
    ).exists():
        return True

    if LearningMentor.objects.filter(course=course, mentor=user).exists():
        return True

    if CourseSessionGroup.objects.filter(course=course, supervisor=user).exists():
        return True

    return False


def can_view_profile(user: User, profile_user: CourseSessionUser) -> bool:
    if user.is_superuser:
        return True

    if user == profile_user.user:
        return True

    if is_course_session_expert(user, profile_user.course_session.id) or is_user_mentor(
        mentor=user,
        participant_user_id=profile_user.user.id,
        course_session_id=profile_user.course_session.id,
    ):
        return True

    return False


def can_view_course_completions(
    user: User, course_session_id: int, target_user_id: str
) -> bool:
    return (
        user.id == target_user_id
        or is_course_session_expert(user=user, course_session_id=course_session_id)
        or is_user_mentor(
            mentor=user,
            participant_user_id=target_user_id,
            course_session_id=course_session_id,
        )
    )


def can_complete_learning_content(user: User, course_session_id: int) -> bool:
    return is_course_session_member(
        user, course_session_id
    ) or is_course_session_expert(user, course_session_id)


def course_session_permissions(user: User, course_session_id: int) -> list[str]:
    return _action_list(
        {
            "complete-learning-content": can_complete_learning_content(
                user, course_session_id
            ),
        }
    )


def _action_list(actions: dict[str, bool]):
    return [action for action, allowed in actions.items() if allowed]
