package com.sw.mes.itemclean.clean.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sw.mes.core.enums.EnumValuesFactory;
import com.sw.mes.core.enums.ItemCleanEnums;
import com.sw.mes.core.exception.BusinessException;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.StringUtils;
import com.sw.mes.itemclean.clean.domain.*;
import com.sw.mes.itemclean.clean.dto.BoxInfoDto;
import com.sw.mes.itemclean.clean.dto.BoxPropertyDto;
import com.sw.mes.itemclean.clean.dto.GeneralScanBoxNoParam;
import com.sw.mes.itemclean.clean.dto.MaterialGroupDetailDto;
import com.sw.mes.itemclean.clean.mapper.MaterialApplyOrderMapper;
import com.sw.mes.itemclean.clean.mapper.MaterialCleaningMapper;
import com.sw.mes.itemclean.clean.mapper.MaterialUnpackingMapper;
import com.sw.mes.itemclean.clean.mapping.ScanBoxNoMapping;
import com.sw.mes.itemclean.clean.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.checkerframework.checker.units.qual.A;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 领料单 服务实现类
 * </p>
 *
 * @author liuzemin
 * @since 2022-11-10
 */
@Service
public class MaterialApplyOrderServiceImpl extends ServiceImpl<MaterialApplyOrderMapper, MaterialApplyOrder> implements MaterialApplyOrderService, ScanBoxNoService {


    @Autowired
    private MaterialStoreSignBoxService materialStoreSignBoxService;

    @Autowired
    CleaningProcessFlowService cleaningProcessFlowService;

    @Autowired
    MaterialUnpackingService materialUnpackingService;

    @Autowired
    MaterialCleaningService materialCleaningService;

    @Autowired
    ModelMapper modelMapper;

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public BoxPropertyDto scanBoxNo(GeneralScanBoxNoParam param) {
        LambdaQueryWrapper<MaterialStoreSignBox> queryWrapper = new LambdaQueryWrapper<>();
        MaterialStoreSignBox box;
        switch (param.getScanName()){
            case "原生多晶领料":
                queryWrapper.eq(MaterialStoreSignBox::getMaterialBoxNo, param.getBoxNo());
                //queryWrapper.eq(MaterialStoreSignBox::getPickingStatus, 1);
                queryWrapper.last("limit 1");
                box = materialStoreSignBoxService.getOne(queryWrapper);
                if (box == null) {
                    throw new RuntimeException(param.getBoxNo() + "该箱号不存在！");
                }
                if (box.getIsEmptyBox() == 1) {
                    throw new RuntimeException(param.getBoxNo() + "该箱号为空箱！");
                }
                if (box.getMaterialType() == ItemCleanEnums.MaterialType.原生多晶.getKey()
                ){
                    return ScanBoxNoMapping.toDto(box);
                }else {
                    throw new RuntimeException(param.getScanName()+":当前箱号"+param.getBoxNo()+"属于"+ItemCleanEnums.MaterialType.getText(box.getMaterialType()));
                }
            case "回收料领料":
                queryWrapper.eq(MaterialStoreSignBox::getMaterialBoxNo, param.getBoxNo());
                queryWrapper.last("limit 1");
                box = materialStoreSignBoxService.getOne(queryWrapper);
                if (box == null) {
                    throw new RuntimeException(param.getBoxNo() + "该箱号不存在！");
                }
                if (box.getIsEmptyBox() == 1) {
                    throw new RuntimeException(param.getBoxNo() + "该箱号为空箱！");
                }
                if (box.getMaterialType() == ItemCleanEnums.MaterialType.回收料.getKey()
                ){
                    return ScanBoxNoMapping.toDto(box);
                }else {
                    throw new RuntimeException(param.getScanName()+":当前箱号"+param.getBoxNo()+"属于"+ItemCleanEnums.MaterialType.getText(box.getMaterialType()));
                }
            case "落地料领料":
                queryWrapper.eq(MaterialStoreSignBox::getMaterialBoxNo, param.getBoxNo());
                queryWrapper.last("limit 1");
                box = materialStoreSignBoxService.getOne(queryWrapper);
                if (box == null) {
                    throw new RuntimeException(param.getBoxNo() + "该箱号不存在！");
                }
                if (box.getIsEmptyBox() == 1) {
                    throw new RuntimeException(param.getBoxNo() + "该箱号为空箱！");
                }
                if (box.getMaterialType() == ItemCleanEnums.MaterialType.落地料.getKey()
                ){
                    return ScanBoxNoMapping.toDto(box);
                }else {
                    throw new RuntimeException(param.getScanName()+":当前箱号"+param.getBoxNo()+"属于"+ItemCleanEnums.MaterialType.getText(box.getMaterialType()));
                }
            case "返工领料":
                queryWrapper.eq(MaterialStoreSignBox::getMaterialBoxNo, param.getBoxNo());
                queryWrapper.last("limit 1");
                box = materialStoreSignBoxService.getOne(queryWrapper);
                if (box == null) {
                    throw new RuntimeException(param.getBoxNo() + "该箱号不存在！");
                }
                if (box.getIsEmptyBox() == 1) {
                    throw new RuntimeException(param.getBoxNo() + "该箱号为空箱！");
                }
                if (box.getMaterialType() == ItemCleanEnums.MaterialType.返工料.getKey()
                ){
                    return ScanBoxNoMapping.toDto(box);
                }else {
                    throw new RuntimeException(param.getScanName()+":当前箱号"+param.getBoxNo()+"属于"+ItemCleanEnums.MaterialType.getText(box.getMaterialType()));
                }
        }
            return null;
    }



    @Override
    public boolean insertOrUpdateMaterialApplyOrders(List<MaterialApplyOrder> materialApplyOrders) {
        return this.saveOrUpdateBatch(materialApplyOrders);
    }

    @Override
    public MaterialApplyOrder selectMaterialOrder(MaterialUnpackingDetail mterialUnpackingDetail) {
        MaterialApplyOrder materialApplyOrder=null;
        LambdaQueryWrapper<MaterialApplyOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialApplyOrder::getMaterialBoxNo,mterialUnpackingDetail.getUnpackingBoxNo());
        queryWrapper.eq(MaterialApplyOrder::getOrderType,mterialUnpackingDetail.getMaterialType());
        List<MaterialApplyOrder> materialApplyOrders = this.list(queryWrapper);
        if(materialApplyOrders!=null&&materialApplyOrders.size()>=1){
            materialApplyOrder=materialApplyOrders.get(0);
        }
        return materialApplyOrder;
    }

    @Override
    @Transactional
    public Result updateBoxByMaterialApplyOrder(MaterialApplyOrder materialApplyOrder) {
        if (materialApplyOrder.getMaterialBoxNo() == null)
            return ResultGenerator.fail("箱号不能为空");
        MaterialStoreSignBox entity = materialStoreSignBoxService.getByBoxNo(materialApplyOrder.getMaterialBoxNo());
        if (entity == null)
            return ResultGenerator.fail("原信息不存在");
        try {
            entity.setPickingStatus(1);
            materialStoreSignBoxService.saveOrUpdate(entity);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @Override
    public MaterialApplyOrder getByMaterialBoxNo(String materialBoxNo) {
        LambdaQueryWrapper<MaterialApplyOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialApplyOrder::getMaterialBoxNo, materialBoxNo);
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    @Override
    public MaterialApplyOrder getByBoxNo(String boxNo) {
        LambdaQueryWrapper<MaterialApplyOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialApplyOrder::getBoxNo, boxNo);
        queryWrapper.orderByDesc(MaterialApplyOrder::getCreateTime);
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }


    @Override
    public List<MaterialApplyOrder> pullMaterialData() {
        LambdaQueryWrapper<MaterialApplyOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialApplyOrder::getPulled,0);
        queryWrapper.isNotNull(MaterialApplyOrder::getClanProductBatchNo);
        queryWrapper.isNotNull(MaterialApplyOrder::getAufnr);
        return this.list(queryWrapper);
    }

    @Override
    public List<MaterialApplyOrder> getMaterialApplyOrder(String materialName, String materialCode, Date startTime, Date endTime) {
        LambdaQueryWrapper<MaterialApplyOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialApplyOrder::getMaterialName, materialName);
        queryWrapper.eq(MaterialApplyOrder::getMaterialCode, materialCode);
        queryWrapper.between(MaterialApplyOrder::getCreateTime, startTime, endTime);
        return this.list(queryWrapper);
    }

    @Override
    public void updatePulled(List<MaterialApplyOrder> list) {
        list.stream().forEach(temp->temp.setPulled(1));
        this.saveOrUpdateBatch(list);
    }

    @Override
    public BoxInfoDto getByBoxNoAndLastSit(String boxNo,String sourceProcess) {
        BoxInfoDto boxInfoDto = new BoxInfoDto();

        //1 判断箱子属于哪个工序
       // CleaningProcessFlow processFlow = cleaningProcessFlowService.getByBoxNo(boxNo);

        LambdaQueryWrapper<CleaningProcessFlow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CleaningProcessFlow::getBoxNo, boxNo);
        queryWrapper.in(CleaningProcessFlow::getStatus, 0,1);
        queryWrapper.orderByDesc(CleaningProcessFlow::getCreateTime);
        queryWrapper.last("limit 1");
        CleaningProcessFlow processFlow =   cleaningProcessFlowService.getOne(queryWrapper);
        if (null == processFlow) {
            throw new BusinessException("箱号:" + boxNo + "无过站履历信息!");
        }
        //2 去对应工序数据中查找箱号对应的信息
        EnumValuesFactory.CleaningWipStorageCode modelTypeEnum = EnumValuesFactory.CleaningWipStorageCode.valueOf(processFlow.getLastSite());
        if (modelTypeEnum == null) {
            throw new RuntimeException("站点类型不存在");
        }
        String currentSiteName = processFlow.getCurrentSiteName();
        if (StringUtils.isEmpty(currentSiteName)) {
            throw new RuntimeException("当前站点不存在");
        }

        switch (modelTypeEnum) {
            case 领料:
                MaterialApplyOrder materialApplyOrder = getByBoxNo(boxNo);
                //工序异常
                if (!currentSiteName.equals(sourceProcess)) {
                    throw new BusinessException("箱号:" + boxNo + "扫录作业方式应该为" + currentSiteName);
                }
                boxInfoDto =  fromDto(materialApplyOrder);
                boxInfoDto.setCurrentProductBatchNo(materialApplyOrder.getClanProductBatchNo());
                break;
            case 分选:
                //上个工序为分选的时候,必须是清洗工序扫录
                if (!currentSiteName.equals(sourceProcess)) {
                    throw new BusinessException("箱号:" + boxNo + "扫录作业方式应该为" + currentSiteName);
                }
                MaterialUnpacking materialUnpacking = materialUnpackingService.getByBoxNo(boxNo);
                boxInfoDto = fromDto(materialUnpacking);
                boxInfoDto.setCurrentProductBatchNo(materialUnpacking.getFxProductBatchNo());
                break;
            case 清洗:
                //上个工序为清洗的时候,必须是破碎工序扫录
                if (!currentSiteName.equals(sourceProcess)) {
                    throw new BusinessException("箱号:" + boxNo + "扫录作业方式应该为" + currentSiteName);
                }
                MaterialCleaning materialCleaning = materialCleaningService.getByBoxNo(boxNo);
                boxInfoDto = fromDto(materialCleaning);
                boxInfoDto.setCurrentProductBatchNo(materialCleaning.getCleanProductBatchNo());
                boxInfoDto.setStatus(materialCleaning.getStatus());
                boxInfoDto.setUsedWeight(BigDecimal.ZERO);
                boxInfoDto.setUnusedWeight(materialCleaning.getWeight());
                boxInfoDto.setTotalWeight(materialCleaning.getWeight() == null ? BigDecimal.ZERO : materialCleaning.getWeight().add(new BigDecimal(StringUtils.isEmpty(materialCleaning.getBoxWeight()) ? "0" : materialCleaning.getBoxWeight())));
                break;
            case 破碎:
                materialCleaning = materialCleaningService.getByBoxNo(boxNo);
                boxInfoDto.setCurrentProductBatchNo(materialCleaning.getCleanProductBatchNo());
                boxInfoDto.setStatus(materialCleaning.getStatus());
                boxInfoDto.setUsedWeight(BigDecimal.ZERO);
                boxInfoDto.setUnusedWeight(materialCleaning.getWeight());
                boxInfoDto.setTotalWeight(materialCleaning.getWeight() == null ? BigDecimal.ZERO : materialCleaning.getWeight().add(new BigDecimal(StringUtils.isEmpty(materialCleaning.getBoxWeight()) ? "0" : materialCleaning.getBoxWeight())));
                boxInfoDto = fromDto(materialCleaning);
                break;
            default:
                throw new RuntimeException("物料来源工序异常");
        }
        boxInfoDto.setSourceProcess(modelTypeEnum.getValue());

        return boxInfoDto;
    }

    @Override
    public MaterialApplyOrder getByProductBatchNo(String productBatchNo) {
        LambdaQueryWrapper<MaterialApplyOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MaterialApplyOrder::getProductBatchNo, productBatchNo);
        queryWrapper.eq(MaterialApplyOrder::getDelFlag, 0);
        queryWrapper.last("limit 1");
        return getOne(queryWrapper);
    }

    public BoxInfoDto fromDto(MaterialApplyOrder dto) {
        return modelMapper.map(dto, BoxInfoDto.class);
    }

    public BoxInfoDto fromDto(MaterialUnpacking dto) {
        return modelMapper.map(dto, BoxInfoDto.class);
    }

    public BoxInfoDto fromDto(MaterialCleaning dto) {
        return modelMapper.map(dto, BoxInfoDto.class);
    }
}
