#!/usr/bin/env python
# @Project ：django_base_ai
# @File    : menu.py
# @Author  : cx
# @Time    : 11/2/2025
# @Desc    : 菜单与路由树 CRUD、初始化。
import logging

from rest_framework import serializers
from rest_framework.decorators import action

from django_base_ai.system.models import Menu, MenuButton
from django_base_ai.system.views.menu_button import MenuButtonInitSerializer
from django_base_ai.utils.json_response import ErrorResponse, SuccessResponse
from django_base_ai.utils.serializers import CustomModelSerializer
from django_base_ai.utils.viewset import CustomModelViewSet

logger = logging.getLogger(__name__)


class MenuSerializer(CustomModelSerializer):
    """
    菜单表的简单序列化器
    """

    menu_permission = serializers.SerializerMethodField(read_only=True)
    has_child = serializers.SerializerMethodField()

    def get_menu_permission(self, instance):
        queryset = instance.menuPermission.order_by("-name").values_list("name", flat=True)
        result = queryset if queryset else None
        logger.debug(f"菜单 {instance.name} 权限列表: {list(result) if result else []}")
        return result

    def get_has_child(self, instance):
        has_child = True if Menu.objects.filter(parent=instance.id).count() > 0 else False
        logger.debug(f"菜单 {instance.name} 是否有子菜单: {has_child}")
        return has_child

    class Meta:
        model = Menu
        fields = "__all__"
        read_only_fields = ["id"]


class MenuCreateSerializer(CustomModelSerializer):
    class Meta:
        model = Menu
        fields = "__all__"
        read_only_fields = ["id"]


class MenuInitSerializer(CustomModelSerializer):
    """
    递归深度获取数信息(用于生成初始化json文件)
    """

    name = serializers.CharField(required=False)
    children = serializers.SerializerMethodField()
    menu_button = serializers.SerializerMethodField()

    def get_children(self, obj: Menu):
        logger.debug(f"获取菜单 {obj.name} 的子菜单")
        data = []
        instance = Menu.objects.filter(parent_id=obj.id)
        if instance:
            serializer = MenuInitSerializer(instance=instance, many=True)
            data = serializer.data
        logger.debug(f"菜单 {obj.name} 子菜单数量: {len(data)}")
        return data

    def get_menu_button(self, obj: Menu):
        logger.debug(f"获取菜单 {obj.name} 的按钮权限")
        data = []
        instance = obj.menuPermission.order_by("method")
        if instance:
            data = list(instance.values("name", "value", "api", "method"))
        logger.debug(f"菜单 {obj.name} 按钮权限数量: {len(data)}")
        return data

    def save(self, **kwargs):
        logger.info(f"开始保存菜单初始化数据: {self.initial_data.get('name', '未知')}")
        instance = super().save(**kwargs)
        logger.info(f"菜单 {instance.name} 基础信息已保存，ID: {instance.id}")
        children = self.initial_data.get("children")
        menu_button = self.initial_data.get("menu_button")
        # 菜单表
        if children:
            for menu_data in children:
                menu_data["parent"] = instance.id
                filter_data = {
                    "name": menu_data["name"],
                    "path": menu_data["path"],
                    "component": menu_data["component"],
                }
                instance_obj = Menu.objects.filter(**filter_data).first()
                if instance_obj and not self.initial_data.get("reset"):
                    continue
                serializer = MenuInitSerializer(instance_obj, data=menu_data, request=self.request)
                serializer.is_valid(raise_exception=True)
                serializer.save()
                logger.info(f"子菜单 {menu_data['name']} 已保存")
        # 菜单按钮
        if menu_button:
            logger.info(f"保存菜单按钮，数量: {len(menu_button)}")
            for menu_button_data in menu_button:
                menu_button_data["menu"] = instance.id
                filter_data = {"menu": menu_button_data["menu"], "value": menu_button_data["value"]}
                instance_obj = MenuButton.objects.filter(**filter_data).first()
                serializer = MenuButtonInitSerializer(instance_obj, data=menu_button_data, request=self.request)
                serializer.is_valid(raise_exception=True)
                serializer.save()
        logger.info(f"菜单 {instance.name} 初始化完成")
        return instance

    class Meta:
        model = Menu
        fields = [
            "name",
            "path",
            "component",
            "redirect",
            "sort",
            "status",
            "meta",
            "parent",
            "children",
            "menu_button",
            "creator",
            "dept_belong_id",
        ]
        extra_kwargs = {"creator": {"write_only": True}, "dept_belong_id": {"write_only": True}}
        read_only_fields = ["id", "children"]


class WebRouterSerializer(CustomModelSerializer):
    """
    前端菜单路由的简单序列化器
    """

    menu_permission = serializers.SerializerMethodField(read_only=True)

    def get_menu_permission(self, instance):
        # 判断是否是超级管理员
        if self.request.user.is_superuser:
            return instance.menuPermission.values_list("value", flat=True)
        else:
            # 根据当前角色获取权限按钮id集合
            permission_ids = self.request.user.role.values_list("permission", flat=True)
            queryset = instance.menuPermission.filter(id__in=permission_ids, menu=instance.id).values_list(
                "value", flat=True
            )
            if queryset:
                return queryset
            else:
                return None

    class Meta:
        model = Menu
        fields = ("id", "parent", "name", "path", "component", "redirect", "sort", "status", "meta", "menu_permission")
        read_only_fields = ["id"]


# 递归获取菜单
def get_child_menu(childs, menu_ids, tree_ids, is_admin=False):
    """
    :param 当前节点:
    :return [{"id": child.id, "title": child.title, "children": []}]:
    """
    children = []
    if childs:
        for child in childs:
            if child.id in menu_ids and child.id not in tree_ids:
                menu_button_list = list(MenuButton.objects.filter(menu=child).values("id", "name", "value"))
                data = {
                    "id": child.id,
                    "path": child.path,
                    "name": child.name,
                    "component": child.component,
                    "meta": child.meta,
                    "label": child.meta.get("title", "") if child.meta else "",
                    "menu_button_list": menu_button_list,
                    "parent_id": child.parent.id,
                    "parent_name": child.parent.name,
                }
                tree_ids.append(child.id)
                if is_admin:
                    _childs = Menu.objects.filter(parent=child).order_by("sort")
                else:
                    _childs = Menu.objects.filter(parent=child, status=True).order_by("sort")
                if _childs:
                    data["children"] = get_child_menu(_childs, menu_ids, tree_ids, is_admin)
                children.append(data)
    return children


class MenuViewSet(CustomModelViewSet):
    """
    菜单管理接口
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """

    queryset = Menu.objects.all()
    serializer_class = MenuSerializer
    create_serializer_class = MenuCreateSerializer
    update_serializer_class = MenuCreateSerializer
    # 模糊查询 包含
    search_fields = ["meta__title"]
    # 精确查询 等于
    filter_fields = ["parent", "name", "status"]

    # extra_filter_backends = []
    @action(methods=["GET"], detail=False, permission_classes=[])
    def web_router(self, request):
        """用于前端获取当前角色的路由"""
        user = request.user
        tree, tree_ids, menus_result = [], [], []
        menu_ids = (
            Menu.objects.values_list("id", flat=True)
            if user.is_superuser
            else user.role.values_list("menu__id", flat=True)
        )
        menus_result = Menu.objects.filter(id__in=menu_ids, status=True, parent=None).order_by("sort")
        for menu in menus_result:
            if menu.id not in tree_ids:
                menu_button_list = list(MenuButton.objects.filter(menu=menu).values("id", "name", "value"))
                menu_data = {
                    "id": menu.id,
                    "path": menu.path,
                    "name": menu.name,
                    "component": menu.component,
                    "meta": menu.meta,
                    "label": menu.meta.get("title", "") if menu.meta else "",
                    "menu_button_list": menu_button_list,
                    "parent_id": menu.parent.id if menu.parent else None,
                    "parent_name": menu.parent.name if menu.parent else None,
                }
                tree_ids.append(menu.id)
                childs = Menu.objects.filter(parent=menu, status=True).order_by("sort")
                if childs:
                    menu_data["children"] = get_child_menu(childs, menu_ids, tree_ids)
                tree.append(menu_data)
        if len(tree) == 0:
            return ErrorResponse(
                code=-1,
                msg="您暂无登录系统权限",
            )
        return SuccessResponse(data=tree, total=len(tree))

    def list(self, request):
        """懒加载"""
        params = request.query_params
        parent = params.get("parent", None)
        if params:
            if parent:
                queryset = self.queryset.filter(parent=parent)
            else:
                queryset = self.queryset
        else:
            queryset = self.queryset.filter(parent__isnull=True)
        queryset = self.filter_queryset(queryset)
        serializer = MenuSerializer(queryset, many=True, request=request)
        data = serializer.data
        return SuccessResponse(data=data)
