package com.njcn.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.system.enums.SystemResponseEnum;
import com.njcn.system.mapper.AreaMapper;
import com.njcn.system.pojo.dto.AreaTreeDTO;
import com.njcn.system.pojo.param.AreaParam;
import com.njcn.system.pojo.po.Area;
import com.njcn.system.pojo.vo.AreaTreeVO;
import com.njcn.system.service.IAreaService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.po.Dept;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hongawen
 * @since 2021-12-13
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements IAreaService {

    private final DeptFeignClient deptFeignClient;

    @Override
    public Page<Area> listDictData(AreaParam.QueryParam queryParam) {
        QueryWrapper<Area> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(queryParam)) {
            //查询参数不为空，进行条件填充
            if (StrUtil.isNotBlank(queryParam.getSearchValue())) {
                //部门根据名称模糊查询
                queryWrapper
                        .and(param -> param.like("sys_area.name", queryParam.getSearchValue()));
            }
        }
        queryWrapper.ne("sys_area.state", DataStateEnum.DELETED.getCode());
        queryWrapper.ge("sys_area.type", queryParam.getType());
        //初始化分页数据
        return this.baseMapper.selectPage(new Page<>(PageFactory.getPageNum(queryParam), PageFactory.getPageSize(queryParam)), queryWrapper);
    }

    @Override
    public Area selectIdArea(String id) {
        return this.baseMapper.selectById(id);
    }

    @Override
    public List<Area> selectAreaByList(List<String> list) {
        return this.lambdaQuery().in(Area::getId, list).list();
    }

    @Override
    public List<Area> selectPid(List<String> ids) {
        return this.baseMapper.selectPid(ids, DataStateEnum.ENABLE.getCode());
    }

    @Override
    public List<AreaTreeVO> areaTree(String id, Integer type) {
        List<AreaTreeVO> areaTreeVOList = new ArrayList<>();
        if (id.equals("") || id == null) {
            /**
             * 用于首次访问区域。此处需要获取当前用户所绑定的部门下的行政区域id
             * 现在默认为0
             */
            id = deptFeignClient.getAreaIdByDeptId(RequestUtil.getDeptIndex()).getData();
        }
        List<AreaTreeVO> areaTreeVOS = new ArrayList<>();
        if (type == 1) {
            areaTreeVOList = this.baseMapper.getAreaIdTree(type, DataStateEnum.ENABLE.getCode());
            List<AreaTreeVO> finalAreaTreeVOList = areaTreeVOList;
            areaTreeVOS = areaTreeVOList.stream().filter(deptTreeVO ->
                    deptTreeVO.getPid().equals("0")
            ).map((deptFirst) -> {
                //map映射方法改变结果，调用getChildrens()方法，把一级部门deptFirst和所有数据allDept作为参数传递，查询所有下级部门
                deptFirst.setChildren(getChildrens(deptFirst, finalAreaTreeVOList));
                return deptFirst;
            }).collect(Collectors.toList());
        } else {
            areaTreeVOS = this.baseMapper.getAreaTree(id, type, DataStateEnum.ENABLE.getCode());
            ;
        }
        return areaTreeVOS;
    }

    /**
     * 递归查找所有企业的下级
     *
     * @return
     */
    private List<AreaTreeVO> getChildrens(AreaTreeVO areaTreeVO, List<AreaTreeVO> allArea) {
        List<AreaTreeVO> chilrdenList = allArea.stream().filter(area -> {
            //在全部数据中，找到和一级部门deptFirst的valueId相等的parentId
            return area.getPid().equals(areaTreeVO.getId());
        }).map(deptId -> {
            //递归查询找到下级部门
            deptId.setChildren(getChildrens(deptId, allArea));
            return deptId;
        }).collect(Collectors.toList());
        return chilrdenList;
    }

    @Override
    public boolean addAreaParam(AreaParam areaParam) {
        checkAreaCode(areaParam, false);
        Area area = new Area();
        BeanUtil.copyProperties(areaParam, area);
        if (areaParam.getPid().equals("0")) {
            //上层节点
            area.setPids("0");
        } else {
            String pids = "," + areaParam.getPid();
            String pid = this.baseMapper.getIdString(area.getPid());
            //上层节点
            area.setPids(pid + pids);
        }
        //默认为正常状态
        area.setState(DataStateEnum.ENABLE.getCode());
        return this.save(area);
    }

    @Override
    public boolean updateArea(AreaParam.AreaUpdateParam updateParam) {
        checkAreaCode(updateParam, true);
        Area area = new Area();
        if (updateParam.getPid().equals("0")) {
            //上层节点
            area.setPids("0");
        } else {
            String pids = "," + updateParam.getPid();
            String pid = this.baseMapper.getIdString(area.getPid());
            //上层节点
            area.setPids(pid + pids);
        }
        BeanUtil.copyProperties(updateParam, area);
        return this.updateById(area);
    }

    @Override
    public boolean deleteArea(List<String> ids) {
        /**
         * 查询子节点
         */
        List<Area> list = this.baseMapper.selectPid(ids, DataStateEnum.ENABLE.getCode());
        /**
         * 将子节点叶添加到需要删除中
         */
        if (list.size() > 0) {
            for (Area area : list) {
                ids.add(area.getId());
            }
        }
        return this.lambdaUpdate().set(Area::getState, DataStateEnum.DELETED.getCode()).in(Area::getId, ids).update();
    }

    @Override
    public List<AreaTreeDTO> areaDeptTree(String id, Integer type) {
        List<AreaTreeDTO> areaTreeVOList = new ArrayList<>();
        List<AreaTreeDTO> areaTreeVOS = new ArrayList<>();
        if (id.equals("") || id == null) {
            /**
             * 用于首次访问区域。此处需要获取当前用户所绑定的部门下的行政区域id
             * 现在默认为0
             */

            id = deptFeignClient.getAreaIdByDeptId(RequestUtil.getDeptIndex()).getData();
        }
        areaTreeVOList = this.baseMapper.getAreaDeptTree(type, DataStateEnum.ENABLE.getCode());
        List<AreaTreeDTO> finalAreaTreeVOList = areaTreeVOList;
        String finalId = id;
        areaTreeVOS = areaTreeVOList.stream().filter(deptTreeVO ->
                deptTreeVO.getPid().equals(finalId)
        ).map((deptFirst) -> {
            //map映射方法改变结果，调用getChildrens()方法，把一级部门deptFirst和所有数据allDept作为参数传递，查询所有下级部门
            deptFirst.setChildren(getChildrens(deptFirst, finalAreaTreeVOList));
            return deptFirst;
        }).collect(Collectors.toList());

        return areaTreeVOS;
    }

    @Override
    public Area areaPro(String id, Integer type) {
        QueryWrapper<Area> areaQueryWrapper = new QueryWrapper<>();
        areaQueryWrapper.eq("sys_area.id", id);
        areaQueryWrapper.eq("sys_area.type", type);
        areaQueryWrapper.eq("sys_area.state", DataStateEnum.ENABLE.getCode());
        Area area = this.baseMapper.selectOne(areaQueryWrapper);
        if (!area.getPid().equals("0")) {
            id = area.getPid();
            area = areaPro(id, type);
        }
        return area;
    }   

    @Override
    public Area areaDeptPro(String id) {
        Area areaDetail = this.baseMapper.areaDeptProDetail(id);
        Area area = areaPro(areaDetail.getId(),areaDetail.getType());
        return area;
    }

    @Override
    public List<AreaTreeVO> getDeptIdAreaTree() {

        //获取当前系统登录的部门信息
        String areaId = deptFeignClient.getAreaIdByDeptId(RequestUtil.getDeptIndex()).getData();
        List<AreaTreeVO> areaTreeVOS = this.baseMapper.getAreaAll();
        List<AreaTreeVO> areaTreeVOLists = areaTreeVOS.stream().filter(areaTreeVO ->
                areaTreeVO.getId().equals(areaId)
        ).map((areaFirst) -> {
            //map映射方法改变结果，调用getChildrens()方法，把一级部门deptFirst和所有数据allDept作为参数传递，查询所有下级部门
            areaFirst.setChildren(getChildrens(areaFirst, areaTreeVOS));
            return areaFirst;
        }).collect(Collectors.toList());
        return areaTreeVOLists;
    }

    @Override
    public Area selectAreaByName(String name) {
        LambdaQueryWrapper<Area> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Area::getName, name);
        return this.baseMapper.selectOne(lambdaQueryWrapper);
    }

    /**
     * 递归查找所有企业的下级
     *
     * @return
     */
    private List<AreaTreeDTO> getChildrens(AreaTreeDTO areaTreeVO, List<AreaTreeDTO> allArea) {
        List<AreaTreeDTO> chilrdenList = allArea.stream().filter(area -> {
            //在全部数据中，找到和一级部门deptFirst的valueId相等的parentId
            return area.getPid().equals(areaTreeVO.getId());
        }).map(deptId -> {
            //递归查询找到下级部门
            deptId.setChildren(getChildrens(deptId, allArea));
            return deptId;
        }).collect(Collectors.toList());
        return chilrdenList;
    }

    /**
     * 校验参数，检查是否存在相同编码的企业区域
     */
    private void checkAreaCode(AreaParam areaParam, boolean isExcludeSelf) {
        LambdaQueryWrapper<Area> dictTypeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dictTypeLambdaQueryWrapper
                .eq(Area::getAreaCode, areaParam.getAreaCode())
                .eq(Area::getState, DataStateEnum.ENABLE.getCode());
        //更新的时候，需排除当前记录
        if (isExcludeSelf) {
            if (areaParam instanceof AreaParam.AreaUpdateParam) {
                dictTypeLambdaQueryWrapper.ne(Area::getId, ((AreaParam.AreaUpdateParam) areaParam).getId());
            }
        }
        int countByAccount = this.count(dictTypeLambdaQueryWrapper);
        //大于等于1个则表示重复
        if (countByAccount >= 1) {
            throw new BusinessException(SystemResponseEnum.AREA_CODE_REPEAT);
        }
    }


}
