package com.huaheng.api.mes.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.huaheng.api.acs.domain.AgvTaskCS;
import com.huaheng.api.acs.service.AgvTaskCSService;
import com.huaheng.api.general.domain.ReceiptDomain;
import com.huaheng.api.general.domain.ShipmentDomain;
import com.huaheng.api.general.service.ReceiptApiService;
import com.huaheng.api.general.service.ShipmentApiService;
import com.huaheng.api.mes.domain.AcsTask;
import com.huaheng.api.mes.domain.InventoryDetailQuery;
import com.huaheng.api.mes.domain.MesTask;
import com.huaheng.api.mes.domain.TaskHeaderQuery;
import com.huaheng.api.rcs.service.RcsService;
import com.huaheng.common.constant.QuantityConstant;
import com.huaheng.common.support.Convert;
import com.huaheng.common.utils.StringUtils;
import com.huaheng.common.utils.Wrappers;
import com.huaheng.common.utils.http.OkHttpUtils;
import com.huaheng.common.utils.security.ShiroUtils;
import com.huaheng.framework.token.TokenService;
import com.huaheng.framework.web.controller.BaseController;
import com.huaheng.framework.web.domain.AjaxResult;
import com.huaheng.framework.web.domain.Result;
import com.huaheng.framework.web.page.TableDataInfo;
import com.huaheng.pc.config.address.service.AddressService;
import com.huaheng.pc.config.container.domain.Container;
import com.huaheng.pc.config.container.service.ContainerService;
import com.huaheng.pc.config.location.domain.Location;
import com.huaheng.pc.config.location.service.LocationService;
import com.huaheng.pc.config.locationType.domain.LocationType;
import com.huaheng.pc.config.locationType.service.LocationTypeService;
import com.huaheng.pc.config.material.domain.Material;
import com.huaheng.pc.config.material.service.MaterialService;
import com.huaheng.pc.config.zone.domain.Zone;
import com.huaheng.pc.config.zone.service.ZoneService;
import com.huaheng.pc.inventory.inventoryDetail.domain.InventoryDetail;
import com.huaheng.pc.inventory.inventoryDetail.service.InventoryDetailService;
import com.huaheng.pc.inventory.inventoryHeader.domain.InventoryHeader;
import com.huaheng.pc.inventory.inventoryHeader.service.InventoryHeaderService;
import com.huaheng.pc.receipt.receiptContainerDetail.domain.ReceiptContainerDetail;
import com.huaheng.pc.receipt.receiptContainerDetail.service.ReceiptContainerDetailService;
import com.huaheng.pc.receipt.receiptContainerHeader.domain.ReceiptContainerView;
import com.huaheng.pc.receipt.receiptContainerHeader.service.ReceiptContainerHeaderService;
import com.huaheng.pc.receipt.receiptDetail.domain.ReceiptDetail;
import com.huaheng.pc.receipt.receiptHeader.domain.ReceiptHeader;
import com.huaheng.pc.receipt.receiptHeader.service.ReceiptHeaderService;
import com.huaheng.pc.shipment.shipmentContainerHeader.domain.ShipmentCombinationModel;
import com.huaheng.pc.shipment.shipmentContainerHeader.domain.ShipmentContainerHeader;
import com.huaheng.pc.shipment.shipmentContainerHeader.service.ShipmentContainerHeaderService;
import com.huaheng.pc.shipment.shipmentDetail.domain.ShipmentDetail;
import com.huaheng.pc.shipment.shipmentHeader.domain.ShipmentHeader;
import com.huaheng.pc.system.user.domain.User;
import com.huaheng.pc.system.user.service.IUserService;
import com.huaheng.pc.task.taskHeader.domain.TaskHeader;
import com.huaheng.pc.task.taskHeader.mapper.TaskHeaderMapper;
import com.huaheng.pc.task.taskHeader.service.ReceiptTaskService;
import com.huaheng.pc.task.taskHeader.service.TaskHeaderService;
import com.huaheng.pc.task.taskHeader.service.WorkTaskService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * mes接口实现层
 * @author xcq
 */
@Service
public class MesServiceImpl extends BaseController implements MesService{
    @Resource
    private TaskHeaderService taskHeaderService;
    @Resource
    private AgvTaskCSService agvTaskCSService;
    @Resource
    private AddressService addressService;
    @Resource
    private LocationTypeService locationTypeService;
    @Resource
    private LocationService locationService;

    @Override
    public AjaxResult sendTaskToAcs(TaskHeader taskHeader) {
        if (taskHeader == null){
            throw new RuntimeException("AGV任务参数不能为空!");
        }
        // 判断任务id是否为空
        if (taskHeader.getId() == null){
            throw new RuntimeException("任务ID不能为空!");
        }
        AcsTask acsTask = new AcsTask();
        acsTask.setTaskNo(taskHeader.getId());
        if (taskHeader.getStatus() > QuantityConstant.AGV_TASK_STATUS_RELEASE){
            throw new RuntimeException("任务已下发!");
        }
        // 整盘出库任务和空托出库任务
        if (taskHeader.getTaskType() == QuantityConstant.TASK_TYPE_WHOLESHIPMENT
                || taskHeader.getTaskType() == QuantityConstant.TASK_TYPE_EMPTYSHIPMENT){
            // 设置起点
            acsTask.setEndPoint(taskHeader.getFromLocation());
            // 设置终点
            acsTask.setBeginPoint(taskHeader.getPickingCartPos());
        }
        // 整盘入库和空托入库任务
        if (taskHeader.getTaskType() == QuantityConstant.TASK_TYPE_WHOLERECEIPT
                || taskHeader.getTaskType() == QuantityConstant.TASK_TYPE_EMPTYRECEIPT){
            // 设置起点
            acsTask.setEndPoint(taskHeader.getPickingCartPos());
            // 设置终点
            acsTask.setBeginPoint(taskHeader.getToLocation());
        }
        // 判断起点是否为空
        if (StringUtils.isEmpty(acsTask.getEndPoint())){
            throw new RuntimeException("起点位置不能为空!");
        }
        if (StringUtils.isEmpty(acsTask.getBeginPoint())){
            throw new RuntimeException("终点位置不能为空!");
        }
        String JsonParam = JSON.toJSONString(acsTask);
        // 获取下发ACS地址
        String url = addressService.selectAddress(QuantityConstant.AGV_TASK_ASSIGN,QuantityConstant.WAREHOUSE_KS );
        String str = OkHttpUtils.sendPost(url, JsonParam);
        if (StringUtils.isEmpty(str)){
            throw new RuntimeException("下发AGV任务失败,返回结果为空!");
        }
        AjaxResult result = JSON.parseObject(str, AjaxResult.class);
        if (result.hasErr()){
            return result;
        }
        taskHeader.setStatus(QuantityConstant.AGV_TASK_STATUS_BUILD);
        taskHeaderService.updateById(taskHeader);
        return result;
    }

    @Override
    public AjaxResult cancelACSTaskService(Integer id) {
        TaskHeader taskHeader = taskHeaderService.getById(id);
        if (taskHeader == null){
            return AjaxResult.error("根据id查询任务表失败!");
        }
        if (QuantityConstant.AGV_TASK_STATUS_EXECUTE == taskHeader.getStatus()){
            return AjaxResult.error("AGV任务已经执行无法取消!");
        }
        AcsTask acsTask = new AcsTask();
        acsTask.setTaskNum(id);
        acsTask.setTaskNo(id);
        String JsonParam = JSON.toJSONString(acsTask);
//        String url = addressService.selectAddress(QuantityConstant.AGV_TASK_CANCEL,QuantityConstant.WAREHOUSE_KS );
//        String str = OkHttpUtils.sendPost(url, JsonParam);
//        if (StringUtils.isEmpty(str)){
//            throw new RuntimeException("取消AGV任务失败,返回结果为空!");
//        }
//        AjaxResult result = JSON.parseObject(str, AjaxResult.class);
//        if (result.hasErr()){
//            return result;
//        }
        AjaxResult result = taskHeaderService.cancelTask(Convert.toIntArray(taskHeader.getId().toString()));
        return result;
    }

    @Resource
    private ReceiptHeaderService receiptHeaderService;
    @Resource
    private ReceiptApiService receiptApiService;
    @Resource
    private MesService mesService;
    @Resource
    private MaterialService materialService;
    @Resource
    private IUserService userService;

    @Override
    public AjaxResult createTaskService(MesTask mesTask) {
        if (mesTask == null){
            return AjaxResult.error("请勿提交空数据!");
        }
        // 根据区域编码查询
        LambdaQueryWrapper<LocationType> lambda = Wrappers.lambdaQuery();
        lambda.eq(LocationType::getCode, mesTask.getArea());
        LocationType locationType = locationTypeService.getOne(lambda);
        if (locationType == null){
            return AjaxResult.error("该区域编码:"+mesTask.getArea()+"不存在");
        }
        // 模拟mes登录
        userService.login(QuantityConstant.PLATFORM_MES, QuantityConstant.PLATFORM_MES_PASSWORD, QuantityConstant.WAREHOUSE_KS, false);
        // 判断是开工还是完工
        if (mesTask.isType()){
            // 出库任务
            return mesService.createShipment(mesTask);
        }else {
            // 创建入库任务
            return mesService.createReceipt(mesTask);
        }
    }

    @Resource
    private ReceiptContainerHeaderService receiptContainerHeaderService;
    @Resource
    private ReceiptContainerDetailService receiptContainerDetailService;
    @Resource
    private ReceiptTaskService receiptTaskService;
    @Resource
    private ShipmentContainerHeaderService shipmentContainerHeaderService;

    @Override
    @Transactional
    public AjaxResult createReceipt(MesTask mesTask) {
//        // 查询当前位置是否已经存在入库任务
//        LambdaQueryWrapper<AgvTaskCS> queryWrapper = Wrappers.lambdaQuery();
//        queryWrapper.lt(AgvTaskCS::getStatus, QuantityConstant.AGV_TASK_STATUS_COMPLETE)
//                .eq(AgvTaskCS::getFromPort, mesTask.getStation()).last("limit 1");
//        AgvTaskCS agvTaskCS = agvTaskCSService.getOne(queryWrapper);
//        if (agvTaskCS != null){
//            AjaxResult result = AjaxResult.success("任务已存在,请勿重复请求!");
//            result.setData(agvTaskCS);
//            return result;
//        }
//        // 根据区查询可以分配的库位
//        LambdaQueryWrapper<Location> query = Wrappers.lambdaQuery();
//        query.eq(Location::getZoneCode, mesTask.getArea())
//                .eq(Location::getContainerCode, "")
//                .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY)
//                .last("limit 1");
//        Location location = locationService.getOne(query);
//        if (location == null){
//            throw new RuntimeException("当前区域没有空闲库位请检查!");
//        }
//        // 新增入库单之前先判断物料是否存在
//        AjaxResult result = mesService.addMaterial(mesTask);
//        if (result.hasErr()){
//            return result;
//        }
//        ReceiptDetail receiptDetail = mesService.createReceiptDocuments(mesTask);
//        // 创建AGV入库任务
//        result = mesService.createAgvTask(QuantityConstant.AGV_TYPE_TAKE, mesTask.getStation(), location.getCode(), receiptDetail.getReceiptCode());
//        if (result.hasErr()){
//            return result;
//        }
//        // 任务创建成功锁定库位
//        Location temp = new Location();
//        temp.setId(location.getId());
//        temp.setStatus(QuantityConstant.STATUS_LOCATION_LOCK);
//        locationService.updateById(temp);

        // 查询当前位置是否已经存在入库任务
//        LambdaQueryWrapper<TaskHeader> taskHeaderLambdaQueryWrapper = Wrappers.lambdaQuery();
//        taskHeaderLambdaQueryWrapper.eq(TaskHeader::getPickingCartPos, mesTask.getStation())
//                .lt(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_COMPLETED);
//        TaskHeader taskHeader = taskHeaderService.getOne(taskHeaderLambdaQueryWrapper);
//        if (taskHeader != null){
//            AjaxResult result = AjaxResult.success("该点位已创建任务请勿重复创建!");
//            result.setData(taskHeader);
//            return result;
//        }

        // 校验任务是否已经存在
        AjaxResult result = mesService.checkStation(mesTask.getStation(), QuantityConstant.TASK_TYPE_WHOLERECEIPT);
        if (!result.hasErr()){
            return result;
        }
        // 新增入库单之前先判断物料是否存在
        result = mesService.addMaterial(mesTask);
        if (result.hasErr()){
            return result;
        }
        Container container = null;
        // 判断是光腾车间任务还是机加库任务
        String locationCode = null;
        if (StringUtils.isEmpty(mesTask.getOrderCode())){
            // 根据区查询可以分配的库位
            LambdaQueryWrapper<Location> query = Wrappers.lambdaQuery();
            query.eq(Location::getLocationType, mesTask.getArea())
                    .eq(Location::getContainerCode, "")
                    .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY)
                    .last("limit 1");
            Location location = locationService.getOne(query);
            if (location == null){
                throw new RuntimeException("当前库区没有可用库位!");
            }
            locationCode = location.getCode();
        }
        LambdaQueryWrapper<Container> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(Container::getCode, mesTask.getContainerCode());
        container = containerService.getOne(lambdaQueryWrapper);
        if (container == null){
            throw new RuntimeException("查询当前容器编码:"+mesTask.getContainerCode()+"不存在!");
        }
        if (QuantityConstant.STATUS_CONTAINER_LOCK.equals(container.getStatus())){
            throw new RuntimeException("当前容器已经存在任务,请勿重复下发!");
        }
        // 判断当前容器是否在库位上
        if (StringUtils.isNotEmpty(container.getLocationCode())){
            throw new RuntimeException("当前容器已经在库位上请更换托盘码!");
        }
        // 创建入库单
        ReceiptDetail receiptDetail = mesService.createReceiptDocuments(mesTask);
        // 进行入库组盘
        ReceiptContainerView receiptContainerView = new ReceiptContainerView();
        receiptContainerView.setContainerCode(container.getCode());
        receiptContainerView.setReceiptCode(receiptDetail.getReceiptCode());
        receiptContainerView.setReceiptDetailId(receiptDetail.getId());
        receiptContainerView.setLocationCode(locationCode);
        receiptContainerView.setQty(BigDecimal.valueOf(mesTask.getQty()));
        result = receiptContainerHeaderService.saveContainer(receiptContainerView);
        if (result.hasErr()){
            throw new RuntimeException(result.getMsg());
        }
        // 通过入库单详情id获取组盘详情
        LambdaQueryWrapper<ReceiptContainerDetail> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ReceiptContainerDetail::getReceiptDetailId, receiptDetail.getId());
        ReceiptContainerDetail receiptContainerDetail = receiptContainerDetailService.getOne(queryWrapper);
        if (receiptContainerDetail == null){
            throw new RuntimeException("获取入库组盘失败!");
        }
        // 创建入库任务
        List<Integer> idList = new ArrayList<>(1);
        idList.add(receiptContainerDetail.getReceiptContainerId());
        result = receiptTaskService.createReceiptTask(idList);
        if (result.hasErr()){
            throw new RuntimeException(result.getMsg());
        }
        // 获取创建的入库任务
        LambdaQueryWrapper<TaskHeader> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.eq(TaskHeader::getAllocationHeadId, receiptContainerDetail.getReceiptContainerId());
        TaskHeader taskHeader = taskHeaderService.getOne(lambdaQuery);
        if (taskHeader == null){
            throw new RuntimeException("创建入库任务失败!");
        }
        // 将mes的任务号写入入库任务头表
        TaskHeader taskHeaderTemp = new TaskHeader();
        taskHeaderTemp.setPickingCartPos(mesTask.getStation());
        taskHeaderTemp.setId(taskHeader.getId());
        taskHeaderService.updateById(taskHeaderTemp);
        result.setData(taskHeader);
        result.setMsg("入库任务下发成功!");
        return result;
    }

    @Override
    @Transactional
    public AjaxResult createShipment(MesTask mesTask) {
        // 查询当前位置是否已经存在出库任务
        AjaxResult result = mesService.checkStation(mesTask.getStation(), QuantityConstant.TASK_TYPE_WHOLESHIPMENT);
        if (!result.hasErr()){
            return result;
        }
        LambdaQueryWrapper<Location> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Location::getLocationType, mesTask.getArea());
        List<Location> locationList = locationService.list(queryWrapper);
        if (locationList.size() == 0){
            throw new RuntimeException("该库区没有库位!");
        }
        // 根据库区查询库存
        LambdaQueryWrapper<InventoryDetail> query = Wrappers.lambdaQuery();
        query.in(InventoryDetail::getLocationCode, locationList.stream().map(Location::getCode).collect(Collectors.toList()))
                .eq(InventoryDetail::getMaterialCode, mesTask.getMaterialCode())
                .eq(InventoryDetail::getQty, mesTask.getQty())
                .last("LIMIT 1");
        InventoryDetail inventoryDetail = inventoryDetailService.getOne(query);
        if (inventoryDetail == null){
            return AjaxResult.error("当前库区没有匹配到合适出库的物料:" + mesTask.getMaterialCode());
        }
        // 创建出库单据
        ShipmentDetail shipmentDetail = mesService.createShipmentDocuments(mesTask);
        // 进行手动出库组盘
        List<ShipmentDetail> shipmentDetailList = new ArrayList<>();
        shipmentDetailList.add(shipmentDetail);
        ShipmentCombinationModel shipmentCombinationModel = new ShipmentCombinationModel();
        shipmentCombinationModel.setShipmentDetailId(shipmentDetail.getId());
        shipmentCombinationModel.setShipQty(BigDecimal.valueOf(mesTask.getQty()));
        shipmentCombinationModel.setInventoryDetailId(inventoryDetail.getId());
        ShipmentContainerHeader shipmentContainerHeader = shipmentContainerHeaderService.combination(shipmentCombinationModel);
        if (shipmentContainerHeader == null){
            throw new RuntimeException("创建出库组盘失败!");
        }
        //表头
        List<Integer> idList = Arrays.asList(Convert.toIntArray(shipmentContainerHeader.getId().toString()));
        result = shipmentContainerHeaderService.createTask(idList);
        // 查询出库任务
        LambdaQueryWrapper<TaskHeader> taskHeaderLambdaQueryWrapper = Wrappers.lambdaQuery();
        taskHeaderLambdaQueryWrapper.eq(TaskHeader::getAllocationHeadId, shipmentContainerHeader.getId());
        TaskHeader taskHeader = taskHeaderService.getOne(taskHeaderLambdaQueryWrapper);
        if (taskHeader == null){
            throw new RuntimeException("创建出库任务失败!");
        }
        TaskHeader taskHeaderTemp = new TaskHeader();
        taskHeaderTemp.setId(taskHeader.getId());
        taskHeaderTemp.setPickingCartPos(mesTask.getStation());
        // 修改任务出库口
        taskHeaderTemp.setPort(QuantityConstant.JIJIA_PORT);
        taskHeaderService.updateById(taskHeaderTemp);
        result.setData(taskHeader);
        return result;
    }

    @Override
    public AjaxResult createAgvTask(Integer type, String fromPort, String toPort, String code) {
        AgvTaskCS agvTaskCS = new AgvTaskCS();
        agvTaskCS.setTaskType(type);
        agvTaskCS.setToPort(toPort);
        agvTaskCS.setFromPort(fromPort);
        agvTaskCS.setFromUserDef1(code);
        agvTaskCS.setStatus(QuantityConstant.AGV_TASK_STATUS_ERROR);
        agvTaskCS.setZoneCode(QuantityConstant.GT_RECEIPT_TYPE);
        if (agvTaskCSService.save(agvTaskCS)){
            AjaxResult result = AjaxResult.success();
            result.setData(agvTaskCS);
            return result;
        }
        return AjaxResult.error("AGV任务创建失败!");
    }

    @Override
    public AjaxResult addMaterial(MesTask mesTask) {
        LambdaQueryWrapper<Material> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Material::getCode, mesTask.getMaterialCode())
                .eq(Material::getWarehouseCode, ShiroUtils.warehouseCode);
        Material material = materialService.getOne(queryWrapper);
        if (material == null){
            material = new Material();
            material.setCode(mesTask.getMaterialCode());
            material.setName(mesTask.getMaterialName());
            material.setSpec(mesTask.getSpec());
            material.setUnit(mesTask.getUnit());
            material.setWarehouseCode(ShiroUtils.warehouseCode);
            material.setCompanyCode(ShiroUtils.getCompanyCode());
            if (!materialService.save(material)){
                return AjaxResult.error("新增物料失败!");
            }
        }
        return AjaxResult.success();
    }

    @Resource
    private InventoryDetailService inventoryDetailService;
    @Resource
    private RcsService rcsService;
    @Resource
    private ContainerService containerService;
    @Resource
    private ShipmentApiService shipmentApiService;

    @Override
    public AjaxResult emptyContainerHandleService(MesTask mesTask) {
        // 模拟mes登录
        userService.login(QuantityConstant.PLATFORM_MES, QuantityConstant.PLATFORM_MES_PASSWORD, QuantityConstant.WAREHOUSE_KS, false);
        if (mesTask.isType()){
            // 空托出库任务
            return mesService.createEmptyShipmentContainer(mesTask);
        }else {
            // 空托入库任务
            return mesService.createEmptyReceiptContainer(mesTask);
        }
    }

    @Override
    public AjaxResult initialLocationService(MesTask mesTask) {
        if (StringUtils.isEmpty(mesTask.getMaterialCode())){
            return AjaxResult.error("物料编码不能为空!");
        }
        if (StringUtils.isEmpty(mesTask.getLocationCode())){
            return AjaxResult.error("初始货架点位不能为空!");
        }
        if (mesTask.getQty() == null || mesTask.getQty() == 0){
            return AjaxResult.error("初始数量不能为空!");
        }
        if (StringUtils.isEmpty(mesTask.getContainerCode())){
            return AjaxResult.error("容器编码不能为空!");
        }
        // 模拟mes登录
        userService.login(QuantityConstant.PLATFORM_MES, QuantityConstant.PLATFORM_MES_PASSWORD, QuantityConstant.WAREHOUSE_KS, false);
        AjaxResult result = mesService.addMaterial(mesTask);
        if (result.hasErr()){
            return result;
        }
        // 获取入库库位
        Location location = locationService.getLocationByCode(mesTask.getLocationCode(), ShiroUtils.getWarehouseCode());
        if (location == null){
            return AjaxResult.error("根据初始库位编码"+mesTask.getLocationCode()+"查询入库库位失败!");
        }
        // 判断库存是否已经存在
        LambdaQueryWrapper<InventoryDetail> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(InventoryDetail::getLocationCode, location.getCode())
                .eq(InventoryDetail::getContainerCode, mesTask.getContainerCode());
        InventoryDetail inventoryDetail = inventoryDetailService.getOne(queryWrapper);
        if (inventoryDetail != null){
            return AjaxResult.success("点位上已有物料请勿重复绑定!");
        }
        // 获取可用托盘码
        LambdaQueryWrapper<Container> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(Container::getCode, mesTask.getContainerCode());
        Container container = containerService.getOne(lambdaQueryWrapper);
        if (container == null){
            throw new RuntimeException("查询当前容器编码:"+mesTask.getContainerCode()+"不存在!");
        }
        // 新增入库单
        ReceiptDetail receiptDetail = mesService.createReceiptDocuments(mesTask);
        rcsService.addInventory(receiptDetail, container.getCode(), location.getCode(), location.getZoneCode());
        Location locationTemp = new Location();
        locationTemp.setId(location.getId());
        locationTemp.setContainerCode(container.getCode());
        locationTemp.setStatus(QuantityConstant.STATUS_LOCATION_EMPTY);
        if (!locationService.updateById(locationTemp)){
            throw new RuntimeException("更新库位数据失败!");
        }
        Container containerTemp = new Container();
        containerTemp.setId(container.getId());
        containerTemp.setLocationCode(location.getCode());
        containerTemp.setStatus(QuantityConstant.STATUS_CONTAINER_SOME);
        if (!containerService.updateById(containerTemp)){
            throw new RuntimeException("更新容器状态失败!");
        }
        ReceiptHeader receiptHeaderTemp = new ReceiptHeader();
        receiptHeaderTemp.setId(receiptDetail.getReceiptId());
        receiptHeaderTemp.setLastStatus(QuantityConstant.RECEIPT_HEADER_RETURN);
        receiptHeaderTemp.setFirstStatus(QuantityConstant.RECEIPT_HEADER_RETURN);
        if (!receiptHeaderService.updateById(receiptHeaderTemp)){
            throw new RuntimeException("更新入库单头表失败!");
        }
        return AjaxResult.success("库位初始化成功!");
    }

    @Override
    public ReceiptDetail createReceiptDocuments(MesTask mesTask) {
        // 创建入库单
        ReceiptDomain receiptDomain = new ReceiptDomain();
        ReceiptHeader receiptHeader = new ReceiptHeader();
        receiptHeader.setReceiptType(QuantityConstant.GT_RECEIPT_TYPE);
        receiptHeader.setWarehouseCode(ShiroUtils.warehouseCode);
        receiptHeader.setCompanyCode(ShiroUtils.getCompanyCode());
        receiptHeader.setCreatedBy(ShiroUtils.getUser().getLoginName());
        List<ReceiptDetail> receiptDetails = new ArrayList<>();
        ReceiptDetail receiptDetail = new ReceiptDetail();
        receiptDetail.setMaterialCode(mesTask.getMaterialCode());
        receiptDetail.setMaterialName(mesTask.getMaterialName());
        receiptDetail.setMaterialSpec(mesTask.getSpec());
        receiptDetail.setMaterialUnit(mesTask.getUnit());
        receiptDetail.setQty(BigDecimal.valueOf(mesTask.getQty()));
        receiptDetail.setWarehouseCode(ShiroUtils.getWarehouseCode());
        receiptDetail.setUWarehouseCode(QuantityConstant.U_WAREHOUSE_CODE_GT);
        receiptDetails.add(receiptDetail);
        receiptDomain.setReceiptHeader(receiptHeader);
        receiptDomain.setReceiptDetails(receiptDetails);
        AjaxResult result = receiptApiService.receipt(receiptDomain);
        if (result.hasErr()){
            throw new RuntimeException(result.getMsg());
        }
        return receiptDetail;
    }

    @Override
    public ShipmentDetail createShipmentDocuments(MesTask mesTask) {
        // 创建出库单
        ShipmentDomain shipmentDomain = new ShipmentDomain();
        ShipmentHeader shipmentHeader = new ShipmentHeader();
        List<ShipmentDetail> shipmentDetailList = new ArrayList<>();
        shipmentHeader.setShipmentType(QuantityConstant.GT_RECEIPT_TYPE);
        shipmentHeader.setWarehouseCode(ShiroUtils.warehouseCode);
        shipmentHeader.setCompanyCode(ShiroUtils.getCompanyCode());
        shipmentHeader.setCreatedBy(ShiroUtils.getUser().getLoginName());
        // 创建出库单详情
        ShipmentDetail shipmentDetail = new ShipmentDetail();
        shipmentDetail.setMaterialCode(mesTask.getMaterialCode());
        shipmentDetail.setMaterialName(mesTask.getMaterialName());
        shipmentDetail.setMaterialSpec(mesTask.getSpec());
        shipmentDetail.setMaterialUnit(mesTask.getUnit());
        shipmentDetail.setQty(BigDecimal.valueOf(mesTask.getQty()));
        shipmentDetail.setWarehouseCode(ShiroUtils.getWarehouseCode());
        shipmentDetail.setUWarehouseCode(QuantityConstant.U_WAREHOUSE_CODE_GT);
        shipmentDetail.setCompanyCode(ShiroUtils.getCompanyCode());
        shipmentDetail.setInventorySts(QuantityConstant.GOOD);
        shipmentDetailList.add(shipmentDetail);
        shipmentDomain.setShipmentHeader(shipmentHeader);
        shipmentDomain.setShipmentDetails(shipmentDetailList);
        AjaxResult result = shipmentApiService.shipment(shipmentDomain);
        if (result.hasErr()){
            throw new RuntimeException(result.getMsg());
        }
        return shipmentDetail;
    }

    @Resource
    private TaskHeaderMapper taskHeaderMapper;

    @Override
    @Transactional
    public AjaxResult createEmptyReceiptContainer(MesTask mesTask) {
        // 判断当前位置是否有任务
        AjaxResult result = mesService.checkStation(mesTask.getStation(), QuantityConstant.TASK_TYPE_EMPTYRECEIPT);
        if (!result.hasErr()){
            return result;
        }
        Container container = null;
        String locationCode = null;
        TaskHeader task = new TaskHeader();
        task.setWarehouseCode(ShiroUtils.getWarehouseCode());
        task.setCompanyCode(ShiroUtils.getCompanyCode());
        task.setPriority(0);
        task.setTaskType(QuantityConstant.TASK_TYPE_EMPTYRECEIPT);
        task.setStatus(QuantityConstant.TASK_STATUS_BUILD);
        task.setZoneCode(mesTask.getArea());
        task.setCreated(new Date());
        task.setCreatedBy(ShiroUtils.getUserName());
        task.setCreated(new Date());
        task.setPickingCartPos(mesTask.getStation());
        // 空托入库任务
        if (StringUtils.isEmpty(mesTask.getOrderCode())){
            // 光腾车间系统直接分配库位
            LambdaQueryWrapper<Location> query = Wrappers.lambdaQuery();
            query.eq(Location::getZoneCode, mesTask.getArea())
                    .eq(Location::getContainerCode, "")
                    .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY)
                    .last("limit 1");
            Location location = locationService.getOne(query);
            if (location == null){
                throw new RuntimeException("当前库区没有可用库位!");
            }
            task.setToLocation(location.getCode());
            location.setStatus(QuantityConstant.STATUS_LOCATION_LOCK);
            locationService.updateById(location);
            locationCode = location.getCode();
        }
        LambdaQueryWrapper<Container> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(Container::getCode, mesTask.getContainerCode());
        container = containerService.getOne(lambdaQueryWrapper);
        if (container == null){
            throw new RuntimeException("该托盘码"+mesTask.getContainerCode()+"不存在!");
        }
        task.setContainerCode(container.getCode());
        if (StringUtils.isNotEmpty(container.getLocationCode())) {
            throw new RuntimeException("容器已在库位[" + container.getLocationCode() + "]上");
        }
        //判断托盘是否已经存在任务
        Integer taskCount = taskHeaderMapper.UncompleteCount(container.getCode(), ShiroUtils.getWarehouseCode());
        if (taskCount != null && taskCount.intValue() > 0) {
            throw new RuntimeException("容器已存在任务");
        }
        task.setContainerCode(container.getCode());
        container.setLocationCode(locationCode);
        if (taskHeaderService.save(task)){
            AjaxResult ajaxResult = AjaxResult.success("任务下发成功!");
            ajaxResult.setData(task);
            container.setStatus(QuantityConstant.STATUS_CONTAINER_LOCK);
            containerService.updateById(container);
            return ajaxResult;
        }
        return AjaxResult.error("任务下发失败!");
    }

    @Resource
    private WorkTaskService  workTaskService;

    @Override
    @Transactional
    public AjaxResult createEmptyShipmentContainer(MesTask mesTask) {
        AjaxResult result = mesService.checkStation(mesTask.getStation(), QuantityConstant.TASK_TYPE_EMPTYSHIPMENT);
        if (!result.hasErr()){
            return result;
        }
        // 根据库区查询库区查询可以出库的空托盘
        List<Location> locationList = containerService.getEmptyContainerInLocation(mesTask.getArea(), null, null, null,ShiroUtils.getWarehouseCode());
        if (locationList == null || locationList.size() == 0){
            return AjaxResult.error("库内没有可用空托盘!");
        }
        Location location = locationList.get(0);
        // 创建空托盘出库任务
        result = workTaskService.createEmptyOut(location.getContainerCode(), location.getCode(), QuantityConstant.JIJIA_PORT);
        if (result.hasErr()){
            return result;
        }
        // 查询空托出库任务
        LambdaQueryWrapper<TaskHeader> query = Wrappers.lambdaQuery();
        query.eq(TaskHeader::getFromLocation, location.getCode())
                .eq(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_BUILD)
                .eq(TaskHeader::getContainerCode, location.getContainerCode());
        TaskHeader taskHeader = taskHeaderService.getOne(query);
        if (taskHeader == null){
            throw new RuntimeException("创建空托出库任务失败!");
        }
        TaskHeader taskHeaderTemp = new TaskHeader();
        taskHeaderTemp.setId(taskHeader.getId());
        taskHeaderTemp.setPickingCartPos(mesTask.getStation());
        taskHeaderService.updateById(taskHeaderTemp);
        result.setData(taskHeader);
        return result;
    }

    @Override
    public AjaxResult checkStation(String station, Integer type) {
        if (StringUtils.isEmpty(station)){
            throw new RuntimeException("位置号不能为空!");
        }
        LambdaQueryWrapper<TaskHeader> taskHeaderLambdaQueryWrapper = Wrappers.lambdaQuery();
        taskHeaderLambdaQueryWrapper.eq(TaskHeader::getPickingCartPos, station)
                .eq(TaskHeader::getTaskType, type)
                .lt(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_COMPLETED);
        TaskHeader taskHeader = taskHeaderService.getOne(taskHeaderLambdaQueryWrapper);
        if (taskHeader != null){
            AjaxResult result = AjaxResult.success("该点位已创建任务请勿重复创建!");
            result.setData(taskHeader);
            return result;
        }
        return AjaxResult.error("任务不存在!");
    }

    @Resource
    private InventoryHeaderService inventoryHeaderService;

    @Override
    @Transactional
    public AjaxResult untieLocationService(MesTask mesTask) {
        if (StringUtils.isEmpty(mesTask.getLocationCode())){
            return AjaxResult.error("初始货架点位不能为空!");
        }
        if (StringUtils.isEmpty(mesTask.getContainerCode())){
            return AjaxResult.error("容器编码不能为空!");
        }
        // 根据库位编码和容器编码查询库存
        LambdaQueryWrapper<InventoryHeader> query = Wrappers.lambdaQuery();
        query.eq(InventoryHeader::getContainerCode, mesTask.getContainerCode())
                .eq(InventoryHeader::getLocationCode, mesTask.getLocationCode());
        InventoryHeader inventoryHeader = inventoryHeaderService.getOne(query);
        if (inventoryHeader == null){
            return AjaxResult.error("当前点位未绑定物料,无需进行解绑!");
        }
        // 判断当前库位是否有任务
        LambdaQueryWrapper<TaskHeader> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.lt(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_COMPLETED)
                .eq(TaskHeader::getContainerCode, mesTask.getContainerCode())
                .eq(TaskHeader::getFromLocation, mesTask.getLocationCode());
        TaskHeader taskHeader = taskHeaderService.getOne(queryWrapper);
        if (taskHeader != null){
            return AjaxResult.error("当前料架以存在任务号:" + taskHeader.getId()+ ",无法进行解绑!");
        }
        LambdaQueryWrapper<InventoryDetail> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(InventoryDetail::getInventoryHeaderId, inventoryHeader.getId());
        InventoryDetail inventoryDetail = inventoryDetailService.getOne(lambdaQueryWrapper);
        if (inventoryDetail == null){
            return AjaxResult.error("查询库存详情失败!");
        }
        inventoryDetailService.removeById(inventoryDetail.getId());
        inventoryHeaderService.removeById(inventoryHeader.getId());
        return AjaxResult.success("料架解绑成功!");
    }

    @Override
    public TableDataInfo getInventoryListService(InventoryDetailQuery query) {
        List<String> zoneCodes = mesService.getZoneCodes(query.getArea());
        LambdaQueryWrapper<InventoryDetail> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.ge(StringUtils.isNotEmpty(query.getCreatedBegin()), InventoryDetail::getCreated, query.getCreatedBegin())
                .le(StringUtils.isNotEmpty(query.getCreatedEnd()), InventoryDetail::getCreated, query.getCreatedEnd()) // 创建时间范围
                .eq(StringUtils.isNotEmpty(query.getInventoryDetail().getZoneCode()), InventoryDetail::getZoneCode, query.getInventoryDetail().getZoneCode())
                .in((zoneCodes != null && zoneCodes.size() > 0), InventoryDetail::getZoneCode, zoneCodes) // 库区
                .eq(StringUtils.isNotEmpty(query.getInventoryDetail().getLocationCode()), InventoryDetail::getLocationCode, query.getInventoryDetail().getLocationCode()) // 库位
                .eq(StringUtils.isNotEmpty(query.getInventoryDetail().getContainerCode()), InventoryDetail::getContainerCode,
                        query.getInventoryDetail().getContainerCode())// 容器
                .eq(StringUtils.isNotEmpty(query.getInventoryDetail().getMaterialCode()), InventoryDetail::getMaterialCode, query.getInventoryDetail().getMaterialCode())// 物料编码
                .like(StringUtils.isNotEmpty(query.getInventoryDetail().getMaterialName()), InventoryDetail::getMaterialName,
                        query.getInventoryDetail().getMaterialName())// 物料名称
                .like(StringUtils.isNotEmpty(query.getInventoryDetail().getMaterialSpec()), InventoryDetail::getMaterialSpec,
                        query.getInventoryDetail().getMaterialSpec())// 物料规格
                .eq(query.getInventoryDetail().getQty() != null, InventoryDetail::getQty, query.getInventoryDetail().getQty()) // 数量
                .eq(InventoryDetail::getTaskQty, BigDecimal.ZERO) // 只查询预计出库数量为0的库存
        ;
        if (StringUtils.isNotNull(query.getPageNum()) && StringUtils.isNotNull(query.getPageSize())) {
            // 分页查询
            Page<InventoryDetail> page = new Page<>(query.getPageNum(), query.getPageSize());
            IPage<InventoryDetail> iPage = inventoryDetailService.page(page, lambdaQueryWrapper);
            return getMpDataTable(iPage.getRecords(), iPage.getTotal());
        } else {
            List<InventoryDetail> list = inventoryDetailService.list(lambdaQueryWrapper);
            return getDataTable(list);
        }
    }

    @Override
    public TableDataInfo getTaskListService(TaskHeaderQuery query) {
        List<String> zoneCodes = mesService.getZoneCodes(query.getArea());
        LambdaQueryWrapper<TaskHeader> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.ge(StringUtils.isNotEmpty(query.getCreatedBegin()), TaskHeader::getCreated, query.getCreatedBegin())
                .le(StringUtils.isNotEmpty(query.getCreatedEnd()), TaskHeader::getCreated, query.getCreatedEnd()) // 创建时间范围
                .in((zoneCodes != null && zoneCodes.size() > 0), TaskHeader::getZoneCode, zoneCodes) // 库区
                .eq(StringUtils.isNotEmpty(query.getTaskHeader().getContainerCode()), TaskHeader::getContainerCode,
                        query.getTaskHeader().getContainerCode())// 容器
                .lt(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_COMPLETED) // 只查询未完成的状态
        ;
        if (StringUtils.isNotNull(query.getPageNum()) && StringUtils.isNotNull(query.getPageSize())) {
            // 分页查询
            Page<TaskHeader> page = new Page<>(query.getPageNum(), query.getPageSize());
            IPage<TaskHeader> iPage = taskHeaderService.page(page, lambdaQueryWrapper);
            return getMpDataTable(iPage.getRecords(), iPage.getTotal());
        } else {
            List<TaskHeader> list = taskHeaderService.list(lambdaQueryWrapper);
            return getDataTable(list);
        }
    }

    @Override
    public List<String> getZoneCodes(String area) {
        List<String> zoneCodes = null;
        List<LocationType> locationTypes = null;
        LambdaQueryWrapper<LocationType> queryWrapper = Wrappers.lambdaQuery();
        if (QuantityConstant.GT_RECEIPT_TYPE.equals(area)){
            queryWrapper.like(LocationType::getCode, "QY%");
            locationTypes = locationTypeService.list(queryWrapper);
        }
        if (QuantityConstant.JJ_RECEIPT_TYPE.equals(area)){
            queryWrapper.like(LocationType::getCode, QuantityConstant.JJ_RECEIPT_TYPE);
            locationTypes = locationTypeService.list(queryWrapper);
        }
        if (locationTypes != null && locationTypes.size() > 0){
            zoneCodes = locationTypes.stream().map(LocationType::getCode).collect(Collectors.toList());
        }
        return zoneCodes;
    }

    @Override
    @Transactional
    public AjaxResult zoneSyncService(List<Zone> zones) {
        if (zones == null || zones.size() == 0){
            return AjaxResult.error("请勿提交空数据!");
        }
        LambdaQueryWrapper<LocationType> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(LocationType::getCode, zones.stream().map(Zone::getCode).collect(Collectors.toList()))
                .eq(LocationType::getWarehouseCode, QuantityConstant.WAREHOUSE_KS);
        List<LocationType> locationTypes = locationTypeService.list(queryWrapper);
        Map<String, LocationType> map = new HashMap<>();
        for (LocationType locationType :locationTypes){
            if (!map.containsKey(locationType.getCode())){
                map.put(locationType.getCode(), locationType);
            }
        }
        List<LocationType> insertZone = new ArrayList<>();
        List<LocationType> updateZone = new ArrayList<>();
        for (Zone zone :zones){
            if (map.containsKey(zone.getCode())){
                // 已存在代表更新
                LocationType temp = new LocationType();
                temp.setId(map.get(zone.getCode()).getId());
                temp.setName(zone.getName());
                updateZone.add(temp);
            }else {
                // 不存在代表新增
                LocationType temp = new LocationType();
                temp.setWarehouseCode(QuantityConstant.WAREHOUSE_KS);
                temp.setCreatedBy(QuantityConstant.PLATFORM_MES);
                temp.setCreated(new Date());
                temp.setCode(zone.getCode());
                temp.setName(zone.getName());
                insertZone.add(temp);
            }
        }
        if (insertZone.size() > 0){
            locationTypeService.saveBatch(insertZone);
        }
        if (updateZone.size() > 0){
            locationTypeService.updateBatchById(updateZone);
        }
        return AjaxResult.success("区域数据同步成功!");
    }

    @Override
    public AjaxResult pointToPointService(MesTask mesTask) {
        if (mesTask == null){
            return AjaxResult.error("参数不能为空!");
        }
        // 起点
        if (StringUtils.isEmpty(mesTask.getStartingPoint())){
            return AjaxResult.error("起点参数不能为空!");
        }
        if (StringUtils.isEmpty(mesTask.getEndPoint())){
            return AjaxResult.error("终点不能为空!");
        }
        // 容器编码
        if (StringUtils.isEmpty(mesTask.getContainerCode())){
            return AjaxResult.error("容器编码不能为空!");
        }
        AjaxResult result = mesService.checkStation(mesTask.getStartingPoint(), QuantityConstant.TASK_TYPE_OVER_STATION);
        if (!result.hasErr()){
            return result;
        }
        TaskHeader taskHeader = new TaskHeader();
        taskHeader.setPickingCartPos(mesTask.getStartingPoint());
        taskHeader.setPort(mesTask.getEndPoint());
        taskHeader.setContainerCode(mesTask.getContainerCode());
        taskHeader.setWarehouseCode(QuantityConstant.WAREHOUSE_KS);
        taskHeader.setTaskType(QuantityConstant.TASK_TYPE_OVER_STATION);
        taskHeader.setStatus(QuantityConstant.TASK_STATUS_BUILD);
        if (!taskHeaderService.save(taskHeader)){
            return AjaxResult.error("新增任务失败!");
        }
        result = AjaxResult.success("任务新增成功");
        result.setData(taskHeader);
        return result;
    }

}