package com.sw.mes.fls.service.impl;


import com.alibaba.nacos.common.utils.CollectionUtils;
import com.sw.mes.base.system.entity.DictionaryItem;
import com.sw.mes.base.system.service.DictionaryItemService;
import com.sw.mes.base.workinprocess.dto.CurrentWipStorageStatusDto;
import com.sw.mes.base.workinprocess.entity.PlanProcessingOrder;
import com.sw.mes.base.workinprocess.service.PlanProcessingOrderService;
import com.sw.mes.base.workinprocess.service.WipStorageService;
import com.sw.mes.core.api.system.YbFeignClients;
import com.sw.mes.core.base.BaseServiceImpl;
import com.sw.mes.core.constant.Constants;
import com.sw.mes.core.dto.CrystalTrayUnBindInfoDto;
import com.sw.mes.core.dto.GetFbInfoDto;
import com.sw.mes.core.dto.mes.pc.yb.ProductionBindingTrayDto;
import com.sw.mes.core.entity.FbCheckOutData;
import com.sw.mes.core.enums.EnumValuesFactory;
import com.sw.mes.core.exception.BusinessException;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultCode;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.StringUtils;
import com.sw.mes.fb.aio.entity.GrindingBlanking;
import com.sw.mes.fb.aio.service.GrindingBlankingService;
import com.sw.mes.fb.checkout.dao.RecutDetailDao;
import com.sw.mes.fb.checkout.dto.Flag4MDto;
import com.sw.mes.fb.checkout.entity.FbJoin;
import com.sw.mes.fb.checkout.entity.RecutDetail;
import com.sw.mes.fb.checkout.service.FbCheckOutDataService;
import com.sw.mes.fb.checkout.service.FbCheckOutRecordService;
import com.sw.mes.fb.checkout.service.FbJoinService;
import com.sw.mes.fls.dao.ProductionBindingTrayDao;
import com.sw.mes.fls.dto.TrayUnBindingDto;
import com.sw.mes.fls.entity.ProductionBindingTray;
import com.sw.mes.fls.entity.ProductionBindingTrayLog;
import com.sw.mes.fls.service.ProductionBindingTrayLogService;
import com.sw.mes.fls.service.ProductionBindingTrayService;
import com.sw.mes.mcs.dto.SquareBindingDto;
import com.sw.mes.mcs.service.MesToMcsService;
import com.sw.mes.mcs.utils.ResultDto;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

;
;


/**
 * @Author
 * @Description：
 * @Date: Create in
 * @Modified By:
 */
@Service
@Transactional
public class ProductionBindingTrayServiceImpl extends BaseServiceImpl<ProductionBindingTray> implements ProductionBindingTrayService {
    @Value("${spring.profiles.active}")
    private String active;
    ProductionBindingTrayDao dao;

    @Autowired
    public void setDao(ProductionBindingTrayDao dao) {
        super.setBaseDao(dao);
        this.dao = dao;
    }

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    YbFeignClients ybFeignClients;

    @Autowired
    private ProductionBindingTrayLogService productionBindingTrayLogService;

//    @Autowired
//    private LongCrystalService longCrystalService;

    @Autowired
    private WipStorageService wipStorageService;

    @Autowired
    private DictionaryItemService dictionaryItemService;

    @Autowired
    private FbCheckOutDataService fbCheckOutDataService;

    @Autowired
    private FbJoinService fbJoinService;

    @Autowired
    private PlanProcessingOrderService planProcessingOrderService;

    @Autowired
    private FbCheckOutRecordService fbCheckOutRecordService;

    @Autowired
    private GrindingBlankingService grindingBlankingService;
    /**
     * 圆棒检验数据库
     */
    @Autowired
    private YbFeignClients ybFeignService;

    @Autowired
    private RecutDetailDao recutDetailDao;

    @Autowired
    private MesToMcsService mesToMcsService;
    @Override
    public List<String> findCrystalNoByTrayNo(String trayNo) {
        List<String> crystalNoByTrayNo = this.dao.findCrystalNoByTrayNo(trayNo);
        return crystalNoByTrayNo;
    }

    @Override
    public ProductionBindingTray getByTrayNoAndLocationNo(String pailNum, String locationNo) {
        return dao.getByTrayNoAndLocationNo(pailNum, locationNo);
    }


    @Override
    public Result bindingCrystalFb(ProductionBindingTrayDto dto) {
        String oldPoint = dto.getPoint();
        //如果载具工位为空，或者载具为托盘，则默认载具工位1
        if (StringUtils.isBlank(dto.getTrayNo())){
            return ResultGenerator.fail("载具编号不能为空，请检查...");
        }

        if (dto.getTrayNo().toUpperCase().startsWith("T") || StringUtils.isBlank(dto.getLocationNo())) {
            dto.setLocationNo("1");
        }

        ProductionBindingTray productionBindingTray;
        //单晶集合
        List<String> listSectionNo = new ArrayList<>();
        FbCheckOutData fbCheckOutData = fbCheckOutDataService.findDataByFbSectionNo(dto.getCrystalNo());
        if (fbCheckOutData != null) {
            if (fbCheckOutData.getSticksCount() != null && fbCheckOutData.getSticksCount() > 1) {
                listSectionNo = Arrays.asList(fbCheckOutData.getSectionCompose().split(","));
                //获取拼棒信息
                FbJoin fbJoin = fbJoinService.getFbJoinBySectionNo(dto.getCrystalNo());
                if (fbJoin != null && fbJoin.getSectionNoFb() != dto.getCrystalNo()){
                    dto.setCrystalNo(fbJoin.getSectionNoFb());
                    fbCheckOutData = fbCheckOutDataService.findDataByFbSectionNo(fbJoin.getSectionNoFb());
                }
            } else {
                listSectionNo.add(fbCheckOutData.getFbSectionNo());
            }
        }
        else{
            listSectionNo.add(dto.getCrystalNo());
        }

        for (String sectionNo : listSectionNo) {
            //查询工单是否为组托状态，组托状态下不允许绑定托盘
            PlanProcessingOrder planProcessingOrder = planProcessingOrderService.findByCode(sectionNo);
            if (planProcessingOrder == null) {
                return ResultGenerator.fail("【" + sectionNo + "】编号不存在，请检查...");
            }

            if (planProcessingOrder != null && planProcessingOrder.getStatus() == EnumValuesFactory.PlanProcessingOrderStatus.组托.getKey()) {
                return ResultGenerator.fail("方棒【" + sectionNo + "】已在" + EnumValuesFactory.PlanProcessingOrderStatus.组托.getValue() + "状态，不允许绑定托盘。");
            }

            List<ProductionBindingTray> productionBindingTrays = this.dao.findByCrystalNo(sectionNo);
            if (productionBindingTrays.size() > 0) {
                return ResultGenerator.fail("该方棒【" + sectionNo + "】已被载具号:[" + productionBindingTrays.get(0).getTrayNo() + "]绑定");
            }

            if ("1.FJY".equals(oldPoint)) {
                //查询当前站点
                Result<CurrentWipStorageStatusDto> currentWipStorageStatusDtoResult = wipStorageService.selectWipStorageResult(sectionNo);
                if (currentWipStorageStatusDtoResult.getCode() != ResultCode.SUCCESS.getCode()) {
                    throw new BusinessException("查询站点信息失败");
                }
                if (currentWipStorageStatusDtoResult.getData() == null) {
                    throw new BusinessException("站点信息为空");
                }
                CurrentWipStorageStatusDto currentWipStorageStatusDto = currentWipStorageStatusDtoResult.getData();
                if (!(currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.方棒检验.getKey())
                        && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey())
                ) {
                    throw new BusinessException("当前晶段在" + currentWipStorageStatusDto.getWipStorageCodeName() + currentWipStorageStatusDto.getWipStorageStatusName() + "，无法在该点位绑定");
                }
            }
        }

        // 查询此单晶是否已经被绑定
        List<ProductionBindingTray> trayNos = dao.findByTrayNo(dto.getTrayNo());
        for (ProductionBindingTray trayNo : trayNos) {
            if (trayNo.getLocationNo() != null && trayNo.getLocationNo().equals(dto.getLocationNo())) {
                if (StringUtils.isNotEmpty(trayNo.getCrystalNo())) {
                    return ResultGenerator.fail("该载具【" + trayNo.getLocationNo() + "】工位,已绑定【" + trayNo.getCrystalNo() + "】,无法绑定");
                } else {
                    dto.setId(trayNo.getId());
                }
            }

        }

        //如果没有指定，那就默认人工绑定
        if (dto.getIsBinding() == null) {
            dto.setIsBinding(1);
        }

        ProductionBindingTray trayNos1 = this.dao.getByTrayNoAndLocationNo(dto.getTrayNo(), dto.getLocationNo());
        if (trayNos1 != null) {
            if (StringUtils.isNotBlank(trayNos1.getCrystalNo())) {
                return ResultGenerator.fail("该载具【" + trayNos1.getLocationNo() + "】工位,已绑定[" + trayNos1.getCrystalNo() + "],无法绑定");
            } else {
                dto.setId(trayNos1.getId());
            }
        }

        if (StringUtils.isNotBlank(dto.getPoint())) {
            String[] pointArr = dto.getPoint().split("\\.");
            if (pointArr.length > 1) {
                dto.setPoint(pointArr[1]);
            } else {
                dto.setPoint(pointArr[0]);
            }
        }

        //如果没有上料点位，则不判断是否在当前点位的工序
        if (StringUtils.isNotBlank(dto.getPoint())) {
//            String wipStorageName = EnumValuesFactory.WipStorageCode.getText(dto.getPoint());
//            if (wipStorageName == null) {
//                return ResultGenerator.fail("载具绑定点位配置中的【" + dto.getPoint() + "】在制品工步代码不存在");
//            }
            DictionaryItem dictionaryItem = dictionaryItemService.findByThemeValueAndValueAndEnable(Constants.FB_BIND_SITE, oldPoint, true);
            if (dictionaryItem == null) {
                throw new BusinessException("该上料点位配置不存在，请刷新页面重试");
            }
            //wipStorageService.selectWipStorage(dto.getCrystalNo(), dto.getPoint(), null);
            dto.setBindingSite(dictionaryItem.getName());
        }

        productionBindingTray = fromDto(dto);
        productionBindingTray.setBindingTime(new Date());
        this.dao.save(productionBindingTray);

        // 写入载具绑定记录表
        ProductionBindingTrayLog log = new ProductionBindingTrayLog();
        log.setBindingPeople(dto.getBindingPeople());
        log.setIsBinding(productionBindingTray.getIsBinding());
        log.setCrystalNo(dto.getCrystalNo());
        log.setGmtCreate(new Date());
        log.setBindingTime(productionBindingTray.getBindingTime());
        log.setTrayNo(dto.getTrayNo());
        log.setLocationNo(dto.getLocationNo());
        log.setClassName(dto.getClassName());
        log.setClassnoname(dto.getClassNoName());
        log.setBindingSite(dto.getBindingSite());
        productionBindingTrayLogService.saveOrUpdate(log);
        //非自动绑定
        if (dto.getIsBinding() != 0) {
            //圆棒直发绑定点位，推送mcs绑定信息
            this.dealWithSend(dto, oldPoint, fbCheckOutData);
        }
        return ResultGenerator.success();
    }

    private void dealWithSend(ProductionBindingTrayDto dto, String oldPoint, FbCheckOutData fbCheckOutData) {
        List<String> listSectionNo = new ArrayList<>();
        SquareBindingDto squareBindingDto = new SquareBindingDto();
        squareBindingDto.setTrayCode(dto.getTrayNo());
        Flag4MDto flag4MDto = fbCheckOutRecordService.whetherOrNotSampling(dto.getCrystalNo());
        squareBindingDto.setCheckType(null != flag4MDto && flag4MDto.getFlagSizeCheck() ? "1" : "0");
        listSectionNo.add(dto.getCrystalNo());
        if (fbCheckOutData != null){
            BigDecimal length = fbCheckOutData.getLength();
            if(fbCheckOutData.getSticksCount() != null && fbCheckOutData.getSticksCount() > 1){
                listSectionNo = Arrays.asList(fbCheckOutData.getSectionCompose().split(","));
                length = fbCheckOutData.getSpellBarLength();
            }
            squareBindingDto.setSquareType(fbCheckOutData.getSpecification());
            squareBindingDto.setSpec(fbCheckOutData.getSpecification());
            squareBindingDto.setCheckName(fbCheckOutData.getCheckoutName());
            squareBindingDto.setLength(length);
            squareBindingDto.setExperimentRank(fbCheckOutData.getFbExperiLevel());
            squareBindingDto.setProductRank(fbCheckOutData.getYbLevel());
        }else {
            // 通过方棒编号去追溯表中找到对应的圆棒id 编号信息
            RecutDetail bySectionNoFb = recutDetailDao.findBySectionNoFb(dto.getCrystalNo());
            if (bySectionNoFb == null) {
                throw new BusinessException("托盘绑定信息,下发MCS失败！：" + "该方棒" + dto.getCrystalNo() + "不存在，无法录入数据");
            }
            Result<GetFbInfoDto> fbInfoByIdResult = ybFeignService.findFbInfoBySectionNoYb(bySectionNoFb.getSectionNo());
            if (fbInfoByIdResult.getCode() != ResultCode.SUCCESS.getCode()) {
                throw new BusinessException(fbInfoByIdResult.getMessage());
            }
            GetFbInfoDto fbInfoById = fbInfoByIdResult.getData();

            BigDecimal length = fbInfoById.getLength();
            if (fbInfoById.getSticksCount() != null && fbInfoById.getSticksCount() > 1) {
                listSectionNo = Arrays.asList(fbInfoById.getSectionCompose().split(","));
                length = fbInfoById.getSpellBarLength();
            }
            squareBindingDto.setSquareType(fbInfoById.getProductTypeSecond());
            squareBindingDto.setSpec(fbInfoById.getProductTypeSecond().equals("295") ? fbInfoById.getProductTypeSecond() + "*210" : fbInfoById.getProductTypeSecond() + "*182");
            squareBindingDto.setCheckName("一次检验");
            squareBindingDto.setLength(length);
            squareBindingDto.setExperimentRank(fbInfoById.getProductLevelExperiment());
            squareBindingDto.setProductRank(fbInfoById.getProductLevel());
        }
        //磨削下料记录
        GrindingBlanking grindingBlanking = grindingBlankingService.findTopByFbSectionNoOrderByIdDesc(dto.getCrystalNo());
        if (grindingBlanking != null && grindingBlanking.getGrindingOrder() != null){
            Integer processNum = null;
            try {
                processNum = Integer.parseInt(grindingBlanking.getGrindingOrder());
            }catch(NumberFormatException e){

            }
            squareBindingDto.setProcessNum(processNum);
        }
        squareBindingDto.setSquareNo(listSectionNo.stream().collect(Collectors.joining("_")));

        if (active != null && active.equals("prod")) {
            ResultDto resultDto = mesToMcsService.squareBinding(squareBindingDto);
            if (resultDto.getStatus() != 100) {
                throw new BusinessException("托盘绑定信息,下发MCS失败！：" + resultDto.getMessage());
            }
        }

    }


    /**
     * 托盘自动解绑
     */
    @Override
    public void UnBinding(TrayUnBindingDto trayUnBindingDto) {
        List<ProductionBindingTray> productionBindingTrayList = this.getByTrayNo(trayUnBindingDto.getTrayNo());
        for (ProductionBindingTray bindingTray : productionBindingTrayList) {
            if (bindingTray != null && StringUtils.isNotBlank(bindingTray.getCrystalNo())) {
                // 解绑需要同时改变长棒表载具号中AGV送验状态
                bindingTray.setBindingSite(trayUnBindingDto.getPoint());
                bindingTray.setCrystalNo(null);
                bindingTray.setToWhere("");
                this.saveOrUpdate(bindingTray);
                //添加绑定载具记录
                Date currentDate = new Date();
                ProductionBindingTrayLog log = new ProductionBindingTrayLog();
                log.setTrayNo(trayUnBindingDto.getTrayNo());
                log.setBindingTime(currentDate);
                log.setBindingSite(trayUnBindingDto.getSource());
                log.setIsBinding(2);//解绑
                log.setGmtCreate(currentDate);
                log.setLocationNo(bindingTray.getLocationNo());
                log.setReason(trayUnBindingDto.getSource() + trayUnBindingDto.getReason());
                productionBindingTrayLogService.saveOrUpdate(log);
            }
            //托盘解绑信息下发mcs
            if (StringUtils.isNotEmpty(trayUnBindingDto.getTrayNo())) {
                String trayNo = trayUnBindingDto.getTrayNo().toUpperCase();
                CrystalTrayUnBindInfoDto crystalTrayUnBindInfoDto = new CrystalTrayUnBindInfoDto();
                crystalTrayUnBindInfoDto.setTrayCode(trayNo);
                ybFeignClients.crystalTrayUnBindInfo(crystalTrayUnBindInfoDto);
            }
        }

    }

    @Override
    public ProductionBindingTray findByTrayNo(String trayNo) {
        List<ProductionBindingTray> productionBindingTrayList = dao.findByTrayNo(trayNo);
        if (CollectionUtils.isNotEmpty(productionBindingTrayList)){
            ProductionBindingTray productionBindingTray = productionBindingTrayList.stream()
                    .max(Comparator.comparing(ProductionBindingTray::getId))
                    .get();
            return productionBindingTray;
        }
        return null;
    }


    public ProductionBindingTray fromDto(ProductionBindingTrayDto dto) {
        return modelMapper.map(dto, ProductionBindingTray.class);
    }

    @Override
    public ProductionBindingTray getByCrystalNo(String crystalNo) {
        List<ProductionBindingTray> trays = dao.findByCrystalNo(crystalNo);
        if (trays.size() > 0) {
            return trays.get(0);
        } else {
            return null;
        }
    }

    @Override
    public List<ProductionBindingTray> getByTrayNo(String code) {
        return dao.findByTrayNoAndCrystalNo(code);
    }
}
