package cn.iocoder.yudao.module.system.api.robot;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.api.robot.vo.RobotUpdatePalletHeightDTO;
import cn.iocoder.yudao.module.system.constant.CommonConstant;
import cn.iocoder.yudao.module.system.dal.dataobject.config.CommonConfigDO;
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseTakePointDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotWarnMsgDO;
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.RobotWarnMsgMapper;
import cn.iocoder.yudao.module.system.enums.robot.ReleaseTakeEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotTaskTypeEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotWarnType;
import cn.iocoder.yudao.module.system.enums.robot.task.RobotCommandTypeEnum;
import cn.iocoder.yudao.module.system.service.houselocation.WareHouseTakePointService;
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;

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

@Slf4j
@RestController // 提供 RESTful API 接口，给 Feign 调用
@Validated
public class RobotUpdatePalletHeightApiImpl implements RobotUpdatePalletHeightApi {

    @Autowired
    private RobotTaskDetailMapper robotTaskDetailMapper;

    @Resource
    private WareHouseLocationMapper houseLocationMapper;

    @Resource
    private RobotWarnMsgMapper warnMsgMapper;

    @Autowired
    private RobotInformationService robotInformationService;

    @Resource
    private WareHouseTakePointService houseTakePointService;

    public static String WARN_CODE = "100001";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePalletHeight(String message) {
        log.info("111111高度反馈 :{}", message);
        TenantContextHolder.setTenantId(1L);
        RobotUpdatePalletHeightDTO data = JSON.parseObject(message, RobotUpdatePalletHeightDTO.class);
        if (RobotCommandTypeEnum.WORK_DROP_OFF_GOODS.getType().equals(data.getCommandType())) {
            dropOffGoods(data);
        } else if (RobotCommandTypeEnum.WORK_PICK_UP_GOODS.getType().equals(data.getCommandType())) {
            pickUpGoods(data);
        }
    }

    /**
     * 取货高度上报
     *
     * @param data
     */
    private void pickUpGoods(RobotUpdatePalletHeightDTO data) {
        RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(data.getOrderId());
        if (ObjectUtil.isEmpty(robotTaskDetailDO) ||
                (!RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(robotTaskDetailDO.getTaskType())
                        && !RobotTaskTypeEnum.TAKE.getType().equals(robotTaskDetailDO.getTaskType()))) {
            log.info("当前任务非取放货/仅取货，不需要更新库位高度");
            addWarnMsg(data);
            return;
        }

        WareHouseLocationDO firstStorey = houseLocationMapper.selectById(robotTaskDetailDO.getFromLocationId());
        if (ObjectUtil.isEmpty(firstStorey)) {
            return;
        }
        firstStorey.setLocationTrayHeight(new BigDecimal(data.getGoodsHeight()));
        List<WareHouseLocationDO> storeyList = new ArrayList<>();
        storeyList.add(firstStorey);

        int locationStorey = firstStorey.getLocationStorey() - 1;

        WareHouseLocationDO twoStorey = houseLocationMapper.selectOne(new LambdaQueryWrapper<WareHouseLocationDO>()
                .eq(WareHouseLocationDO::getLocationStorey, locationStorey)
                .eq(WareHouseLocationDO::getMapItemId, firstStorey.getMapItemId()));
        if (ObjectUtil.isNotEmpty(twoStorey)) {
            twoStorey.setLocationTotalHeight(new BigDecimal(data.getGoodsHeight()));
            storeyList.add(twoStorey);
        }

        houseLocationMapper.updateById(storeyList);
    }

    public void addWarnMsg(RobotUpdatePalletHeightDTO data) {
        String robotNo = robotInformationService.getRobotNoByMac(data.getMac());
        RobotWarnMsgDO warnMsg = RobotWarnMsgDO.builder().warnLevel(4)
                .warnCode(WARN_CODE)
                .robotNo(robotNo)
                .warnType(RobotWarnType.ROBOT_WARN.getType())
                .warnMsg(data.getOrderId() + CommonConstant.SYMBOL + "不需要更新库位高度")
                .build();
        warnMsgMapper.insert(warnMsg);
    }

    /**
     * 放货高度
     *
     * @param data
     */
    @Transactional(rollbackFor = Exception.class)
    public void dropOffGoods(RobotUpdatePalletHeightDTO data) {
        RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(data.getOrderId());
        if (ObjectUtil.isEmpty(robotTaskDetailDO) ||
                (!RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(robotTaskDetailDO.getTaskType())
                        && !RobotTaskTypeEnum.RELEASE.getType().equals(robotTaskDetailDO.getTaskType()))) {
            log.info("当前任务非取放货/仅放货，不需要更新库位高度");
            addWarnMsg(data);
            return;
        }

        if (ReleaseTakeEnum.isLocation(robotTaskDetailDO.getReleaseType())) {
            setDropLocation(data,robotTaskDetailDO);
        } else if (ReleaseTakeEnum.TO_POINT.getType().equals(robotTaskDetailDO.getReleaseType())) {
            setDropPoint(data,robotTaskDetailDO);
        }
    }

    private void setDropPoint(RobotUpdatePalletHeightDTO data, RobotTaskDetailDO robotTaskDetailDO) {
        WareHouseTakePointDO houseTakePoint = houseTakePointService.getHouseTakePoint(robotTaskDetailDO.getToLocationId());
        houseTakePoint.setTotalHeight(new BigDecimal(data.getGoodsHeight()));
        houseTakePointService.updateById(houseTakePoint);
        WareHouseTakePointDO pointDO = new WareHouseTakePointDO();
        pointDO.setPositionMapItemId(houseTakePoint.getPositionMapItemId());
        pointDO.setTrayHeight(new BigDecimal(data.getGoodsHeight()));
        pointDO.setLocationStorey(houseTakePoint.getLocationStorey()-1);
        houseTakePointService.updateHouseTakePointByItemIdAndStorey(pointDO);
    }

    public void setDropLocation(RobotUpdatePalletHeightDTO data,RobotTaskDetailDO robotTaskDetailDO) {
        WareHouseLocationDO firstStorey = houseLocationMapper.selectById(robotTaskDetailDO.getToLocationId());
        if (ObjectUtil.isEmpty(firstStorey)) {
            return;
        }
        firstStorey.setLocationTotalHeight(new BigDecimal(data.getGoodsHeight()));
        List<WareHouseLocationDO> storeyList = new ArrayList<>();
        storeyList.add(firstStorey);

        int locationStorey = firstStorey.getLocationStorey() + 1;

        WareHouseLocationDO twoStorey = houseLocationMapper.selectOne(new LambdaQueryWrapper<WareHouseLocationDO>()
                .eq(WareHouseLocationDO::getLocationStorey, locationStorey)
                .eq(WareHouseLocationDO::getMapItemId, firstStorey.getMapItemId()));
        if (ObjectUtil.isNotEmpty(twoStorey)) {
            twoStorey.setLocationTrayHeight(new BigDecimal(data.getGoodsHeight()));
            storeyList.add(twoStorey);
        }

        houseLocationMapper.updateById(storeyList);
    }

}
