package com.yaoai.admin.menu;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yaoai.admin.auth.StpAdminUtil;
import com.yaoai.admin.menu.dto.AdminMenuNode;
import com.yaoai.domain.entity.AdminMenu;
import com.yaoai.domain.mapper.AdminMenuMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class AdminMenuService {

    private final AdminMenuMapper adminMenuMapper;

    public List<AdminMenuNode> currentMenus() {
        String role = StpAdminUtil.getRole();
        List<AdminMenu> menus = adminMenuMapper.selectList(Wrappers.<AdminMenu>lambdaQuery()
                .eq(AdminMenu::getStatus, 1)
                .orderByAsc(AdminMenu::getSortOrder)
                .orderByAsc(AdminMenu::getId))
                .stream()
                .filter(menu -> visibleToRole(menu, role))
                .toList();

        Map<Long, AdminMenuNode> nodes = new LinkedHashMap<>();
        for (AdminMenu menu : menus) {
            nodes.put(menu.getId(), toNode(menu));
        }

        List<AdminMenuNode> roots = new ArrayList<>();
        for (AdminMenu menu : menus) {
            AdminMenuNode node = nodes.get(menu.getId());
            if (menu.getParentId() == null || menu.getParentId() == 0 || !nodes.containsKey(menu.getParentId())) {
                roots.add(node);
            } else {
                nodes.get(menu.getParentId()).getChildren().add(node);
            }
        }
        sortTree(roots);
        return roots;
    }

    private boolean visibleToRole(AdminMenu menu, String role) {
        if ("SUPER_ADMIN".equals(role)) {
            return true;
        }
        if (!StringUtils.hasText(menu.getAllowedRoles())) {
            return true;
        }
        return Arrays.stream(menu.getAllowedRoles().split(","))
                .map(String::trim)
                .anyMatch(item -> item.equals(role));
    }

    private AdminMenuNode toNode(AdminMenu menu) {
        AdminMenuNode node = new AdminMenuNode();
        node.setId(menu.getId());
        node.setParentId(menu.getParentId());
        node.setTitle(menu.getTitle());
        node.setPath(menu.getPath());
        node.setIcon(menu.getIcon());
        node.setSortOrder(menu.getSortOrder());
        return node;
    }

    private void sortTree(List<AdminMenuNode> nodes) {
        nodes.sort(Comparator.comparing(AdminMenuNode::getSortOrder, Comparator.nullsLast(Integer::compareTo))
                .thenComparing(AdminMenuNode::getId));
        for (AdminMenuNode node : nodes) {
            sortTree(node.getChildren());
        }
    }
}
