from rest_framework import status
from rest_framework.exceptions import ValidationError

from api.admin_permission_conf import PERMISSIONS
from api.translation import __
from api.utils import log_critical_error, get_exception_detail
from api.validator import BaseValidator
from api.views.admin.base import AdminApiBase

class PermissionList(AdminApiBase):
    def validate_request(self, request):
        rules = {
            "filter": "nullable",
            "page": "nullable",
            "per_page": "nullable",
            "sort_by": "nullable",
            "order_by": "nullable",
        }
        validator = BaseValidator(request.data, rules, {})
        error = validator.validate()
        if error:
            raise ValidationError(error)

    def post(self, request):
        try:
            self.api_log_skip_outgoing_data=True
            self.validate_request(request)
            data = self.get_data(request)
            return self.api_response(data=data)
        except ValidationError as e:
            first_message = e.detail['error']
            errors = e.detail['errors']
            return self.api_response(error=first_message,errors=errors,code=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            e_details = get_exception_detail(e)
            log_critical_error(user_id=None,descr=e_details['descr'],url=e_details['url'],trace=e_details['trace'])
            return self.api_response(error=__("message.internal_server_error"),code=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def get_data(self,request):
        filters = request.data.get("filter") or {}
        search_query = filters.get("permissions", "") or request.data.get("permissions", "")
        if search_query:
            search_query = str(search_query).lower()

        groups = {}

        sorted_permissions = sorted(list(PERMISSIONS))

        for val in sorted_permissions:
            prefix = val.split(';')[0]
            name = __("permission.admin." + val)

            # Check if this permission or its group matches the search query
            if search_query:
                if search_query not in prefix.lower() and search_query not in name.lower():
                    continue

            if prefix not in groups:
                groups[prefix] = []
            
            groups[prefix].append({
                "code": val,
                "name": name
            })

        group_keys = list(groups.keys())
        total = len(group_keys)

        order_by = request.data.get("order_by", "asc")
        is_desc = str(order_by).lower() == "desc"

        if search_query:
            group_keys_matching = sorted([k for k in group_keys if search_query in k.lower()], reverse=is_desc)
            group_keys_other = sorted([k for k in group_keys if search_query not in k.lower()], reverse=is_desc)
            group_keys = group_keys_matching + group_keys_other
        else:
            group_keys = sorted(group_keys, reverse=is_desc)

        page, per_page = self.parse_pagination(request)

        if per_page != -1:
            start_index = (page - 1) * per_page
            end_index = start_index + per_page
            paginated_keys = group_keys[start_index:end_index]
        else:
            paginated_keys = group_keys

        paginated_groups = {k: groups[k] for k in paginated_keys}

        return {
            "page": page,
            "per_page": per_page,
            "total": total,
            "group": paginated_groups
        }