from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

from core.permissions import IsAdmin
from core.responses import success_response

from .models import Menu
from .serializers import MenuNodeSerializer, MenuSerializer


def _is_admin(user):
    return bool(user and (getattr(user, "role", None) == "ADMIN" or user.is_superuser))


class MenuTreeView(APIView):
    """GET /api/v1/menus/ — the sidebar tree, already filtered for the current user.

    A leaf/child is kept when the user has its permission_code (admins keep all).
    A parent is kept only when it has at least one visible child, or it has its
    own route and no children (a standalone top-level link)."""

    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        is_admin = _is_admin(user)
        user_perms = set() if is_admin else set(user.get_all_permissions())

        def allowed(menu):
            if menu.admin_only and not is_admin:
                return False
            if is_admin or not menu.permission_code:
                return True
            return menu.permission_code in user_perms

        menus = list(Menu.objects.filter(is_active=True).order_by("sort_order", "id"))
        by_parent = {}
        for m in menus:
            by_parent.setdefault(m.parent_id, []).append(m)

        def build(parent_id):
            nodes = []
            for m in by_parent.get(parent_id, []):
                children = build(m.id)
                has_children_defined = bool(by_parent.get(m.id))
                if has_children_defined:
                    # A parent shows only if a child survived the filter.
                    if not children:
                        continue
                elif not allowed(m):
                    # A leaf shows only if the user holds its permission.
                    continue
                m._visible_children = children
                nodes.append(m)
            return nodes

        tree = build(None)
        return success_response(MenuNodeSerializer(tree, many=True).data)


class AdminMenuViewSet(viewsets.ModelViewSet):
    """Admin CRUD for menus. /api/v1/menus/admin/menus/ (ADMIN only)."""

    queryset = Menu.objects.all().order_by("sort_order", "id")
    serializer_class = MenuSerializer
    permission_classes = [IsAdmin]
