package com.njcn.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.user.enums.UserResponseEnum;
import com.njcn.user.mapper.ComponentMapper;
import com.njcn.user.pojo.constant.ComponentState;
import com.njcn.user.pojo.constant.FunctionState;
import com.njcn.user.pojo.dto.ComponentDTO;
import com.njcn.user.pojo.param.ComponentParam;
import com.njcn.user.pojo.po.Component;
import com.njcn.user.pojo.vo.ComponentVO;
import com.njcn.user.service.IComponentService;
import com.njcn.user.service.IRoleComponentService;
import com.njcn.user.service.IRoleService;
import com.njcn.web.utils.RequestUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hongawen
 * @since 2021-12-13
 */
@AllArgsConstructor
@Service
public class ComponentServiceImpl extends ServiceImpl<ComponentMapper, Component> implements IComponentService {

    private final ComponentMapper componentMapper;

    private final IRoleService roleService;

    private final IRoleComponentService roleComponentService;

    @Override
    public boolean addComponent(ComponentParam componentParam) {
        checkComponentParam(componentParam,false);
        Component component = new Component();
        BeanUtil.copyProperties(componentParam, component);
        String functionGroup = componentParam.getFunctionGroup().stream().map(String::valueOf).collect(Collectors.joining(","));
        component.setFunctionGroup(functionGroup);
        component.setState(ComponentState.ENABLE);
        if (Objects.equals(componentParam.getPid(), FunctionState.FATHER_PID)){
            component.setPids(FunctionState.FATHER_PID);
        } else {
            Component fatherComponent = this.lambdaQuery().eq(Component::getId,componentParam.getPid()).one();
            if (Objects.equals(fatherComponent.getPid(),FunctionState.FATHER_PID)){
                component.setPids(componentParam.getPid());
            } else {
                String pidS = fatherComponent.getPids();
                component.setPids(pidS+","+componentParam.getPid());
            }
        }
        return this.save(component);
    }

    @Override
    public boolean deleteComponent(String id) {
        return this.lambdaUpdate()
                .set(Component::getState, ComponentState.DELETE)
                .in(Component::getId, id)
                .update();
    }

    @Override
    public boolean updateComponent(ComponentParam.ComponentUpdateParam componentParam) {
        checkComponentParam(componentParam,true);
        Component component = new Component();
        BeanUtil.copyProperties(componentParam, component);
        String functionGroup = componentParam.getFunctionGroup().stream().map(String::valueOf).collect(Collectors.joining(","));
        component.setFunctionGroup(functionGroup);
        return this.updateById(component);
    }

    @Override
    public List<ComponentVO> getComponentTree() {
        List<ComponentVO> list = new ArrayList<>();
        List<ComponentDTO> componentList = componentMapper.getAllComponent();
        componentList.forEach(item->{
            ComponentVO componentVO = new ComponentVO();
            BeanUtil.copyProperties(item, componentVO);
            componentVO.setFunctionGroup(Arrays.stream(item.getFunctionGroup().split(",")).map(s -> Integer.valueOf(s.trim())).collect(Collectors.toList()));
            list.add(componentVO);
        });
        return list.stream()
                .filter(fun -> Objects.equals(ComponentState.FATHER_PID,fun.getPid()))
                .peek(funS -> funS.setChildren(getChildCategoryList(funS, list)))
                .collect(Collectors.toList());
    }

    @Override
    public List<ComponentVO> getUserComponentTree() {
        List<ComponentVO> result = new ArrayList<>();
        List<ComponentVO> componentVOList = new ArrayList<>();
        List<String> roleList = roleService.getIdByUserId(RequestUtil.getUserIndex());
        if (!CollectionUtils.isEmpty(roleList)){
            List<String> componentList = roleComponentService.selectRoleComponent(roleList);
            if (!CollectionUtils.isEmpty(componentList)){
                List<ComponentDTO> list = componentMapper.getComponentByList(componentList);
                list.forEach(item->{
                    ComponentVO componentVO = new ComponentVO();
                    BeanUtil.copyProperties(item, componentVO);
                    componentVO.setFunctionGroup(Arrays.stream(item.getFunctionGroup().split(",")).map(s -> Integer.valueOf(s.trim())).collect(Collectors.toList()));
                    componentVOList.add(componentVO);
                });
                result = componentVOList.stream()
                        .filter(fun -> Objects.equals(ComponentState.FATHER_PID,fun.getPid()))
                        .peek(funS -> funS.setChildren(getChildCategoryList(funS, componentVOList)))
                        .collect(Collectors.toList());
            }
        }
        return result;
    }

    /**
     *  递归组装组件表
     */
    private List<ComponentVO> getChildCategoryList(ComponentVO currMenu, List<ComponentVO> categories) {
        return categories.stream().filter(o -> Objects.equals(o.getPid(),currMenu.getId()))
                .peek(o -> o.setChildren(getChildCategoryList(o, categories)))
                .collect(Collectors.toList());
    }

    /**
     * 校验参数，
     * 1.检查是否存在相同名称的组件
     */
    private void checkComponentParam(ComponentParam componentParam, boolean isExcludeSelf) {
        LambdaQueryWrapper<Component> componentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        componentLambdaQueryWrapper
                .eq(Component::getName, componentParam.getName())
                .eq(Component::getState, ComponentState.ENABLE);
        //更新的时候，需排除当前记录
        if (isExcludeSelf) {
            if (componentParam instanceof ComponentParam.ComponentUpdateParam) {
                componentLambdaQueryWrapper.ne(Component::getId, ((ComponentParam.ComponentUpdateParam) componentParam).getId());
            }
        }
        int countByAccount = this.count(componentLambdaQueryWrapper);
        //大于等于1个则表示重复
        if (countByAccount >= 1) {
            throw new BusinessException(UserResponseEnum.COMPONENT_NAME_EXIST);
        }
    }
}
