package com.lesingle.creation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lesingle.creation.common.exception.BusinessException;
import com.lesingle.creation.dto.menu.CreateMenuDTO;
import com.lesingle.creation.dto.menu.UpdateMenuDTO;
import com.lesingle.creation.entity.*;
import com.lesingle.creation.mapper.*;
import com.lesingle.creation.service.MenuService;
import com.lesingle.creation.vo.menu.MenuDetailVO;
import com.lesingle.creation.vo.menu.MenuTreeVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜单服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    private final MenuMapper menuMapper;
    private final UserRoleMapper userRoleMapper;
    private final RolePermissionMapper rolePermissionMapper;
    private final PermissionMapper permissionMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MenuDetailVO create(CreateMenuDTO dto, Long operatorId) {
        log.info("开始创建菜单，菜单名称：{}", dto.getName());

        // 创建菜单
        Menu menu = new Menu();
        menu.setName(dto.getName());
        menu.setPath(dto.getPath());
        menu.setIcon(dto.getIcon());
        menu.setComponent(dto.getComponent());
        menu.setParentId(dto.getParentId() != null ? dto.getParentId() : 0L);
        menu.setPermission(dto.getPermission());
        menu.setSort(dto.getSort() != null ? dto.getSort() : 0);
        menu.setValidState(1);
        menu.setCreateBy(String.valueOf(operatorId));

        menuMapper.insert(menu);
        log.info("菜单创建成功，菜单 ID: {}", menu.getId());

        return convertToDetailVO(menu);
    }

    @Override
    public List<MenuTreeVO> tree() {
        log.info("查询菜单树");

        // 查询所有菜单
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Menu::getValidState, 1)
                .orderByAsc(Menu::getSort, Menu::getId);

        List<Menu> allMenus = menuMapper.selectList(wrapper);

        // 构建树形结构
        return buildTree(allMenus, 0L);
    }

    @Override
    public List<MenuTreeVO> getUserMenus(Long userId, Long tenantId) {
        log.info("查询用户菜单，用户 ID: {}, 租户 ID: {}", userId, tenantId);

        // 1. 查询用户关联的角色
        List<UserRole> userRoles = userRoleMapper.selectList(
                new LambdaQueryWrapper<UserRole>()
                        .eq(UserRole::getUserId, userId)
        );

        if (userRoles.isEmpty()) {
            // 用户没有角色，返回空菜单
            log.warn("用户没有任何角色，用户 ID: {}", userId);
            return new ArrayList<>();
        }

        // 2. 获取角色 ID 列表
        List<Long> roleIds = userRoles.stream()
                .map(UserRole::getRoleId)
                .collect(Collectors.toList());

        // 3. 查询角色关联的权限
        List<RolePermission> rolePermissions = rolePermissionMapper.selectList(
                new LambdaQueryWrapper<RolePermission>()
                        .in(RolePermission::getRoleId, roleIds)
        );

        if (rolePermissions.isEmpty()) {
            // 角色没有关联权限，返回空菜单
            log.warn("用户角色没有关联任何权限，用户 ID: {}", userId);
            return new ArrayList<>();
        }

        // 4. 获取权限 ID 列表
        List<Long> permissionIds = rolePermissions.stream()
                .map(RolePermission::getPermissionId)
                .distinct()
                .collect(Collectors.toList());

        // 5. 查询权限详情，检查是否有 super_admin 权限
        List<Permission> permissions = permissionMapper.selectBatchIds(permissionIds);
        boolean hasSuperAdmin = permissions.stream()
                .anyMatch(p -> "super_admin".equals(p.getCode()));

        // 6. 查询菜单
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Menu::getValidState, 1)
                .orderByAsc(Menu::getSort, Menu::getId);

        List<Menu> allMenus;
        if (hasSuperAdmin) {
            // 超管：查询所有菜单
            log.info("用户是超级管理员，返回所有菜单");
            allMenus = menuMapper.selectList(wrapper);
        } else {
            // 非超管：只查询有权限的菜单
            // 获取有权限的菜单编码
            List<String> permissionCodes = permissions.stream()
                    .map(Permission::getCode)
                    .collect(Collectors.toList());

            // 筛选条件：菜单权限为空（所有人都可见）或 菜单权限在用户权限列表中
            wrapper.and(w ->
                    w.isNull(Menu::getPermission)
                            .or()
                            .in(Menu::getPermission, permissionCodes)
            );

            log.info("非超管用户，根据权限过滤菜单，权限编码数量：{}", permissionCodes.size());
            allMenus = menuMapper.selectList(wrapper);
        }

        // 7. 构建树形结构
        return buildTree(allMenus, 0L);
    }

    @Override
    public MenuDetailVO detail(Long id) {
        log.info("查询菜单详情，菜单 ID: {}", id);

        Menu menu = menuMapper.selectById(id);
        if (menu == null) {
            throw new BusinessException("菜单不存在");
        }

        return convertToDetailVO(menu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MenuDetailVO update(Long id, UpdateMenuDTO dto) {
        log.info("更新菜单，菜单 ID: {}", id);

        Menu existingMenu = menuMapper.selectById(id);
        if (existingMenu == null) {
            throw new BusinessException("菜单不存在");
        }

        // 更新菜单信息
        Menu menu = new Menu();
        menu.setId(id);
        menu.setName(dto.getName());
        menu.setPath(dto.getPath());
        menu.setIcon(dto.getIcon());
        menu.setComponent(dto.getComponent());
        menu.setParentId(dto.getParentId());
        menu.setPermission(dto.getPermission());
        menu.setSort(dto.getSort());

        menuMapper.updateById(menu);
        log.info("菜单更新成功，菜单 ID: {}", id);

        return convertToDetailVO(menuMapper.selectById(id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        log.info("删除菜单，菜单 ID: {}", id);

        Menu menu = menuMapper.selectById(id);
        if (menu == null) {
            throw new BusinessException("菜单不存在");
        }

        // 检查是否有子菜单
        LambdaQueryWrapper<Menu> childWrapper = new LambdaQueryWrapper<>();
        childWrapper.eq(Menu::getParentId, id);
        Long childCount = menuMapper.selectCount(childWrapper);
        if (childCount > 0) {
            throw new BusinessException("存在子菜单，无法删除");
        }

        // 删除菜单（逻辑删除）
        menuMapper.deleteById(id);
        log.info("菜单删除成功，菜单 ID: {}", id);
    }

    /**
     * 构建树形结构
     */
    private List<MenuTreeVO> buildTree(List<Menu> menus, Long parentId) {
        return menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(this::convertToTreeVO)
                .peek(vo -> vo.setChildren(buildTree(menus, vo.getId())))
                .collect(Collectors.toList());
    }

    /**
     * 转换为详情 VO
     */
    private MenuDetailVO convertToDetailVO(Menu menu) {
        MenuDetailVO vo = new MenuDetailVO();
        vo.setId(menu.getId());
        vo.setName(menu.getName());
        vo.setPath(menu.getPath());
        vo.setIcon(menu.getIcon());
        vo.setComponent(menu.getComponent());
        vo.setParentId(menu.getParentId());
        vo.setPermission(menu.getPermission());
        vo.setSort(menu.getSort());
        vo.setValidState(menu.getValidState());
        vo.setCreateBy(menu.getCreateBy());
        vo.setCreateTime(menu.getCreateTime());
        vo.setUpdateBy(menu.getUpdateBy());
        vo.setUpdateTime(menu.getUpdateTime());
        return vo;
    }

    /**
     * 转换为树 VO
     */
    private MenuTreeVO convertToTreeVO(Menu menu) {
        MenuTreeVO vo = new MenuTreeVO();
        vo.setId(menu.getId());
        vo.setName(menu.getName());
        vo.setPath(menu.getPath());
        vo.setIcon(menu.getIcon());
        vo.setComponent(menu.getComponent());
        vo.setParentId(menu.getParentId());
        vo.setPermission(menu.getPermission());
        vo.setSort(menu.getSort());
        return vo;
    }
}
