package com.tuoheng.admin.service.dept.add;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tuoheng.admin.constant.SystemConstant;
import com.tuoheng.admin.dto.ChannelLegDto;
import com.tuoheng.admin.entity.*;
import com.tuoheng.admin.enums.MarkEnum;
import com.tuoheng.admin.enums.code.dept.AddDeptCodeEnum;
import com.tuoheng.admin.mapper.DeptMapper;
import com.tuoheng.admin.mapper.ChannelDeptMapper;
import com.tuoheng.admin.mapper.LegDeptMapper;
import com.tuoheng.admin.mapper.UserMapper;
import com.tuoheng.admin.request.dept.AddDeptRequest;
import com.tuoheng.admin.utils.CurrentUserUtil;
import com.tuoheng.common.core.utils.DateUtils;
import com.tuoheng.common.core.utils.JsonResult;
import com.tuoheng.common.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

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

/**
 * 添加部门业务层处理
 *
 * @author wanjing
 * @team tuoheng
 * @date 2022-11-17
 */
@Slf4j
@Service
public class AddDeptService {

    @Autowired
    private DeptMapper deptMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ChannelDeptMapper channelDeptMapper;

    @Autowired
    private LegDeptMapper legDeptMapper;

    /**
     * 添加部门数据
     *
     * @return
     */
    public JsonResult add(AddDeptRequest addDeptRequest) {
        log.info("进入添加部门业务接口");
        String userId = CurrentUserUtil.getUserId();
        String tenantId = CurrentUserUtil.getTenantId();
        JsonResult result = this.check(tenantId, addDeptRequest);
        if (0 != result.getCode()) {
            log.info("添加部门业务接口：校验失败：{}", result.getMsg());
            return result;
        }

        Dept dept = new Dept();
        dept.setTenantId(tenantId);
        dept.setName(addDeptRequest.getName());
        dept.setPid(addDeptRequest.getPid());
        dept.setCreateUser(CurrentUserUtil.getUserId());
        dept.setCreateTime(DateUtils.now());
        Integer rowId = deptMapper.insert(dept);
        log.info("新增部门, 返回结果: deptId={}", dept.getId());

        if (rowId <= 0) {
            log.info("添加部门业务接口：添加部门失败：{}", result.getMsg());
            return JsonResult.error(AddDeptCodeEnum.ADD_DEPT_IS_FAILED.getCode(), AddDeptCodeEnum.ADD_DEPT_IS_FAILED.getMsg());
        }

        this.updateSuperAdminUser(userId, tenantId, dept);

        // 新增航道/航段与部门数据
        addRoadAndSectionToDept(tenantId, dept.getId(), addDeptRequest.getChannelLegDtoList());

        log.info("添加部门业务接口：添加部门成功：{}");
        return JsonResult.success(dept);
    }

    /**
     * 检查参数
     *
     * @param tenantId
     * @param addDeptRequest
     * @return
     */
    private JsonResult check(String tenantId, AddDeptRequest addDeptRequest) {
        if (null == addDeptRequest.getPid()) {
            return JsonResult.error(AddDeptCodeEnum.DEPT_PID_IS_NULL.getCode(), AddDeptCodeEnum.DEPT_PID_IS_NULL.getMsg());
        }

        if (StringUtils.isEmpty(addDeptRequest.getName())) {
            return JsonResult.error(AddDeptCodeEnum.DEPT_NAME_IS_NULL.getCode(), AddDeptCodeEnum.DEPT_NAME_IS_NULL.getMsg());
        }

        if (SystemConstant.ROOT_DEPT_PID.equals(addDeptRequest.getPid())) {
            Integer count = deptMapper.selectCount(new LambdaQueryWrapper<Dept>()
                    .eq(Dept::getTenantId, tenantId)
                    .eq(Dept::getPid, addDeptRequest.getPid())
                    .eq(Dept::getMark, MarkEnum.VALID.getCode()));

            // 顶级部门只能创建一个
            if (count > 0) {
                return JsonResult.error(AddDeptCodeEnum.ROOT_DEPT_IS_EXIST.getCode(), AddDeptCodeEnum.ROOT_DEPT_IS_EXIST.getMsg());
            }
        } else {
            // 判断上级部门是否存在
            Integer count = deptMapper.selectCount(new LambdaQueryWrapper<Dept>()
                    .eq(Dept::getTenantId, tenantId)
                    .eq(Dept::getId, addDeptRequest.getPid())
                    .eq(Dept::getMark, MarkEnum.VALID.getCode()));
            if (count <= 0) {
                return JsonResult.error(AddDeptCodeEnum.PARENT_DEPT_IS_NOT_EXIST.getCode(), AddDeptCodeEnum.PARENT_DEPT_IS_NOT_EXIST.getMsg());
            }

            // 判断是否已存在该部门名称，同部门下，部门名称不能重复
            count = deptMapper.selectCount(new LambdaQueryWrapper<Dept>()
                    .eq(Dept::getTenantId, tenantId)
                    .eq(Dept::getPid, addDeptRequest.getPid())
                    .eq(Dept::getName, addDeptRequest.getName())
                    .eq(Dept::getMark, MarkEnum.VALID.getCode()));

            // 系统中已存在
            if (count > 0) {
                return JsonResult.error(AddDeptCodeEnum.DEPT_NAME_IS_ALREADY_EXIST.getCode(), AddDeptCodeEnum.DEPT_NAME_IS_ALREADY_EXIST.getMsg());
            }
        }

        // 新增部门，航道和航段信息不能为空
        if (CollectionUtils.isEmpty(addDeptRequest.getChannelLegDtoList())) {
            return JsonResult.error(AddDeptCodeEnum.ROAD_IS_NULL.getCode(), AddDeptCodeEnum.ROAD_IS_NULL.getMsg());
        }

        List<Leg> legList;
        List<ChannelLegDto> channelLegDtoList = addDeptRequest.getChannelLegDtoList();
        for (ChannelLegDto channelLegDto : channelLegDtoList) {
            legList = channelLegDto.getLegList();
            if (CollectionUtils.isEmpty(legList)) {
                return JsonResult.error(AddDeptCodeEnum.SECTION_IS_NULL.getCode(), AddDeptCodeEnum.SECTION_IS_NULL.getMsg());
            }
        }
        return JsonResult.success();
    }

    /**
     * 新增航道/航段与部门数据
     *
     * @param tenantId           租户Id
     * @param deptId             部门Id
     * @param channelLegDtoList 航道/航段集合
     * @return 结果
     */
    private void addRoadAndSectionToDept(String tenantId, String deptId, List<ChannelLegDto> channelLegDtoList) {
        List<Channel> channelList = new ArrayList<>();
        List<Leg> legList = new ArrayList<>();
        Channel channel;
        List<Leg> legListTmp;
        for (ChannelLegDto channelLegDto : channelLegDtoList) {
            channel = channelLegDto.getChannel();
            legListTmp = channelLegDto.getLegList();
            channelList.add(channel);
            legList.addAll(legListTmp);
        }

        // 添加部门和航道数据
        // 去重，防止前端提交了重复的数据
        channelList = channelList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Channel::getId))), ArrayList::new));
        this.addRoadToDept(tenantId, deptId, channelList);

        // 添加部门和航段数据
        // 去重，防止前端提交了重复的数据
        legList = legList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Leg::getId))), ArrayList::new));
        this.addSectionToDept(tenantId, deptId, legList);
    }

    /**
     * 新增航道部门数据
     * 1、先删除原有记录数据
     * 2、新增此次提交的数据
     *
     * @param tenantId            租户Id
     * @param deptId              部门Id
     * @param channelList 航道集合
     * @return 结果
     */
    private void addRoadToDept(String tenantId, String deptId, List<Channel> channelList) {
        List<String> channelIdList = channelList.stream().map(o -> o.getId()).collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        map.put("tenantId", tenantId);
        map.put("deptId", deptId);
        map.put("channelIdList", channelIdList);
        channelDeptMapper.deleteBatchByMap(map);

        List<ChannelDept> list = new ArrayList<>();
        ChannelDept channelDept;
        for (Channel channel : channelList) {
            Integer count = channelDeptMapper.selectCount(new LambdaQueryWrapper<ChannelDept>()
                    .eq(ChannelDept::getTenantId, tenantId)
                    .eq(ChannelDept::getDeptId, deptId)
                    .eq(ChannelDept::getChannelId, channel.getId()));
            if (count > 0) {
                // 已经存在，不用在添加，防止出现冗余数据
                continue;
            }
            channelDept = new ChannelDept();
            channelDept.setTenantId(tenantId);
            channelDept.setDeptId(deptId);
            channelDept.setChannelId(channel.getId());
            list.add(channelDept);
        }

        if (!CollectionUtils.isEmpty(list)) {
            channelDeptMapper.insertBatch(list);
        }
    }

    /**
     * 新增航段部门数据
     * 1、先删除原有记录数据
     * 2、新增此次提交的数据
     *
     * @param tenantId    租户Id
     * @param deptId      部门Id
     * @param legList 航段集合
     * @return 结果
     */
    private void addSectionToDept(String tenantId, String deptId, List<Leg> legList) {
        List<String> legIdList = legList.stream().map(o -> o.getId()).collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        map.put("tenantId", tenantId);
        map.put("deptId", deptId);
        map.put("legIdList", legIdList);
        legDeptMapper.deleteBatchByMap(map);
        List<LegDept> list = new ArrayList<>();
        LegDept legDept;
        for (Leg leg : legList) {
            Integer count = legDeptMapper.selectCount(new LambdaQueryWrapper<LegDept>()
                    .eq(LegDept::getTenantId, tenantId)
                    .eq(LegDept::getDeptId, deptId)
                    .eq(LegDept::getLegId, leg.getId()));
            if (count > 0) {
                // 已经存在，不用在添加，防止出现冗余数据
                continue;
            }

            legDept = new LegDept();
            legDept.setTenantId(tenantId);
            legDept.setDeptId(deptId);
            legDept.setLegId(leg.getId());
            list.add(legDept);
        }
        if (!CollectionUtils.isEmpty(list)) {
            legDeptMapper.insertBatch(list);
        }
    }

    /**
     * 如果创建的是顶级部门，将该部门与超级管理员关联
     */
    private void updateSuperAdminUser(String userId, String tenantId, Dept dept) {
        if (!SystemConstant.ROOT_DEPT_PID.equals(dept.getPid())) {
            return;
        }
        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>()
                .eq(User::getTenantId, tenantId)
                .eq(User::getDataPermission, 1)
                .eq(User::getMark, MarkEnum.VALID.getCode()));
        if (CollectionUtils.isEmpty(userList)) {
            log.info("用户为空");
            return;
        }
        List<String> userIdList = userList.stream().map(o -> o.getId()).collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        map.put("deptId", dept.getId());
        map.put("idList", userIdList);
        map.put("updateUser", userId);
        map.put("updateTime", DateUtils.now());
        userMapper.updateDeptIdByIdList(map);
    }

}
