package com.njcn.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
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.system.api.DicDataFeignClient;
import com.njcn.system.enums.SystemResponseEnum;
import com.njcn.system.pojo.po.DictData;
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.po.Role;
import com.njcn.user.pojo.vo.ComponentVO;
import com.njcn.user.service.IComponentService;
import com.njcn.user.service.IRoleComponentService;
import com.njcn.user.service.IUserRoleService;
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;

/**
 * <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 IUserRoleService iUserRoleService;

    private final IRoleComponentService roleComponentService;

    private final DicDataFeignClient dicDataFeignClient;

    @Override
    public boolean addComponent(ComponentParam componentParam) {
        checkComponentParam(componentParam, false);
        Component component = new Component();
        BeanUtil.copyProperties(componentParam, component);
        component.setState(ComponentState.ENABLE);
        if (Objects.equals(componentParam.getPid(), FunctionState.FATHER_PID)) {
            component.setPids(FunctionState.FATHER_PID);
        } else {
            component.setPid("1");
            component.setPids("0,1");
        }
        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);
        if (Objects.equals(componentParam.getPid(), FunctionState.FATHER_PID)) {
            component.setPids(FunctionState.FATHER_PID);
        } else {
            component.setPid("1");
            component.setPids("0,1");
        }
        return this.updateById(component);
    }

//    @Override
//    public List<ComponentVO> getComponentTree() {
//        List<ComponentVO> list = new ArrayList<>();
//        List<ComponentVO> result = new ArrayList<>();
//        List<ComponentDTO> componentList = componentMapper.getAllComponent();
//        if (!CollectionUtils.isEmpty(componentList)) {
//            componentList.forEach(item -> {
//                ComponentVO componentVO = new ComponentVO();
//                BeanUtil.copyProperties(item, componentVO);
//                componentVO.setTimeKeys(StrUtil.split(item.getTimeKey(), ","));
//                list.add(componentVO);
//            });
//            Map<String, List<ComponentVO>> map = list.stream().filter(m -> !Objects.isNull(m.getSystemType())).collect(Collectors.groupingBy(ComponentVO::getSystemType));
//            map.forEach((k, v) -> {
//                DictData dictData = dicDataFeignClient.getDicDataById(k).getData();
//                if (Objects.isNull(dictData)) {
//                    throw new BusinessException(SystemResponseEnum.SYSTEM_TYPE_EMPTY);
//                }
//                ComponentVO componentVO = new ComponentVO();
//                componentVO.setId(dictData.getId());
//                componentVO.setName(dictData.getName());
//                componentVO.setSort(dictData.getSort());
//                componentVO.setChildren(
//                        v.stream()
//                                .filter(fun -> Objects.equals(ComponentState.FATHER_PID, fun.getPid()))
//                                .peek(funS -> funS.setChildren(getChildCategoryList(funS, v))).sorted(Comparator.comparing(ComponentVO::getSort))
//                                .collect(Collectors.toList()));
//                result.add(componentVO);
//            });
//            result.sort(Comparator.comparing(ComponentVO::getSort));
//        }
//        return result;
//    }

    @Override
    public List<ComponentVO> getComponentTree() {
        List<ComponentVO> list = new ArrayList<>();
        List<ComponentVO> result = new ArrayList<>();
        List<ComponentDTO> componentList = componentMapper.getAllComponent();
        if (!CollectionUtils.isEmpty(componentList)) {
            componentList.forEach(item -> {
                ComponentVO componentVO = new ComponentVO();
                BeanUtil.copyProperties(item, componentVO);
                componentVO.setTimeKeys(StrUtil.split(item.getTimeKey(), ","));
                list.add(componentVO);
            });
            //二层集合
            List<ComponentVO> second = list.stream().filter(item -> Objects.equals(item.getPid(), "0")).collect(Collectors.toList());
            //三层集合
            List<ComponentVO> third = list.stream().filter(item -> Objects.equals(item.getPid(), "1")).collect(Collectors.toList());

            Set<String> uniqueValues = list.stream()
                    .flatMap(obj -> Arrays.stream(obj.getSystemType().split(",")))
                    .map(String::trim)
                    .collect(Collectors.toSet());
            //根据字典code获取当前所有系统
            List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode("System_Type").getData();
            dictDataList.forEach(dic->{
                //第一层
                ComponentVO componentVO = new ComponentVO();
                componentVO.setId(dic.getId());
                componentVO.setName(dic.getName());
                componentVO.setSort(dic.getSort());
                //第二层
                if (CollectionUtil.isNotEmpty(second)) {
                    List<ComponentVO> l2 = second.stream().filter(item2 -> item2.getSystemType().contains(dic.getId())).sorted(Comparator.comparing(ComponentVO::getSort)).collect(Collectors.toList());
                    componentVO.setChildren(l2);
                    //第三层
                    componentVO.getChildren().forEach(item3->{
                        List<ComponentVO> l3 = third.stream().filter(item4 -> item4.getComponentType().contains(item3.getId())).sorted(Comparator.comparing(ComponentVO::getSort)).collect(Collectors.toList());
                        item3.setChildren(l3);
                    });
                }
                result.add(componentVO);
            });
            result.sort(Comparator.comparing(ComponentVO::getSort));
        }
        return result;
    }

    @Override
    public List<ComponentVO> getUserComponentTree() {
        List<ComponentVO> result = new ArrayList<>();
        List<ComponentVO> componentVOList = new ArrayList<>();
        List<Role> roleList = iUserRoleService.getRoleListByUserId(RequestUtil.getUserIndex());
        if (!CollectionUtils.isEmpty(roleList)) {
            List<ComponentDTO> list;
            if (roleList.stream().anyMatch(item -> "root".equals(item.getCode()))) {
                list = componentMapper.getAllComponent();
            } else {
                List<String> componentList = roleComponentService.selectRoleComponent(roleList.stream().map(Role::getId).collect(Collectors.toList()));
                if (CollectionUtil.isEmpty(componentList)) {
                    return result;
                }
                list = componentMapper.getComponentByList(componentList);
            }
            if (CollectionUtil.isEmpty(list)) {
                return result;
            }
            list.forEach(item -> {
                ComponentVO componentVO = new ComponentVO();
                BeanUtil.copyProperties(item, componentVO);
                componentVO.setTimeKeys(StrUtil.split(item.getTimeKey(), ","));
//                componentVO.setFunctionGroup(Arrays.stream(item.getFunctionGroup().split(",")).map(s -> Integer.valueOf(s.trim())).collect(Collectors.toList()));
                componentVOList.add(componentVO);
            });
            Map<String, List<ComponentVO>> map = componentVOList.stream().collect(Collectors.groupingBy(ComponentVO::getSystemType));
            map.forEach((k, v) -> {
                DictData dictData = dicDataFeignClient.getDicDataById(k).getData();
                if (Objects.isNull(dictData)) {
                    throw new BusinessException(SystemResponseEnum.SYSTEM_TYPE_EMPTY);
                }
                ComponentVO componentVO = new ComponentVO();
                componentVO.setName(dictData.getName());
                componentVO.setChildren(
                        v.stream()
                                .filter(fun -> Objects.equals(ComponentState.FATHER_PID, fun.getPid()))
                                .peek(funS -> funS.setChildren(getChildCategoryList(funS, v)))
                                .collect(Collectors.toList()));
                result.add(componentVO);
            });
        }
        return result;
    }

    @Override
    public List<Component> getFatherComponent(String systemType) {
        return new ArrayList<>(this.lambdaQuery()
                .eq(Component::getSystemType, systemType)
                .eq(Component::getPid, ComponentState.FATHER_PID)
                .eq(Component::getState, ComponentState.ENABLE)
                .list());
    }

    /**
     * 递归组装组件表
     */
    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))).sorted(Comparator.comparing(ComponentVO::getSort))
                .collect(Collectors.toList());
    }

    /**
     * 校验参数，
     * 1.检查是否存在相同名称的组件
     */
    private void checkComponentParam(ComponentParam componentParam, boolean isExcludeSelf) {
        LambdaQueryWrapper<Component> componentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        componentLambdaQueryWrapper
                .eq(Component::getName, componentParam.getName())
                .eq(Component::getSystemType, componentParam.getSystemType())
                .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);
        }
    }
}
