package cn.iocoder.yudao.module.system.handler.mapnode.strategy;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.system.controller.admin.houselocation.vo.WareHouseLocationRespVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.dto.NodeBaseDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
import cn.iocoder.yudao.module.system.service.houselocation.HouseLocationService;
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapService;
import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

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

import static cn.hutool.core.collection.CollUtil.isNotEmpty;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static com.baomidou.mybatisplus.core.toolkit.IdWorker.getId;

@Slf4j
@Component
public class HouseLocationStrategyImpl implements NodeProcessingStrategy {
    @Resource
    private HouseLocationService houseLocationService;

    @Resource
    @Lazy
    private RobotTaskDetailService taskDetailService;

    @Resource
    private PositionMapService positionMapService;

    //库位编号格式 - 第一个通配符为地图id 第二个通配符为随机数四位最后一个通配符为库位点层数
    private static final String KW_NO_FORMAT = "KW-%s-%s-%s";

    @Override
    public void processNodes(Long positionMapId, List<NodeBaseDTO> nodeBaseDTOS) {
        // -- 策略1 处理库位点
        // -- 将data里面的json 数据转为实体类 - 再对比节点id - 然后做新增删除修改操作
        List<WareHouseLocationDO> newList = new ArrayList<>();

        PositionMapDO positionMap = positionMapService.getPositionMap(positionMapId);
        Long locationNoSort = positionMap.getLocationNoSort();

        for (NodeBaseDTO item : nodeBaseDTOS) {
            if (item.getId() == null) {
                item.setId(getId());
            }
            item.setPositionMapId(positionMapId);
            // -- 如果是库位点 - 可能是一对多情况 - 需要将多个库位点的id set进去
            List<WareHouseLocationDO> wareHouseLocationDOS = JSONUtil.toList(item.getDataJson(), WareHouseLocationDO.class);
            // -- 筛选出 库位编号不为空 - 并且第最后一组数据 最大的值 - 如果没有则为0
//            int max = wareHouseLocationDOS.stream().map(WareHouseLocationDO::getLocationNo).filter(StrUtil::isNotEmpty)
//                    .mapToInt(s -> Integer.parseInt(s.substring(s.length() - 1))).max().orElse(1);
//            boolean isNew = wareHouseLocationDOS.stream().allMatch(v -> ObjectUtil.isEmpty(v.getLocationNo()));

            int max = 1;
            boolean isNew = true;
            Long randomNumber = locationNoSort;
            for (WareHouseLocationDO wareHouseLocation : wareHouseLocationDOS) {
                if (ObjectUtil.isEmpty(wareHouseLocation.getLocationNo())) {
                    continue;
                }
                isNew = false;
                int i = Integer.parseInt(wareHouseLocation.getLocationNo().substring(wareHouseLocation.getLocationNo().length() - 1));
                if (i > max) {
                    max = i;
                }
                String[] split = wareHouseLocation.getLocationNo().split("-");
                randomNumber = Long.valueOf(split[split.length - 2]);
            }

            if (!isNew) {
                max = max + 1;
            } else {
                locationNoSort = locationNoSort + 1L;
            }
            Long locationNumber = null;
            if (ObjectUtil.isNotEmpty(item.getLocationNumber())) {
                locationNumber = item.getLocationNumber();
            }
            for (WareHouseLocationDO wareHouseLocationDO : wareHouseLocationDOS) {
                wareHouseLocationDO.setLocationX(item.getLocationX());
                wareHouseLocationDO.setLocationY(item.getLocationY());
                wareHouseLocationDO.setActualLocationX(item.getActualLocationX());
                wareHouseLocationDO.setActualLocationY(item.getActualLocationY());
                if (wareHouseLocationDO.getId() == null) {
                    wareHouseLocationDO.setId(getId());
                }
                if (1 == max) {
                    wareHouseLocationDO.setLocationTrayHeight(new BigDecimal("0"));
                }
                if (StrUtil.isEmpty(wareHouseLocationDO.getLocationNo())) {
                    wareHouseLocationDO.setLocationStorey(max);
                    // -- 生成库位编号 -
//                    String locationNo = String.format(KW_NO_FORMAT, positionMapId, RandomUtil.randomNumbers(4), max++);
                    String locationNo = String.format(KW_NO_FORMAT, positionMapId, randomNumber, max++);
                    wareHouseLocationDO.setLocationNo(locationNo);
                }
                wareHouseLocationDO.setMapId(positionMapId);
                wareHouseLocationDO.setMapItemId(item.getId());
                if (ObjectUtil.isNotEmpty(locationNumber) && ObjectUtil.isEmpty(wareHouseLocationDO.getLocationNumber())) {
                    wareHouseLocationDO.setLocationNumber(locationNumber);
                    locationNumber = locationNumber - 10;
                }
                newList.add(wareHouseLocationDO);
            }
            item.setDataJson(JSONUtil.toJsonStr(wareHouseLocationDOS));
        }

        List<WareHouseLocationDO> oldList = houseLocationService.getByMapId(positionMapId);
        List<List<WareHouseLocationDO>> list = CollectionUtils.compareLists(oldList, newList,
                (oldVal, newVal) -> ObjectUtil.equal(oldVal.getId(), newVal.getId()));

        /*if (isNotEmpty(list.get(2))) {
            checkLocationHaveDoingTask(list);
        }*/

        positionMapService.updateNoSort(positionMap.getId(),locationNoSort);
        houseLocationService.batchSaveOrEditOrDel(positionMapId, list);
    }

    /**
     * 校验要删除的库位是否有处理中的任务
     *
     * @param list
     */
    public void checkLocationHaveDoingTask(List<List<WareHouseLocationDO>> list) {
        List<Long> ids = convertList(list.get(2), WareHouseLocationDO::getId);
        List<RobotTaskDetailDO> details = taskDetailService.getDoingTaskDetailByLocationIds(ids);
        if (ObjectUtil.isNotEmpty(details)) {
            List<String> locationNos = new ArrayList<>();
            for (RobotTaskDetailDO detail : details) {
                if (ObjectUtil.isNotEmpty(detail.getFromLocationId()) && ids.contains(detail.getFromLocationId())) {
                    locationNos.add(detail.getFromLocationNo());
                    continue;
                }
                if (ObjectUtil.isNotEmpty(detail.getToLocationId()) && ids.contains(detail.getToLocationId())) {
                    locationNos.add(detail.getToLocationNo());
                }
            }

            String join = StringUtils.join(locationNos, ",");
            throw exception0(HOUSE_LOCATION_HAVE_TASK.getCode(), "以下库位存在处理中的任务:" + join, join);
        }
    }
}
