package com.shkj.wms.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.shkj.common.constant.RedisConstant;
import com.shkj.common.core.domain.Result;
import com.shkj.common.utils.DateUtils;
import com.shkj.wms.bo.BaseBarcodesOutAddBo;
import com.shkj.wms.bo.BaseBarcodesOutQueryBo;
import com.shkj.wms.bo.BaseBarcodesOutThirdPointBo;
import com.shkj.wms.bo.BaseBarcodesOutThirdSyncBo;
import com.shkj.wms.domain.BaseBarcodesOut;
import com.shkj.wms.domain.BusinBillhead;
import com.shkj.wms.domain.BusinDataTask;
import com.shkj.wms.mapper.BaseBarcodesOutMapper;
import com.shkj.wms.service.*;
import com.shkj.wms.third.ykl.ThirdYklResult;
import com.shkj.wms.vo.BaseBarcodesOutVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 出库条码信息Service业务层处理
 *
 * @author zjx
 * @date 2023-04-06
 */
@Slf4j
@Service
public class BaseBarcodesOutServiceImpl extends ServiceImpl<BaseBarcodesOutMapper, BaseBarcodesOut> implements IBaseBarcodesOutService {
    @Autowired
    private BaseBarcodesOutMapper baseBarcodesOutMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    IBusinBillheadService iBusinBillheadService;

    @Autowired
    IBusinBillbodyService iBusinBillbodyService;

    @Autowired
    IBusinDataTaskService iBusinDataTaskService;

    @Autowired
    IBaseDeriveService iBaseDeriveService;
    @Autowired
    IBaseBarcodesInService iBaseBarcodesInService;

    @Autowired
    IBaseBarcodesOutService iBaseBarcodesOutService;


    /**
     * 出库过点时间同步
     *
     * @param bos 出库过点信息
     * @return 出库条码信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ThirdYklResult thirdSyncBaseBarcodesOutPoint(List<BaseBarcodesOutThirdPointBo> bos) {
        List<BusinDataTask> taskList = new ArrayList<>();
        List<BusinBillhead> headList = new ArrayList<>();
        List<BaseBarcodesOut> barcodesList = new ArrayList<>();
        List<String> dateList = new ArrayList<>();
        HashMap<String, Object> resultMap = new HashMap<>();
        try {
            for (BaseBarcodesOutThirdPointBo bo : bos) {
                LambdaQueryWrapper<BaseBarcodesOut> wrapper = new LambdaQueryWrapper<BaseBarcodesOut>()
                        .eq(BaseBarcodesOut::getTraverseDate, bo.getTraverseDate())
                        .last("limit 1");
                BaseBarcodesOut baseBarcodesOut = getOne(wrapper);
                if (baseBarcodesOut == null) {
                    String msg = "此过点时间信息：" + bo.getTraverseDate() + "不存在";
                    return ThirdYklResult.error(msg);
                }

                baseBarcodesOut.setTraverseDate(DateUtils.parseDate(bo.getTraverseDate()));
                baseBarcodesOut.setCancel_time(new Date());
                baseBarcodesOut.setIs_cancel("1");
                barcodesList.add(baseBarcodesOut);
                dateList.add(bo.getTraverseDate().toString());
                //根据过点时间处理正在执行的出库任务及出库单
                //根据过点时间查询出库任务；
                BusinDataTask businDataTask = iBusinDataTaskService.getBusinDataTaskByTraverseDate(DateUtils.parseDate(bo.getTraverseDate()));
                if (null != businDataTask && "0".equals(businDataTask.getTaskStatus())) {
                    businDataTask.setTaskType("4"); //作废
                    businDataTask.setUpdateTime(DateUtils.getNowDate());
                    taskList.add(businDataTask);
                } else {
                }

                BusinBillhead businBillhead = iBusinBillheadService.getBusinBillHeadByTraverseDate(DateUtils.parseDate(bo.getTraverseDate()));
                if (null != businBillhead) {
                    businBillhead.setCancleDate(DateUtils.getNowDate());
                    businBillhead.setIsCancle("1");
                    headList.add(businBillhead);
                }
            }

            if (headList.size() > 0) {
                if (!iBusinBillheadService.saveBatch(headList)) {
                    return ThirdYklResult.error("同步出库业务更新失败");
                }
            }

            if (taskList.size()>0) {
                if (!iBusinDataTaskService.saveBatch(taskList)) {
                    return ThirdYklResult.error("同步任务更新失败");
                }
            }
            if (barcodesList.size()>0) {
                if (!iBaseBarcodesOutService.saveBatch(barcodesList)) {
                    return ThirdYklResult.error("同步VIN更新失败");
                }
            }
            resultMap.put("correctDate", dateList);
            return ThirdYklResult.ok().put("data", resultMap);

        } catch (Exception e) {
            return ThirdYklResult.error(e.getMessage());
        }
    }

    /**
     * 出库信息同步
     *
     * @param bos 出库信息
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ThirdYklResult thirdSyncBaseBarcodesOut(List<BaseBarcodesOutThirdSyncBo> bos) {
        List<BaseBarcodesOut> barcodesOutList = new ArrayList<>();
        List<String> vinOkList = new ArrayList<>();
        List<String> vinErrList = new ArrayList<>();

        for (BaseBarcodesOutThirdSyncBo bo : bos) {
            vinErrList.add(bo.getVin());
            //出库车辆队列信息
            BaseBarcodesOut baseBarcodesOut = (BaseBarcodesOut) redisTemplate.opsForValue().get(RedisConstant.redisVin + bo.getVin());
            if (baseBarcodesOut == null) {
                LambdaQueryWrapper<BaseBarcodesOut> wrapper = new LambdaQueryWrapper<BaseBarcodesOut>().eq(BaseBarcodesOut::getVin, bo.getVin()).last("limit 1");
                baseBarcodesOut = getOne(wrapper);
            }
            if (baseBarcodesOut == null) {
                vinOkList.add(bo.getVin());
                baseBarcodesOut = BeanUtil.toBean(bo, BaseBarcodesOut.class);
                baseBarcodesOut.setCreateTime(DateUtils.getNowDate());
                baseBarcodesOut.setBatch(DateUtils.getDate());
                baseBarcodesOut.setOutStatus("0");
                barcodesOutList.add(baseBarcodesOut);
            } else {
                //是否把已存在的信息返回
            }
        }
        if (barcodesOutList.size() > 0) {
            if (this.saveBatch(barcodesOutList)) {
                for (BaseBarcodesOut baseBarcodesOut : barcodesOutList) {
                    redisTemplate.opsForValue().set(RedisConstant.redisVin + baseBarcodesOut.getVin(), baseBarcodesOut);
                }
                HashMap<String, Object> resultMap = new HashMap<>();
                resultMap.put("vinArr", vinOkList);
                return ThirdYklResult.ok("同步车辆队列信息").put("data", resultMap);
            } else {
                return ThirdYklResult.error().put("data", vinErrList);
            }
        } else {
            return ThirdYklResult.error("已同步");
        }
    }

    @Override
    public List<BaseBarcodesOutVo> getBarcodesOutData(BaseBarcodesOutQueryBo bo) {
        return this.baseBarcodesOutMapper.getBarcodesOutData(bo);
    }

    @Override
    public List<BaseBarcodesOutVo> getBarcodesnoOutData() {
        return this.baseMapper.getBarcodesnoOutData();
    }

    @Override
    public List<BaseBarcodesOutAddBo> selectVinOutboundList() {
        return baseMapper.selectVinOutboundList();
    }

    /**
     * 筛选订单为一个整体的货位信息
     * @param AllLocation
     * @return
     */
    public List<String> getGlobalityData(List<String> AllLocation){
        Map<String, Long> collect = AllLocation.stream().collect(Collectors.groupingBy(p -> p, Collectors.counting()));
        List<String> list = collect.entrySet().stream().filter(e -> e.getValue() >= 3).map(Map.Entry::getKey).collect(Collectors.toList());
        return list;
    }

    /**
     * 修改出货表状态
     * @param vo
     * @return
     */
    public Result<Boolean> updateStatus(BaseBarcodesOutVo vo){
        BaseBarcodesOut baseBarcodesOut=BeanUtil.toBean(vo,BaseBarcodesOut.class);
                this.baseMapper.updateById(baseBarcodesOut);
        return Result.ok();
    }
}
