from django.contrib import messages
from django.db import IntegrityError, transaction
from django.shortcuts import redirect, render
from django.views import View
from django.views.decorators.cache import cache_control
from django.utils.decorators import method_decorator

from codesofy.custom_config import (
    get_global_master_details,
    get_privilleges,
    is_authorized,
    set_menu_items,
    set_user_profile,
)

from usermanagement.models import (
    SystemRole,
    MainFeature,
    SubFeature,
    Privilege,
)


menu_item = "permission_management"


def set_sub_menu_item(sub_menu_item, context):
    return set_menu_items(menu_item, sub_menu_item, context)


def get_role_description(role):
    if hasattr(role, "description"):
        return role.description or "-"
    return "System role permission access"


def get_role_icon_color(index):
    colors = [
        "bg-primary",
        "bg-info",
        "bg-secondary",
        "bg-warning",
        "bg-dark",
        "bg-success",
        "bg-danger",
    ]
    return colors[index % len(colors)]


@method_decorator(
    cache_control(no_cache=True, must_revalidate=True, no_store=True),
    name="dispatch"
)
class RoleManagementView(View):
    template_name = "role-management.html"
    this_feature = "manage_permissions"
    sub_menu_item = "manage_permissions"

    def get_base_context(self, request):
        context = get_global_master_details()
        user_profile = set_user_profile(request, context)

        if user_profile is None:
            return None, None

        get_privilleges(user_profile, context)
        set_sub_menu_item(self.sub_menu_item, context)

        return context, user_profile

    def get(self, request):
        context, user_profile = self.get_base_context(request)

        if user_profile is None:
            return redirect("login")

        if not is_authorized(user_profile, self.this_feature):
            return redirect("unauthorized-access")

        roles = SystemRole.objects.all().order_by("id")
        roles_data = []

        for index, role in enumerate(roles):
            assigned_count = Privilege.objects.filter(
                system_role=role
            ).count()

            roles_data.append({
                "id": role.id,
                "role_name": role.role_name,
                "role_description": get_role_description(role),
                "assigned_features_count": assigned_count,
                "badge_class": "bg-success" if assigned_count > 0 else "bg-secondary",
                "badge_text": f"{assigned_count} features" if assigned_count > 0 else "No features",
                "icon_class": get_role_icon_color(index),
            })

        main_features = MainFeature.objects.all().order_by("id")
        feature_groups = []

        for main_feature in main_features:
            sub_features = SubFeature.objects.filter(
                main_feature=main_feature
            ).order_by("id")

            feature_groups.append({
                "id": main_feature.id,
                "feature_name": main_feature.feature_name,
                "sub_features": sub_features,
                "sub_feature_count": sub_features.count(),
            })

        context["roles_data"] = roles_data
        context["feature_groups"] = feature_groups
        context["total_sub_features"] = SubFeature.objects.count()

        return render(request, self.template_name, context)

    def post(self, request):
        context, user_profile = self.get_base_context(request)

        if user_profile is None:
            return redirect("login")

        if not is_authorized(user_profile, self.this_feature):
            return redirect("unauthorized-access")

        action = request.POST.get("action")

        if action == "create_role":
            return self.create_role(request)

        if action == "assign_features":
            return self.assign_features(request)

        messages.error(request, "Invalid request.")
        return redirect("role-management")

    def create_role(self, request):
        role_name = (request.POST.get("role_name") or "").strip()
        description = (request.POST.get("description") or "").strip()

        if not role_name:
            messages.error(request, "Role name is required.")
            return redirect("role-management")

        if SystemRole.objects.filter(role_name__iexact=role_name).exists():
            messages.error(request, "Role name already exists.")
            return redirect("role-management")

        try:
            with transaction.atomic():
                role = SystemRole(role_name=role_name)

                if hasattr(role, "description"):
                    role.description = description

                role.save()

            messages.success(
                request,
                f'Role "{role.role_name}" created successfully.'
            )

        except IntegrityError:
            messages.error(request, "Role could not be created.")

        return redirect("role-management")

    def assign_features(self, request):
        role_id = request.POST.get("role_id")
        selected_sub_features = request.POST.getlist("sub_features")

        if not role_id:
            messages.error(request, "Role is required.")
            return redirect("role-management")

        try:
            role = SystemRole.objects.get(id=role_id)
        except SystemRole.DoesNotExist:
            messages.error(request, "Selected role not found.")
            return redirect("role-management")

        with transaction.atomic():
            Privilege.objects.filter(system_role=role).delete()

            for sub_feature_id in selected_sub_features:
                sub_feature = SubFeature.objects.filter(id=sub_feature_id).first()

                if sub_feature:
                    Privilege.objects.create(
                        system_role=role,
                        sub_feature=sub_feature,
                    )

        messages.success(
            request,
            f'Permissions updated successfully for "{role.role_name}".'
        )

        return redirect("role-management")