package com.qqchen.deploy.backend.system.service.impl;

import com.qqchen.deploy.backend.system.converter.MenuConverter;
import com.qqchen.deploy.backend.system.entity.Menu;
import com.qqchen.deploy.backend.system.entity.Permission;
import com.qqchen.deploy.backend.framework.annotation.ServiceType;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.system.model.MenuDTO;
import com.qqchen.deploy.backend.system.model.UserDTO;
import com.qqchen.deploy.backend.system.model.query.MenuQuery;
import com.qqchen.deploy.backend.system.model.response.MenuPermissionTreeResponse;
import com.qqchen.deploy.backend.system.model.response.MenuResponse;
import com.qqchen.deploy.backend.system.repository.IMenuRepository;
import com.qqchen.deploy.backend.system.repository.IPermissionRepository;
import com.qqchen.deploy.backend.system.service.IMenuService;
import com.qqchen.deploy.backend.system.service.IUserService;
import com.qqchen.deploy.backend.system.service.IRoleService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Optional;

import static com.qqchen.deploy.backend.framework.annotation.ServiceType.Type.DATABASE;

@Slf4j
@Service
@ServiceType(DATABASE)
public class MenuServiceImpl extends BaseServiceImpl<Menu, MenuDTO, MenuQuery, Long> implements IMenuService {

    @Resource
    private IMenuRepository menuRepository;

    @Resource
    private IPermissionRepository permissionRepository;

    @Resource
    private MenuConverter menuConverter;

    @Resource
    private IUserService userService;

    @Resource
    private IRoleService roleService;

    @Override
    public List<MenuResponse> getMenuTree() {
        List<Menu> allMenus = menuRepository.findByDeletedFalseOrderBySort();
        List<MenuDTO> menuDTOs = menuConverter.toDtoList(allMenus);
        List<MenuDTO> menuTree = buildMenuTree(menuDTOs);
        return menuConverter.toResponseList(menuTree);
    }

    @Override
    public List<MenuResponse> getUserMenus() {
        // 1. 获取当前用户信息(使用内部服务方法)
        UserDTO user = userService.getCurrentUser();

        // 2. 通过roleService获取用户的所有角色ID
        List<Long> roleIds = roleService.getUserRoleIds(user.getId());

        // 3. 获取这些角色关联的所有菜单
        List<Menu> userMenus = menuRepository.findByRoleIdsAndEnabledTrue(roleIds);

        // 4. 转换为DTO并构建树形结构
        List<MenuDTO> menuDTOs = menuConverter.toDtoList(userMenus);
        List<MenuDTO> menuTree = buildMenuTree(menuDTOs);

        // 5. 转换为响应对象
        return menuConverter.toResponseList(menuTree);
    }

    @Override
    public List<MenuPermissionTreeResponse> getPermissionTree() {
        // 1. 获取所有菜单
        List<Menu> menus = menuRepository.findByDeletedFalseOrderBySort();
        
        // 2. 获取所有权限
        List<Permission> permissions = permissionRepository.findAllByDeletedFalseOrderBySort();
        
        // 3. 构建权限Map (menuId -> List<Permission>)
        Map<Long, List<Permission>> permissionMap = permissions.stream()
            .collect(Collectors.groupingBy(Permission::getMenuId));
        
        // 4. 构建菜单树
        return buildPermissionTree(menus, permissionMap);
    }
    
    private List<MenuPermissionTreeResponse> buildPermissionTree(List<Menu> menus, 
            Map<Long, List<Permission>> permissionMap) {
        // 1. 转换所有菜单为树形节点
        List<MenuPermissionTreeResponse> nodes = menus.stream()
            .map(menu -> convertToTreeNode(menu, permissionMap))
            .collect(Collectors.toList());
            
        // 2. 构建父子关系
        Map<Long, List<MenuPermissionTreeResponse>> childrenMap = nodes.stream()
            .collect(Collectors.groupingBy(node -> 
                Optional.ofNullable(node.getParentId()).orElse(0L)));
                
        // 3. 设置子节点并排序
        nodes.forEach(node -> {
            List<MenuPermissionTreeResponse> children = childrenMap.getOrDefault(node.getId(), new ArrayList<>());
            children.sort(Comparator.comparing(MenuPermissionTreeResponse::getSort));
            node.setPermissionChildren(children);
        });
            
        // 4. 返回排序后的顶层节点
        List<MenuPermissionTreeResponse> rootNodes = childrenMap.getOrDefault(0L, new ArrayList<>());
        rootNodes.sort(Comparator.comparing(MenuPermissionTreeResponse::getSort));
        return rootNodes;
    }
    
    private MenuPermissionTreeResponse convertToTreeNode(Menu menu, 
            Map<Long, List<Permission>> permissionMap) {
        MenuPermissionTreeResponse node = menuConverter.toMenuPermissionResponse(menu);
        
        // 设置权限列表
        List<Permission> permissions = permissionMap.getOrDefault(menu.getId(), new ArrayList<>());
        node.setPermissions(menuConverter.toPermissionResponseList(permissions));
        
        return node;
    }

    private List<MenuDTO> buildTree(List<Menu> menus) {
        Map<Long, MenuDTO> dtoMap = new HashMap<>();
        List<MenuDTO> roots = new ArrayList<>();

        // 转换为DTO并建立映射
        menus.forEach(menu -> {
            MenuDTO dto = menuConverter.toDto(menu);
            dto.setChildren(new ArrayList<>());
            dtoMap.put(dto.getId(), dto);
        });

        // 构建树形结构
        menus.forEach(menu -> {
            MenuDTO dto = dtoMap.get(menu.getId());
            if (menu.getParentId() == null || menu.getParentId() == 0) {
                roots.add(dto);
            } else {
                MenuDTO parent = dtoMap.get(menu.getParentId());
                if (parent != null) {
                    parent.getChildren().add(dto);
                }
            }
        });

        return roots;
    }

    private List<MenuDTO> buildMenuTree(List<MenuDTO> menus) {
        // 使用Map存储所有菜单，便于查找
        Map<Long, MenuDTO> menuMap = menus.stream()
            .collect(Collectors.toMap(MenuDTO::getId, menu -> menu));

        List<MenuDTO> rootMenus = new ArrayList<>();

        // 遍历所有菜单，构建树形结构
        for (MenuDTO menu : menus) {
            if (menu.getParentId() == null || menu.getParentId() == 0) {
                // 如果是根菜单，直接添加到结果列表
                rootMenus.add(menu);
            } else {
                // 如果不是根菜单，找到其父菜单并添加到children中
                MenuDTO parent = menuMap.get(menu.getParentId());
                if (parent != null) {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(menu);
                }
            }
        }

        // 对每一级菜单进行排序
        sortMenuTree(rootMenus);

        return rootMenus;
    }

    private void sortMenuTree(List<MenuDTO> menus) {
        if (menus == null || menus.isEmpty()) {
            return;
        }
        // 根据sort字段排序
        menus.sort(Comparator.comparing(MenuDTO::getSort));
        // 递归排序子菜单
        for (MenuDTO menu : menus) {
            if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {
                sortMenuTree(menu.getChildren());
            }
        }
    }
} 