package com.ningdatech.pmapi.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpStatus;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ningdatech.basic.exception.BaseUncheckedException;
import com.ningdatech.basic.util.ValidatorUtil;
import com.ningdatech.pmapi.common.constant.DefValConst;
import com.ningdatech.pmapi.sys.model.entity.Menu;
import com.ningdatech.pmapi.sys.model.enumeration.MenuTypeEnum;
import com.ningdatech.pmapi.sys.model.dto.MenuSaveDTO;
import com.ningdatech.pmapi.sys.model.dto.MenuUpdateDTO;
import com.ningdatech.pmapi.sys.mapper.MenuMapper;
import com.ningdatech.pmapi.sys.service.IMenuService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.ningdatech.basic.util.StrPool.DEF_PARENT_ID;


/**
 * <p>
 * 业务实现类
 * 菜单
 * </p>
 *
 * @author WendyYang
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIdWithCache(List<Long> ids) {
        if (ids.isEmpty()) {
            return true;
        }

        List<Long> lastIds = Lists.newArrayList();
        lastIds.addAll(ids);

        //子菜单id
        subMenus(ids, lastIds);

        return this.removeByIds(lastIds);
    }

    private void subMenus(List<Long> ids, List<Long> lastIds) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        ids.forEach(id -> {
            List<Menu> subMenus = list(Wrappers.lambdaQuery(Menu.class).eq(Menu::getPid, id));
            if (CollUtil.isNotEmpty(subMenus)) {
                //添加子菜单ID
                List<Long> subIds = subMenus.stream().map(Menu::getId).collect(Collectors.toList());
                lastIds.addAll(subIds);
                //递归
                subMenus(subIds, lastIds);
            }
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(MenuUpdateDTO data, Long userId) {
        if (MenuTypeEnum.MENU.getCode().equals(data.getType())) {
            if (StrUtil.isBlank(data.getPath())) {
                throw new BaseUncheckedException(HttpStatus.HTTP_OK, "【地址栏路径】不能为空");
            }
            if (StrUtil.isBlank(data.getComponent())) {
                throw new BaseUncheckedException(HttpStatus.HTTP_OK, "【页面路径】不能为空");
            }
            if (!ValidatorUtil.isUrl(data.getPath())) {
                if (checkPath(data.getId(), data.getPath())) {
                    throw new BaseUncheckedException(HttpStatus.HTTP_OK, "【地址栏路径】:{}重复", data.getPath());
                }
            }
        }
        Menu old = getById(data);
        if (Objects.isNull(old)) {
            throw new BaseUncheckedException(HttpStatus.HTTP_OK, "您修改的菜单已不存在");
        }
        Menu menu = BeanUtil.toBean(data, Menu.class);
        menu.setUpdateBy(userId);
        return this.updateById(menu);
    }

    public Boolean checkPath(Long id, String path) {
        return baseMapper.selectCount(Wrappers.lambdaQuery(Menu.class).ne(Menu::getId, id).eq(Menu::getPath, path)) > 0;
    }

    public Boolean checkTitle(Long id, String title) {
        LambdaQueryWrapper<Menu> wrapper = Wrappers.lambdaQuery(Menu.class)
                .ne(Menu::getId, id).eq(Menu::getTitle, title);
        return baseMapper.selectCount(wrapper) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(MenuSaveDTO data, Long userId) {
        if (StrUtil.isBlank(data.getPath())) {
            throw new BaseUncheckedException(HttpStatus.HTTP_OK, "【地址栏路径】不能为空");
        }
        if (StrUtil.isBlank(data.getComponent())) {
            throw new BaseUncheckedException(HttpStatus.HTTP_OK, "【页面路径】不能为空");
        }
        if (!ValidatorUtil.isUrl(data.getPath())) {
            if (checkPath(null, data.getPath())) {
                throw new BaseUncheckedException(HttpStatus.HTTP_OK, "【地址栏路径】:{}重复", data.getPath());
            }
        }
        data.setPid(Convert.toLong(data.getPid(), DEF_PARENT_ID));
        Menu menu = BeanUtil.toBean(data, Menu.class);
        menu.setCreateBy(userId);
        menu.setUpdateBy(userId);
        save(menu);
        return Boolean.TRUE;
    }

    public List<Menu> findChildrenByParentId(Long pid) {
        if (Objects.isNull(pid)) {
            throw new BaseUncheckedException(HttpStatus.HTTP_OK, "pid 不能为空");
        }
        return list(Wrappers.lambdaQuery(Menu.class).in(Menu::getPid, pid).orderByAsc(Menu::getSort));
    }

    private void fill(Menu resource) {
        if (resource.getPid() == null || resource.getPid() <= 0) {
            resource.setPid(DefValConst.PARENT_ID);
        } else {
            Menu parent = getById(resource.getPid());
            if (Objects.isNull(parent)) {
                throw new BaseUncheckedException(HttpStatus.HTTP_OK, "请正确填写父级");
            }
        }
    }

}
