package cn.iocoder.yudao.module.system.service.robot.job;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskDetailAddVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotWarnCodeMappingDO;
import cn.iocoder.yudao.module.system.dal.mysql.houselocation.WareHouseLocationMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskMapper;
import cn.iocoder.yudao.module.system.enums.redis.RobotCacheLockEnum;
import cn.iocoder.yudao.module.system.enums.robot.LocationLockEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotTaskDetailStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotTaskStatusEnum;
import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService;
import cn.iocoder.yudao.module.system.service.robot.RobotTaskService;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static com.baomidou.mybatisplus.core.toolkit.IdWorker.getId;

@Service
@Slf4j
public class CycleServiceImpl implements CycleService {

    @Resource
    private RobotTaskMapper taskMapper;

    @Resource
    private RobotTaskDetailMapper taskDetailMapper;

    @Value("${zn.do_cycle:true}")
    private Boolean doCycle;

    @Value("${zn.task-no:ZN}")
    private String taskNo;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private WareHouseLocationMapper locationMapper;

    @Resource
    private RobotTaskService robotTaskService;
    /**
     * 创建循环任务
     */
    @Override
    public void cycleTaskJob() {
        TenantContextHolder.setTenantId(1L);

        if (!doCycle) {
            log.info("循环任务关闭了--不自动创建循环任务");
        }

        List<RobotTaskDetailDO> detailDOS = taskDetailMapper.selectAutoCreateCycleTask();

        if (ObjectUtil.isEmpty(detailDOS)) {
            log.info("---不存在需要自动创建循环的任务--");
            return;
        }

        Set<Long> taskIds = detailDOS.stream().map(RobotTaskDetailDO::getRobotTaskId).collect(Collectors.toSet());

        List<RobotTaskDO> taskList = taskMapper.selectList(new LambdaQueryWrapper<RobotTaskDO>()
                .in(RobotTaskDO::getId, taskIds));

        Map<Long, List<RobotTaskDetailDO>> taskIdMap =
                detailDOS.stream().collect(Collectors.groupingBy(RobotTaskDetailDO::getRobotTaskId));

        String incrementByKey = redisUtil.getIncrementByKey(RobotCacheLockEnum.TASK_NO.getKey());

        List<RobotTaskDO> taskDOList = new ArrayList<>();
        List<RobotTaskDetailDO> taskDetailList = new ArrayList<>();
        for (RobotTaskDO v : taskList) {
            RobotTaskDO taskData = getTaskData(incrementByKey, v);
            List<RobotTaskDetailDO> taskDetailDOS = getTaskDetailData(taskData,taskIdMap,v.getId());
            taskDOList.add(taskData);
            taskDetailList.addAll(taskDetailDOS);
        }

        taskMapper.insertBatch(taskDOList);
        taskDetailMapper.insertBatch(taskDetailList);

        List<Long> fromLocationIds = taskDetailList.stream().map(RobotTaskDetailDO::getFromLocationId).collect(Collectors.toList());
        List<Long> toLocationIds = taskDetailList.stream().map(RobotTaskDetailDO::getToLocationId).collect(Collectors.toList());
        List<Long> locationIds = new ArrayList<>();
        locationIds.addAll(fromLocationIds);
        locationIds.addAll(toLocationIds);

        List<List<Long>> fromPartition = Lists.partition(locationIds, 100);
        fromPartition.forEach(list -> {
            locationMapper.updateLocationLockList(list, -1l, LocationLockEnum.NO.getType());
        });

        List<RobotTaskDetailAddVO> bean = BeanUtils.toBean(taskDetailList, RobotTaskDetailAddVO.class);
        Map<Long, List<RobotTaskDetailAddVO>> taskDetailMap =
                bean.stream().collect(Collectors.groupingBy(RobotTaskDetailAddVO::getRobotTaskId));
        taskDetailMap.forEach((k,v) ->{
            robotTaskService.addCycle(k,v);
        });
    }

    private List<RobotTaskDetailDO> getTaskDetailData(RobotTaskDO taskData, Map<Long,
            List<RobotTaskDetailDO>> taskIdMap, Long id) {

        List<RobotTaskDetailDO> taskDetailDOList = new ArrayList<>();
        List<RobotTaskDetailDO> taskDetailDOS = taskIdMap.get(id);
        for (RobotTaskDetailDO v : taskDetailDOS) {
            RobotTaskDetailDO build = RobotTaskDetailDO.builder()
                    .robotTaskId(taskData.getId())
                    .taskType(v.getTaskType())
                    .releaseType(v.getTakeType())
                    .takeType(v.getReleaseType())
                    .releaseId(v.getTakeId())
                    .takeId(v.getReleaseId())
                    .fromLocationNo(v.getToLocationNo())
                    .fromLocationId(v.getToLocationId())
                    .fromLaneId(v.getToLaneId())
                    .toLaneId(v.getFromLaneId())
                    .toLocationNo(v.getFromLocationNo())
                    .toLocationId(v.getFromLocationId())
                    .fromLocationStorey(v.getToLocationStorey())
                    .toLocationStorey(v.getFromLocationStorey())
                    .priority(v.getPriority())
                    .taskStatus(RobotTaskDetailStatusEnum.NEW.getType())
                    .taskStage(0l)
                    .needLock(v.getNeedLock())
                    .startTime(null)
                    .endTime(null)
                    .fromLocationNumber(v.getToLocationNumber())
                    .toLocationNumber(v.getFromLocationNumber())
                    .fromMapItemId(v.getToMapItemId())
                    .toMapItemId(v.getFromMapItemId())
                    .build();
            taskDetailDOList.add(build);
        }

        return taskDetailDOList;
    }

    /**
     * 设置任务主表数据
     * @param incrementByKey
     * @param v
     * @return
     */
    public RobotTaskDO getTaskData(String incrementByKey, RobotTaskDO v ) {
        String taskNoStr = taskNo + DateUtils.getYearMonthDay() + incrementByKey;
        RobotTaskDO task = new RobotTaskDO();
        BeanUtils.copyProperties(v, task);
        task.setRemainingCycleNumber(v.getRemainingCycleNumber() - 1);
        task.setTaskNo(taskNoStr);
        task.setTaskStatus(RobotTaskStatusEnum.NEW.getType());
        task.setTaskStage(0l);
        task.setStartTime(null);
        task.setEndTime(null);
        task.setCreateTime(LocalDateTime.now());
        task.setUpdateTime(LocalDateTime.now());
        task.setId(getId());
        return task;
    }





































}
