from functools import wraps

from django.contrib.auth import authenticate, login
from django.contrib.auth.views import redirect_to_login
from django.http import HttpResponseForbidden
from django.shortcuts import redirect

from learn.models import RolePermission, UserProfile


class AdminLoginMiddleware:
    """Legacy login middleware retained for compatibility with group_urls.py."""

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if not request.user.is_authenticated and request.path.startswith('/admin'):
            username = request.POST.get('username')
            password = request.POST.get('password')

            if username and password:
                user = authenticate(request, username=username, password=password)
                if user and user.is_staff:
                    login(request, user)
                    landing_url = get_admin_landing_url(user)
                    if landing_url:
                        return redirect(landing_url)
                    return HttpResponseForbidden(
                        "No admin module has been assigned to this user."
                    )

        return self.get_response(request)


# URL names grouped by the feature keys configured in the role-permission screen.
# Every interactive admin URL must be present here; unknown URLs are denied to
# non-superusers by protect_admin_urlpatterns below.
ADMIN_FEATURE_URLS = {
    "dashboard": {"dashboard"},
    "exam_category": {
        "exam_category", "add_exam_category", "edit_exam_category",
        "delete_exam_category", "exam_category_detail", "delete_examitem",
        "examMaster", "addExam", "editExam", "deleteExamById", "AddSubject",
        "section_selct1", "exam_syllabus", "get_sub_sections", "get_topics",
        "add_exam_syllabus", "update_strength_bulk", "exam_topics",
    },
    "foundation_videos": {
        "foundation_videos_list", "add_foundation_video",
        "edit_foundation_video", "delete_foundation_video",
    },
    "courses": {
        "courses", "course_create", "course_edit", "create-course",
        "select_exam_category", "change_category_status", "delete_course",
        "change_course_status", "Course_Students_list", "update_student_access",
        "add_on_course_list", "create_add_on_course", "delete_add_on_course",
    },
    "course_discount": {
        "course_discount", "add_course_discount", "edit_course_discount",
        "delete_course_discount",
    },
    "batches": {
        "batch_management", "batch_students", "add_batch", "edit_batch",
        "delete_batch_by_Id", "change_batch_status", "remove_batch",
        "assign_batch", "generate_lectures", "save_previewed_lectures",
        "add_batch_time_slot", "delete_batch_slot", "save_monthly_lectures",
        "get_course_students_for_batch", "bulk_assign_batch_students",
    },
    "live_lectures": {
        "live_Lectures", "addLiveLecture", "deleteLiveLecturebyId",
        "editLiveLecture", "uploadVideobyLectureId", "uploadZoomRecording", "zoomRecordingJobStatus",
        "record_zoom_attendance", "Lecture_Details", "lectures_timetable_html",
        "student_endTest", "verify_student", "counseling_groups",
        "add_counseling_group", "edit_counseling_group",
        "delete_counseling_group_by_id", "counseling_groups_detail",
        "add_counseling_students", "delete_counseling_student_by_id",
        "counseling_schedule_list", "add_counseling_schedule",
        "edit_counseling_schedule", "counseling_group_students",
        "delete_counseling_schedule_by_id", "counseling_schedule_detail",
    },
    "test_series": {
        "question-bank", "question-bank-list", "add-question", "upload_excel",
        "upload_question_excel", "upload_question_word",
        "update_question_tags_view", "download_questions_word",
        "add_question_store", "add_mock_questions", "filter_questions",
        "save_mock_questions", "editquestion", "delete-question",
        "mock-test-list", "update_mock_statisctic",
        "calculate_fullmock_statisctic", "calculate_advancemock_statisctic",
        "mock-test-result", "view-solution", "mock-analysis", "abc-analysis",
        "exam_section_analysis", "exam_filter_analysis", "student_analysis",
        "reset_student_exam", "add-mock", "edit_mock_test", "edit_mock",
        "delete_mock", "search_mock", "add_mocktest", "MockTestSeries",
        "addTestSeries", "editTestSeries", "deleteMockTestSeries",
        "vocabulary_questions", "add_vocab_question", "edit_vocab_question",
        "delete_vocab_question", "upload_vocab_excel", "update_question_order",
        "category_selct", "question_tag_list", "add_question_tag",
        "edit_question_tag", "delete_question_tag", "get_mocktests_by_type",
        "upload_question_explaination_video", "regrade_edited_questions",
        "sync_question_explanation_videos",
        "bulk_upload_question_explanation_videos", "question_video_upload_status",
        "auto_tag_question_paragraphs",
    },
    "students": {
        "Students_list", "edit_student", "delete_student", "block_student",
        "Device_login_history", "edit_login_is_lecture", "Student_Profile",
        "addFollowUp", "addComments",
    },
    "faculty_module": {
        "faculty_module", "add_faculty", "edit_faculty",
        "delete_faculty_by_Id", "faculty_details", "add_faculty_leave",
        "delete_faculty_leave", "edit_faculty_leave", "add_faculty_details",
        "add_time_slot", "update_slot_priority", "delete_slot",
    },
    "user_roles": {
        "user_role_management", "delete_user_role", "add_user_role",
        "edit_user_role", "user_profile_list", "add_user", "edit_user",
    },
    "leads": {
        "delete_lead", "Lead_Student_Profile", "Lead_Management",
        "upload_lead_excel", "app_leads", "Lead_View", "Lead_followup",
        "addLead", "save-lead", "edit_lead", "failed_orders",
        "Course_enquiries", "delete_course_enquiries", "Contact_us_enquiries",
        "delete_Contact_us_enquiries", "lead_status", "add_lead_status",
        "edit_lead_status", "delete_lead_status", "lead_source",
        "add_lead_source", "edit_lead_source", "delete_lead_source",
        "send_whatsapp_template",
    },
    "study_materials": {
        "StudyMaterial", "AddStudyMaterial", "deleteMaterials",
        "EditStudyMaterial",
    },
    "resources": {
        "resources", "addResources", "deleteResources", "editResources",
        "resourcesRc", "addResourcesRc", "deleteResourcesRc", "editResourcesRc",
    },
    "contents": {
        "section", "add_section", "edit_section", "delete_section_by_Id",
        "sub-section", "add_sub_section", "edit_sub_section",
        "delete_sub_section_by_Id", "topic-list", "add_topic", "edit_topic",
        "Select_section_topic", "delete_topic", "section_selct",
        "subsection_select", "blog_category", "add_blog_category",
        "edit_blog_category", "delete_blog_category", "blogs-list",
        "add_blogs", "edit_blogs", "delete_blog", "banners", "add_banner",
        "edit_banner", "delete_banner", "media", "addMedia", "editMedia",
        "deleteMediabyId", "notification", "add_notification",
        "edit_notification", "delete_notification", "testimonial",
        "add_testimonial", "edit_testimonial", "delete_testimonial",
        "Results", "add_result", "edit_result", "delete_result",
        "app_notification", "add_app_notification",
    },
    "orders": {"Seles", "Change_Status", "seles_Details"},
    "coupons": {"coupon_code", "add_coupons", "edit_coupon", "delete_coupon"},
    "reports": {
        "report", "sales_reports", "lead_conversion_report",
        "get_courses_by_exam", "potential_sales_report",
        "not_enrolled_students_report", "enrolled_report",
        "selfprep_students_report",
    },
    "zoom_keys": {"zoomkeys", "add_zoomkey", "edit_zoomkey", "delete_zoomkey_by_Id"},
}


EXEMPT_ADMIN_URL_NAMES = {
    "admin_login", "login_process", "admin_logout",
    "cron_notify_lectures", "cron_motivation", "cron_mock_events",
}

SUPERUSER_ONLY_URL_NAMES = {
    "academicYearMaster", "addAcademicYear", "editAcademicYear",
    "deleteAcademicYear", "examValidities", "saveExamValidities",
}

ADD_URL_NAMES = {
    name for names in ADMIN_FEATURE_URLS.values() for name in names
    if name.lower().startswith(("add", "create", "upload", "generate"))
}
ADD_URL_NAMES.update({"course_create", "save-lead", "save_previewed_lectures"})

DELETE_URL_NAMES = {
    name for names in ADMIN_FEATURE_URLS.values() for name in names
    if name.lower().startswith(("delete", "remove"))
}

EDIT_URL_NAMES = {
    name for names in ADMIN_FEATURE_URLS.values() for name in names
    if name.lower().startswith((
        "edit", "change", "update", "block", "reset", "regrade", "assign",
        "verify", "record", "save", "student_end", "calculate", "send",
    ))
}
EDIT_URL_NAMES.discard("save-lead")
EDIT_URL_NAMES.discard("save_previewed_lectures")
EDIT_URL_NAMES.add("bulk_assign_batch_students")

URL_FEATURE_MAP = {
    url_name: feature_key
    for feature_key, url_names in ADMIN_FEATURE_URLS.items()
    for url_name in url_names
}


# Ordered to match the admin sidebar. Dashboard is intentionally excluded for
# role-based users; only superusers use it as their default landing page.
FEATURE_LANDING_URLS = (
    ("exam_category", "/admin/exam_category"),
    ("foundation_videos", "/admin/foundation-videos-list"),
    ("courses", "/admin/courses"),
    ("course_discount", "/admin/course-discount/"),
    ("batches", "/admin/batch_management"),
    ("live_lectures", "/admin/live_lecture"),
    ("test_series", "/admin/mock-test-list?type=1"),
    ("students", "/admin/students"),
    ("faculty_module", "/admin/faculty_module"),
    ("user_roles", "/admin/users-list/"),
    ("leads", "/admin/app_leads"),
    ("study_materials", "/admin/study-material"),
    ("resources", "/admin/resources"),
    ("contents", "/admin/section"),
    ("orders", "/admin/sales"),
    ("coupons", "/admin/coupons"),
    ("reports", "/admin/reports/not-enrolled/"),
    ("zoom_keys", "/admin/zoom-keys/"),
)


def get_admin_landing_url(user):
    if not user or not user.is_authenticated:
        return None

    if user.is_superuser:
        return "/admin/dashboard"

    profile = UserProfile.objects.filter(
        user=user,
        status="Active",
        role__status="Active",
        role__is_deleted=False,
    ).first()

    if not profile:
        return None

    viewable_features = set(
        RolePermission.objects.filter(
            role=profile.role,
            can_view=True,
            feature__is_deleted=False,
        ).values_list("feature__feature_key", flat=True)
    )

    for feature_key, landing_url in FEATURE_LANDING_URLS:
        if feature_key in viewable_features:
            return landing_url

    return None


def _permission_action(url_name):
    if url_name in DELETE_URL_NAMES:
        return "delete"
    if url_name in EDIT_URL_NAMES:
        return "edit"
    if url_name in ADD_URL_NAMES:
        return "add"
    return "view"


def admin_permission_required(feature_key, action="view", superuser_only=False):
    permission_field = f"can_{action}"

    def decorator(view_func):
        @wraps(view_func)
        def wrapped(request, *args, **kwargs):
            if not request.user.is_authenticated:
                return redirect_to_login(request.get_full_path(), login_url="/admin/login")

            if request.user.is_superuser:
                return view_func(request, *args, **kwargs)

            if superuser_only:
                return HttpResponseForbidden("You do not have permission to access this page.")

            profile = UserProfile.objects.filter(
                user=request.user,
                status="Active",
                role__status="Active",
                role__is_deleted=False,
            ).first()

            if not profile or not feature_key:
                return HttpResponseForbidden("You do not have permission to access this page.")

            allowed = RolePermission.objects.filter(
                role=profile.role,
                feature__feature_key=feature_key,
                feature__is_deleted=False,
                **{permission_field: True},
            ).exists()

            if not allowed:
                return HttpResponseForbidden("You do not have permission to access this page.")

            return view_func(request, *args, **kwargs)

        return wrapped
    return decorator


def protect_admin_urlpatterns(urlpatterns):
    """Apply role permissions directly to each admin URL callback."""
    for pattern in urlpatterns:
        url_name = pattern.name

        if url_name in EXEMPT_ADMIN_URL_NAMES:
            continue

        if url_name in SUPERUSER_ONLY_URL_NAMES:
            pattern.callback = admin_permission_required(
                feature_key=None,
                superuser_only=True,
            )(pattern.callback)
            continue

        feature_key = URL_FEATURE_MAP.get(url_name)
        pattern.callback = admin_permission_required(
            feature_key=feature_key,
            action=_permission_action(url_name),
        )(pattern.callback)

    return urlpatterns
