/*
 * Author: wangjian
 * 生成ServiceImpl
 */
package com.tofly.dispatch.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.dispatch.common.FlowConstant;
import com.tofly.dispatch.dto.DispatchDto;
import com.tofly.dispatch.dto.UpdateDispatchDto;
import com.tofly.dispatch.entity.*;
import com.tofly.dispatch.mapper.DispatchMapper;
import com.tofly.dispatch.service.DispatchExpertRService;
import com.tofly.dispatch.service.DispatchLogService;
import com.tofly.dispatch.service.DispatchOrderService;
import com.tofly.dispatch.service.DispatchService;
import com.tofly.dispatch.vo.DispatchTreeVo;
import com.tofly.dispatch.vo.DispatchVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 供水调度（日常->名称->详情；开关阀->方案->名称->详情）
 *
 * @author xqf
 * @date Mon Mar 14 00:00:00 CST 2022
 */
@Service("dispatchService")
public class DispatchServiceImpl extends ServiceImpl<DispatchMapper, Dispatch> implements DispatchService {

    @Autowired
    private DispatchLogService dispatchLogService;
    @Autowired
    private DispatchExpertRService dispatchExpertRService;
    @Autowired
    private DispatchOrderService dispatchOrderService;

    /**
     * 保存方案名称
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public Object saveDispatch(DispatchDto dto) {
        Dispatch dispatch = new Dispatch();
        BeanUtils.copyProperties(dto,dispatch);
        if(dispatch.getUpDispatchId()==null){
            dispatch.setUpDispatchId(FlowConstant.LONG_ZERO);
        }
        //是否重名
        int count = this.count(new QueryWrapper<Dispatch>().lambda()
                .eq(Dispatch::getDispatchType,dispatch.getDispatchType())
                .eq(Dispatch::getDispatchSchemeName,dispatch.getDispatchSchemeName())
                .eq(Dispatch::getIsDel,FlowConstant.SHORT_ZERO)
                .eq(Dispatch::getUpDispatchId,dispatch.getUpDispatchId()));
        if(count>0){
            return FlowConstant.NAME_EXISTS;
        }
        if(dispatch.getUpDispatchId()!=FlowConstant.LONG_ZERO) {
           if( this.getById(dispatch.getUpDispatchId())==null){
               return FlowConstant.DATA_NOTHINGNESS;
           }
           if(dispatch.getDispatchType()!=FlowConstant.SHORT_TWO){
               return FlowConstant.TYPE_ERROR;
           }
           //子级只允许1级并且是 开关阀/泵类型
           count = this.baseMapper.upDispatchCount(dispatch.getUpDispatchId(),FlowConstant.SHORT_TWO);
           if(count>1){
               return FlowConstant.CHILD_LEVEL_NO_ADD;
           }
        }
        if(dispatch.getIsValid()==null){
            dispatch.setIsValid(FlowConstant.SHORT_ONE);
        }
        dispatch.setIsDel(FlowConstant.SHORT_ZERO);

        if(this.save(dispatch)){

            if(StringUtils.isNotEmpty(dispatch.getDispatchExpertIds())){
                for (String dispatchExpertId:dispatch.getDispatchExpertIds().split(",")
                ) {
                    DispatchExpertR dispatchExpertR=new DispatchExpertR();
                    dispatchExpertR.setDispatchExpertId(Long.parseLong(dispatchExpertId));
                    dispatchExpertR.setDispatchId(dispatch.getId());
                    dispatchExpertRService.save(dispatchExpertR);
                }

            }
             return dispatch.getId();
        }
        return null;
    }

    /**
     * 查询父级数据条数，包含本身
     * @param id 主键id
     * @return
     */
    @Override
    public int upDispatchCount(Long id,Short type){
        return this.baseMapper.upDispatchCount(id,type);
    }
    @Override
    public int upDispatchCount(Long id){
        return this.baseMapper.upDispatchCount(id,FlowConstant.SHORT_TWO);
    }

    /**
     * 修改方案名称
     * @param dto 对象信息
     * @return
     */
    @Override
    @Transactional
    public Object updateDispatchById(UpdateDispatchDto dto) {
        Dispatch dispatch = new Dispatch();
        BeanUtils.copyProperties(dto,dispatch);

        Dispatch dbinfo = this.getById(dispatch.getId());
        if(dbinfo==null){
            return FlowConstant.DATA_NOTHINGNESS;
        }
        //是否重名
        int count = this.count(new QueryWrapper<Dispatch>().lambda()
                .eq(Dispatch::getDispatchType,dbinfo.getDispatchType())
                .eq(Dispatch::getDispatchSchemeName,dispatch.getDispatchSchemeName())
                .eq(Dispatch::getUpDispatchId,dbinfo.getUpDispatchId())
                .eq(Dispatch::getIsDel,FlowConstant.SHORT_ZERO)
                .ne(Dispatch::getId,dispatch.getId()));
        if(count>0){
            return FlowConstant.NAME_EXISTS;
        }
        //删除专家库关联关系
        QueryWrapper<DispatchExpertR> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("DISPATCH_ID",dispatch.getId());
         dispatchExpertRService.remove(queryWrapper);
        if(StringUtils.isNotEmpty(dispatch.getDispatchExpertIds())){
            for (String dispatchExpertId:dispatch.getDispatchExpertIds().split(",")
            ) {
                DispatchExpertR dispatchExpertR=new DispatchExpertR();
                dispatchExpertR.setDispatchExpertId(Long.parseLong(dispatchExpertId));
                dispatchExpertR.setDispatchId(dispatch.getId());
                dispatchExpertRService.save(dispatchExpertR);
            }

        }else{
            dispatch.setDispatchExpertIds("");
        }

        if(dispatch.getWaterInfoId()==null){
            dispatch.setWaterInfoId("");
        }
        return this.updateById(dispatch);
    }

    /**
     * 删除方案
     * @param id 主键id
     * @return
     */
    @Override
    @Transactional
    public boolean removeUpdateById(Long id) {
        checkIsDel(id+"");
        //删除专家库关联关系
        QueryWrapper<DispatchExpertR> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("DISPATCH_ID",id);
        dispatchExpertRService.remove(queryWrapper);

        return update(new UpdateWrapper<Dispatch>().lambda().set(Dispatch::getIsDel,FlowConstant.SHORT_ONE)
                .set(Dispatch::getUpdateTime,new Date()).set(Dispatch::getUpdateUser, SecurityUtils.getUserId())
                .eq(Dispatch::getIsDel,FlowConstant.SHORT_ZERO)
                .eq(Dispatch::getId,id));
    }

    /**
     * 调度方案删除权限
     * @param ids 主键id
     * @return
     */
    public  void checkIsDel(String ids){
        List<String> list = Arrays.asList(ids.split(","));
        QueryWrapper<DispatchLog> log_queryWrapper=new QueryWrapper<>();
        log_queryWrapper.in("DISPATCH_ID",list);
        Integer count_check = dispatchLogService.count(log_queryWrapper);

        if(count_check>0){
            throw new RuntimeException("在调度日志存在数据不允许删除");
        }

      //指令里面是否存在
        QueryWrapper<DispatchOrder> order_queryWrapper=new QueryWrapper<>();
        order_queryWrapper.in("DISPATCH_ID",list);
        Integer count_order = dispatchOrderService.count(order_queryWrapper);

        if(count_order>0){
            throw new RuntimeException("在指令管理中存在数据不允许删除");
        }

    }

    @Override
    @Transactional
    public Object removeUpdateByIds(String ids) {

        checkIsDel(ids);
        try {
            //删除专家库关联关系
            QueryWrapper<DispatchExpertR> queryWrapper=new QueryWrapper<>();
            queryWrapper.in("DISPATCH_ID",ids.split(","));
            dispatchExpertRService.remove(queryWrapper);

            List<Long> lids= Arrays.asList(ids.split(",")).stream().map(st->Long.parseLong(st)).collect(Collectors.toList());
            return this.baseMapper.update(new Dispatch(),new UpdateWrapper<Dispatch>().lambda()
                    .set(Dispatch::getIsDel,FlowConstant.SHORT_ONE)
                    .eq(Dispatch::getIsDel,FlowConstant.SHORT_ZERO)
                    .in(Dispatch::getId,lids));
        }catch (Exception e){
            log.error("异常：",e);
            return e.getMessage();
        }
    }

    @Override
    public Object getDispatchTree(String types) {
        List<Short> lids= null;
        try {
            if(StringUtils.isNotEmpty(types)) {
                lids = Arrays.asList(types.split(",")).stream().map(st -> Short.parseShort(st)).collect(Collectors.toList());
            }
        }catch (Exception e){
            log.error("异常：",e);
            return e.getMessage();
        }

        List<Dispatch> ds= this.list(new QueryWrapper<Dispatch>().lambda()
                .eq(Dispatch::getIsDel,FlowConstant.SHORT_ZERO)
                .in(CollUtil.isNotEmpty(lids),Dispatch::getDispatchType,lids).orderByAsc(Dispatch::getUpDispatchId));
        Map<Short,DispatchTreeVo> tmap = new HashMap<>();
        if(CollUtil.isNotEmpty(ds)) {
            Map<Long,DispatchVo> map = new HashMap<>();
            for (Dispatch d : ds) {
                DispatchTreeVo treeVo = null;
                if(tmap.containsKey(d.getDispatchType())){
                    treeVo = tmap.get(d.getDispatchType());
                }else {
                    treeVo = new DispatchTreeVo();
                    treeVo.setDispatchType(d.getDispatchType());
                    treeVo.setVos(new ArrayList<>());
                    tmap.put(d.getDispatchType(),treeVo);
                }
                DispatchVo vo = new DispatchVo();
                BeanUtils.copyProperties(d,vo);
                vo.setChildLevel(new ArrayList<>());
                if(FlowConstant.LONG_ZERO==d.getUpDispatchId()){
                    treeVo.getVos().add(vo);
                    map.put(d.getId(),vo);
                }else {
                    if(map.containsKey(d.getUpDispatchId())){
                        map.get(d.getUpDispatchId()).getChildLevel().add(vo);
                    }
                }
            }
        }
        List<DispatchTreeVo> list = tmap.values().stream().collect(Collectors.toList());
        return list;
    }
}
