package com.app.service.platform;

import com.app.constant.MenuConstant;
import com.app.dto.PageResult;
import com.app.dto.platform.ResponseMenuDto;
import com.app.dto.platform.ResponseNodeDto;
import com.app.dto.platform.SearchMenuDto;
import com.app.entity.BaseEntity;
import com.app.entity.platform.system.Resource;
import com.app.mapper.platform.ResourceMapper;
import com.app.util.NodeUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 菜单管理
 */
@Slf4j
@Service
public class ResourceService {

    @javax.annotation.Resource
    private ResourceMapper resourceMapper;

    /**
     * 查询【菜单】分页
     * 未传菜单标题搜索时，只查询出顶级菜单（目录）
     */
    public PageResult<ResponseMenuDto> page(SearchMenuDto dto) {
        LambdaQueryWrapper<Resource> wrapper = new QueryWrapper<Resource>().lambda();
        if (!StringUtils.isEmpty(dto.getName())) { // 有传入名称时，按名称查询
            wrapper.like(Resource::getName, dto.getName());
        } else { // 默认查询顶级菜单
            wrapper.eq(Resource::getResourceType, MenuConstant.TYPE_CATALOG).isNull(Resource::getParentId);
        }
        wrapper.eq(Resource::getIsDel, dto.getIsDel());
        wrapper.orderByDesc(Resource::getSort);
        Page<Resource> p = resourceMapper.selectPage(new Page<>(dto.getPage(), dto.getSize()), wrapper);
        Page<ResponseMenuDto> page = new Page<>(dto.getPage(), dto.getSize());
        page.setTotal(p.getTotal());
        List<ResponseMenuDto> list = new ArrayList<>();
        for (Resource m : p.getRecords()) { // 判断节点是否有子节点
            ResponseMenuDto respDto = new ResponseMenuDto();
            BeanUtils.copyProperties(m, respDto);
            wrapper = new QueryWrapper<Resource>().lambda();
            wrapper.eq(Resource::getParentId, m.getId()).eq(BaseEntity::getIsDel, Boolean.FALSE);
            Integer count = resourceMapper.selectCount(wrapper);
            if (count > 0) {
                respDto.setHasChildren(true);
            } else {
                respDto.setHasChildren(false);
            }
            list.add(respDto);
        }
        page.setRecords(list);
        return new PageResult<>(dto.getPage(), dto.getSize(), page.getTotal(), page.getRecords());
    }


    /**
     * 获取节点树（用于前端选择上级部门）
     * @return 节点树
     */
    public List<ResponseNodeDto> getAllNodes() {
        LambdaQueryWrapper<Resource> wrapper = new QueryWrapper<Resource>().lambda().eq(BaseEntity::getIsDel, Boolean.FALSE);
        List<Resource> menuList = resourceMapper.selectList(wrapper);
        List<ResponseNodeDto> list=new ArrayList<>();
        for (Resource menu : menuList) {
            ResponseNodeDto nodeDto = new ResponseNodeDto();
            BeanUtils.copyProperties(menu,nodeDto);
            nodeDto.setLabel(menu.getName());
            nodeDto.setValue(menu.getId());
            list.add(nodeDto);
        }
        return NodeUtils.buildTree(list);
    }


    /**
     * 查询【菜单】
     */
    public List<ResponseMenuDto> list(SearchMenuDto dto) {
        LambdaQueryWrapper<Resource> wrapper = new QueryWrapper<Resource>().lambda();
        if (!StringUtils.isEmpty(dto.getParentId())) {
            wrapper.eq(Resource::getParentId, dto.getParentId());
        }
        wrapper.eq(Resource::getIsDel, Boolean.FALSE);
        wrapper.orderByDesc(Resource::getSort);
        List<Resource> menuList = resourceMapper.selectList(wrapper);
        if (menuList.isEmpty()) {
            return null;
        }
        List<ResponseMenuDto> list = new ArrayList<>();
        for (Resource menu : menuList) {
            ResponseMenuDto respDto = new ResponseMenuDto();
            BeanUtils.copyProperties(menu, respDto);
            wrapper = new QueryWrapper<Resource>().lambda();
            wrapper.eq(Resource::getParentId, menu.getId()).eq(BaseEntity::getIsDel, Boolean.FALSE);
            Integer count = resourceMapper.selectCount(wrapper);
            if (count > 0) {
                respDto.setHasChildren(true);
            } else {
                respDto.setHasChildren(false);
            }
            list.add(respDto);
        }
        return list;
    }

    /**
     * 保存或更新【菜单】
     */
    public Resource saveOrUpdate(Resource dto) {
        // 改变菜单类型时清空无用数据
        if(dto.getResourceType().equals(MenuConstant.TYPE_CATALOG)){
            dto.setPermission("");
            dto.setComponentName("");
            dto.setComponentPath("");
        }else if(dto.getResourceType().equals(MenuConstant.TYPE_BUTTON)){
            dto.setPath("");
            dto.setComponentPath("");
            dto.setComponentName("");
        }
        Resource _menu = null;
        if (StringUtils.isEmpty(dto.getId())) {
            _menu = new Resource();
            if(StringUtils.isEmpty(dto.getParentId())){
                _menu.setParentId(null);
            }else {
                _menu.setParentId(dto.getParentId());
            }
            _menu.setComponentName(dto.getComponentName());
            _menu.setIcon(dto.getIcon());
            _menu.setCache(dto.getCache());
            _menu.setSort(dto.getSort());
            _menu.setHidden(dto.getHidden());
            _menu.setPath(dto.getPath());
            _menu.setComponentPath(dto.getComponentPath());
            _menu.setLink(dto.getLink());
            _menu.setPermission(dto.getPermission());
            _menu.setName(dto.getName());
            _menu.setResourceType(dto.getResourceType());
            _menu.setRemarks(dto.getRemarks());
            resourceMapper.insert(_menu);
        } else {
            Optional<Resource> newsOptional = Optional.ofNullable(resourceMapper.selectById(dto.getId()));
            if (newsOptional.isPresent()) {
                _menu = newsOptional.get();
                LambdaUpdateWrapper<Resource> wrapper = new UpdateWrapper<Resource>().lambda();
                wrapper.eq(BaseEntity::getId,_menu.getId());
                // 当parentId为空时，把该字段置为null，即节点修改为顶级节点
                if(StringUtils.isEmpty(dto.getParentId())){
                    wrapper.set(Resource::getParentId,null);
                }else {
                    wrapper.set(Resource::getParentId,dto.getParentId());
                }
                wrapper.set(Resource::getComponentName,dto.getComponentName());
                wrapper.set(Resource::getIcon,dto.getIcon());
                wrapper.set(Resource::getCache,dto.getCache());
                wrapper.set(Resource::getSort,dto.getSort());
                wrapper.set(Resource::getHidden,dto.getHidden());
                wrapper.set(Resource::getPath,dto.getPath());
                wrapper.set(Resource::getComponentPath,dto.getComponentPath());
                wrapper.set(Resource::getLink,dto.getLink());
                wrapper.set(Resource::getPermission,dto.getPermission());
                wrapper.set(Resource::getName,dto.getName());
                wrapper.set(Resource::getResourceType,dto.getResourceType());
                wrapper.set(Resource::getRemarks,dto.getRemarks());
                resourceMapper.update(null,wrapper);
            }
        }
        return _menu;
    }

    /**
     * 替换[菜单]删除状态
     */
    public void handleIsDel(String id) {
        LambdaQueryWrapper<Resource> wrapper = new QueryWrapper<Resource>().lambda();
        wrapper.eq(Resource::getIsDel,Boolean.FALSE).eq(Resource::getParentId,id);
        List<Resource> list = resourceMapper.selectList(wrapper);
        Optional<Resource> optional = Optional.ofNullable(resourceMapper.selectById(id));
        if (optional.isPresent()) {
            Resource menu = optional.get();
            menu.setIsDel(!menu.getIsDel());
            resourceMapper.updateById(menu);
        }
        // 如果该节点有子节点，继续遍历删除其子节点
        if(!list.isEmpty()){
            for (Resource menu : list) {
                handleIsDel(menu.getId());
            }
        }


    }
}
