package com.sw.mes.yb.seed.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sw.mes.base.factory.material.entity.MaterialType;
import com.sw.mes.base.factory.material.service.MaterialTypeService;
import com.sw.mes.base.factory.product.entity.ProductModel;
import com.sw.mes.core.api.system.FbFeignClients;
import com.sw.mes.core.api.system.StoreFeignClients;
import com.sw.mes.core.api.system.YbFeignClients;
import com.sw.mes.core.base.BaseServiceImpl;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.dto.DictionaryItemDto;
import com.sw.mes.core.dto.FactoryMaterialModelDto;
import com.sw.mes.core.dto.ProductionOrderDto;
import com.sw.mes.core.dto.mes.pc.fb.FbCheckOutDataDto;
import com.sw.mes.core.dto.sap.RecycledReportSapRecordDto;
import com.sw.mes.core.dto.sap.ReportSapChargItemDto;
import com.sw.mes.core.dto.sap.ReportSapGoodsmvtDto;
import com.sw.mes.core.dto.store.WarehouseInventoryBo;
import com.sw.mes.core.dto.store.WarehouseInventoryDto;
import com.sw.mes.core.dto.store.WarehouseOutputBillBo;
import com.sw.mes.core.dto.store.WarehouseOutputBillDetailBo;
import com.sw.mes.core.enums.MesToSapTypeEnum;
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.CodeSenderUtils;
import com.sw.mes.core.utils.RedisTools;
import com.sw.mes.core.utils.StringUtils;
import com.sw.mes.core.utils.ThreadManager;
import com.sw.mes.inspect.entity.YbInspectData;
import com.sw.mes.inspect.service.YbInspectDataService;
import com.sw.mes.sap.entity.ReportSapGoodsmvt;
import com.sw.mes.sap.service.ReportSapGoodsmvtService;
import com.sw.mes.yb.pad.entity.SectionNoDetail;
import com.sw.mes.yb.pad.service.SectionNoDetailService;
import com.sw.mes.yb.plan.entity.ProductionOrder;
import com.sw.mes.yb.plan.service.ProductionOrderService;
import com.sw.mes.yb.production.entity.RecycledMaterialManage;
import com.sw.mes.yb.production.service.RecycledMaterialManageService;
import com.sw.mes.yb.seed.dao.SeedDataDao;
import com.sw.mes.yb.seed.dto.SeedBatchesDataDto;
import com.sw.mes.yb.seed.dto.SeedBatchesDto;
import com.sw.mes.yb.seed.dto.SeedDataDto;
import com.sw.mes.yb.seed.entity.SeedData;
import com.sw.mes.yb.seed.enums.SeedMetaEnum;
import com.sw.mes.yb.seed.service.SeedService;
import com.sw.mes.yb.seed.utils.SeedCodeGeneratorNewUtils;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.SimpleFormatter;

/**
 * @Author：wanjia
 * @Date：2024/1/9 17:02
 */
@Service
@Slf4j
public class SeedServiceImpl extends BaseServiceImpl<SeedData> implements SeedService {

    private SeedDataDao dao;
    @Autowired
    private SeedCodeGeneratorNewUtils seedCodeGeneratorNewUtils;
    @Autowired
    private YbInspectDataService ybInspectDataService;
    @Autowired
    private FbFeignClients fbFeignClients;
    @Autowired
    private ProductionOrderService productionOrderService;
    @Autowired
    private MaterialTypeService materialTypeService;
    @Autowired
    private YbFeignClients ybFeignClients;
    @Autowired
    private SectionNoDetailService sectionNoDetailService;
    @Autowired
    private StoreFeignClients storeFeignClients;
    @Autowired
    private ReportSapGoodsmvtService reportSapGoodsmvtService;
    @Autowired
    private RecycledMaterialManageService recycledMaterialManageService;

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

    @Override
    public SeedData findByCode(String code) {
        return dao.findByCode(code);
    }

    @Override
    public SeedData findByBatchNo(String seedBatchNo) {
        return dao.findByBatchNo(seedBatchNo);
    }

    @Override
    public SeedData findByBatch(String batchNo) {
        return dao.findByBatch(batchNo);
    }

    @Override
    public List<SeedData> findByBatchs(String batchNo) {
        return dao.findByBatchs(batchNo);
    }

    @Override
    public List<SeedData> findByBatchAndQualified(String batchNo) {
        return dao.findByBatchAndQualified(batchNo);
    }

    @Override
    public Result create(SeedDataDto seedDataDto) {
        SeedData seedDataCode = this.findByCode(seedDataDto.getSeedCode());
        if (!ObjectUtils.isEmpty(seedDataCode)) {
            return ResultGenerator.fail("该籽晶对象已存在!");
        }
        //查询是否来源于圆棒
        Result dataByFbSectionNo = fbFeignClients.findDataByFbSectionNo(seedDataDto.getBatchNo());
        YbInspectData bySectionNo = new YbInspectData();
        FbCheckOutDataDto fbCheckOutDataDto = new FbCheckOutDataDto();
        if (ObjectUtils.isEmpty(dataByFbSectionNo.getData())) {
            bySectionNo = ybInspectDataService.findBySectionNo(seedDataDto.getBatchNo());
        } else {
            fbCheckOutDataDto = JSONObject.parseObject(JSONObject.toJSONString(dataByFbSectionNo.getData()), FbCheckOutDataDto.class);
        }
        SeedData seedData = fromDto(seedDataDto);
        //如果方棒没有查询到数据，其余一概默认来源圆棒
        if (ObjectUtils.isEmpty(fbCheckOutDataDto)) {
            if (!ObjectUtils.isEmpty(bySectionNo)) {
                seedData.setDopant(bySectionNo.getDopant());
            }
            seedData.setSource(SeedMetaEnum.SEED_INGOT.getOriginDesc());
        } else {
            seedData.setDopant(fbCheckOutDataDto.getDopant());
            seedData.setSource(SeedMetaEnum.SEED_BRICK.getOriginDesc());
            seedData.setHeadTailRecognition(fbCheckOutDataDto.getHeadTailRecognition());
        }
        seedData.setSeedCode(seedCodeGeneratorNewUtils.generator(bySectionNo, seedData));
        seedData.setSeedBatchNo("001");
        seedData.setDeleted(false);
        seedData.setCreateBy(BaseContextHandler.getUsername());
        seedData.setCreateDate(new Date());
        this.saveOrUpdate(seedData);
        return ResultGenerator.success();
    }

    @Override
    public Result batches(SeedBatchesDto seedBatchesDto) {
        if (ObjectUtils.isEmpty(seedBatchesDto)) {
            return ResultGenerator.fail("请传入相关参数!");
        }
        if (seedBatchesDto.getCount() < 1) {
            return ResultGenerator.fail("分批数量不能小于1!");
        }
        RecycledMaterialManage recycleMaterialByRecycleNo = recycledMaterialManageService.getRecycleMaterialByRecycleNo(seedBatchesDto.getBatchNo());
        if (ObjectUtils.isEmpty(recycleMaterialByRecycleNo)) {
            return ResultGenerator.fail("未查到批次【" + seedBatchesDto.getBatchNo() + "】的库存信息,无法提交,请检查数据!");
        }
        //获取订单
        ProductionOrder productionOrder = productionOrderService.findByAufnr(seedBatchesDto.getPlanCode());
        //校验订单是否已结束
        if (null != productionOrder.getGltrp()) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date startTime = productionOrder.getGltrp();
            Date endTime = new Date();
            boolean before = startTime.before(endTime);
            if (before) {
                return ResultGenerator.fail("订单计划结束时间【" + sdf.format(startTime) + "】已结束,无法在进行生产分批!");
            }
        }
        YbInspectData bySectionNo = new YbInspectData();
        SectionNoDetail byLikeSectionNo = new SectionNoDetail();
        //查圆棒检测数据
        bySectionNo = ybInspectDataService.findByLikeSectionNo(seedBatchesDto.getBatchNo());
        if (null == bySectionNo) {
            bySectionNo = new YbInspectData();
            //查回收料
            byLikeSectionNo = sectionNoDetailService.findByLikeSectionNo(seedBatchesDto.getBatchNo());
            if (ObjectUtils.isEmpty(byLikeSectionNo)) {
                return ResultGenerator.fail("未查到回收料批次【" + seedBatchesDto.getBatchNo() + "】的检测数据");
            }
            SectionNoDetail sectionNoDetail = sectionNoDetailService.get(byLikeSectionNo.getParentId());
            if (ObjectUtils.isEmpty(byLikeSectionNo)) {
                return ResultGenerator.fail("未查到回收料批次【" + seedBatchesDto.getBatchNo() + "】父级的检测数据");
            }
            YbInspectData likeSectionNo = ybInspectDataService.findByLikeSectionNo(sectionNoDetail.getSectionNo());
            if (ObjectUtils.isEmpty(likeSectionNo)) {
                return ResultGenerator.fail("未查到母晶批次【" + sectionNoDetail.getSectionNo() + "】的检测数据");
            }
            if (StringUtils.isNotEmpty(likeSectionNo.getSectionNo())) {
                bySectionNo.setSectionNo(likeSectionNo.getSectionNo());
            }
            if (StringUtils.isNotEmpty(likeSectionNo.getDopant())) {
                bySectionNo.setDopant(likeSectionNo.getDopant());
            }
            if (StringUtils.isNotEmpty(likeSectionNo.getHeadTailRecognition())) {
                bySectionNo.setHeadTailRecognition(likeSectionNo.getHeadTailRecognition());
            }
            if (null != likeSectionNo.getPiecewiseNum()) {
                bySectionNo.setPiecewiseNum(likeSectionNo.getPiecewiseNum());
            }
        }
        FactoryMaterialModelDto material = new FactoryMaterialModelDto();
        Result<FactoryMaterialModelDto> materialByCode = ybFeignClients.findMaterialByCode(seedBatchesDto.getMaterialCode());
        if (!materialByCode.getCode().equals(200) || null == materialByCode.getData()) {
            return ResultGenerator.fail("未查到物料【" + seedBatchesDto.getMaterialCode() + "】的物料模型数据");
        }
        if (materialByCode.getCode().equals(200)) {
            material = materialByCode.getData();
        }
        //分批未提交导致流水号递增，需要重新设置成上次提交的批次流水号
        SeedData maxByBatchNo = dao.findMaxByBatchNo(seedBatchesDto.getBatchNo());
        //获取日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String date = sdf.format(new Date());
        if (!ObjectUtils.isEmpty(maxByBatchNo)) {
            String maxSeedBatchNo = maxByBatchNo.getSeedBatchNo();
            Long aLong = Long.valueOf(maxSeedBatchNo);
            RedisTools.setAtomicValue(seedBatchesDto.getBatchNo().substring(0, 17) + ":" + date, aLong);
        }
        List<SeedDataDto> seedDataDtoList = new ArrayList<>();
        for (int i = 0; i < seedBatchesDto.getCount(); i++) {
            SeedData seedData = new SeedData();
            SeedDataDto seedDataDto = new SeedDataDto();
            seedData.setBatchNo(seedBatchesDto.getBatchNo());
            seedData.setPlanCode(seedBatchesDto.getPlanCode());
            seedData.setWorkShopCode(productionOrder.getField4());
            seedData.setSeedCoringDevice(seedBatchesDto.getSeedCoringDevice());
            seedData.setSeedGrindingDevice(seedBatchesDto.getSeedGrindingDevice());
            seedData.setProcessLength(seedBatchesDto.getProcessLength());
            seedData.setSource(SeedMetaEnum.SEED_INGOT.getOriginDesc());
            seedData.setDopant(bySectionNo.getDopant());
            seedData.setHeadTailRecognition(bySectionNo.getHeadTailRecognition());
            if (!ObjectUtils.isEmpty(productionOrder) && !ObjectUtils.isEmpty(productionOrder.getProductModel())) {
                ProductModel productModel = productionOrder.getProductModel();
                MaterialType materialType = materialTypeService.get(productModel.getId());
                seedData.setMaterialCode(material.getCode());
                seedData.setMaterialId(material.getId());
                seedData.setSpec(productModel.getSpecs());
                seedData.setMaterialModel(material.getModelNumber());
                if (!ObjectUtils.isEmpty(materialType)) {
                    seedData.setMaterialType(material.getType());
                }
                seedData.setMaterialName(productModel.getName());
                if (StringUtils.isEmpty(seedData.getWorkShopCode()) && StringUtils.isNotEmpty(productionOrder.getWorkShop())) {
                    seedData.setWorkShopCode(productionOrder.getWorkShop());
                }
            }
            String seedBatchNo = "";
            if (seedBatchesDto.getBatchNo().length() < 17) {
                return ResultGenerator.fail("请输入正确的母棒批次【" + seedBatchesDto.getBatchNo() + "】,长度不小于17位");
            }
            String number = CodeSenderUtils.getNumber1(seedBatchesDto.getBatchNo().substring(0, 17), "yyyyMMdd", date, 3);
            seedBatchNo = number.substring(number.length() - 3, number.length());
            seedData.setSeedBatchNo(seedBatchNo);
            seedData.setSeedCode(seedCodeGeneratorNewUtils.generator(bySectionNo, seedData));
            seedData.setCreateBy(BaseContextHandler.getUsername());
            seedData.setCreateDate(new Date());
            seedData.setDeleted(false);
            seedData.setDirectionalSign(productionOrder.getZorientationind());
            BeanUtils.copyProperties(seedData, seedDataDto, "id");
            seedDataDtoList.add(seedDataDto);
        }
        return ResultGenerator.success(seedDataDtoList);
    }

    @Override
    public Result submit(SeedBatchesDataDto seedBatchesDataDto) {
        if (CollectionUtils.isEmpty(seedBatchesDataDto.getSeedDataDto())) {
            return ResultGenerator.fail("提交数据为空!,请选择数据之后在进行提交");
        }
        seedBatchesDataDto.getSeedDataDto().stream().forEach(entity -> {
            SeedData seedData = new SeedData();
            BeanUtils.copyProperties(entity, seedData, "id");
            this.saveOrUpdate(seedData);
        });
        SeedBatchesDto seedBatchesDto = seedBatchesDataDto.getSeedBatchesDto();
        RecycledMaterialManage recycleMaterialByRecycleNo = recycledMaterialManageService.getRecycleMaterialByRecycleNo(seedBatchesDto.getBatchNo());
        if (ObjectUtils.isEmpty(recycleMaterialByRecycleNo)) {
            return ResultGenerator.fail("未查到批次【" + seedBatchesDto.getBatchNo() + "】的库存信息,无法提交,请检查数据!");
        }
        Result<DictionaryItemDto> warehouseLocation = ybFeignClients.findNameByThemeValueAndItemValue("ylWarehouseLocation", recycleMaterialByRecycleNo.getWorkShop());
        String warehouseCode = "";
        if (warehouseLocation.getCode().equals(200)) {
            warehouseCode = warehouseLocation.getData().getName();
        }
        Result<WarehouseInventoryBo> inventoryBoResult = storeFeignClients.getByBatchNoAndWarehouseCode(recycleMaterialByRecycleNo.getProduceBatchNo(), warehouseCode);
        if(inventoryBoResult.getCode().equals(200)){
            WarehouseInventoryBo warehouseInventory = inventoryBoResult.getData();
            BigDecimal weight = new BigDecimal(seedBatchesDto.getWeight());
            if(warehouseInventory.getQuantity().compareTo(weight)==-1){
                return ResultGenerator.fail("消耗重量大于当前库存数量【" + warehouseInventory.getQuantity() + "】,无法提交,请检查数据!");
            }
        }else {
            return ResultGenerator.fail("未查到批次【" + seedBatchesDto.getBatchNo() + "】的库存信息,无法提交,请检查数据!");
        }
        WarehouseOutputBillBo warehouseOutputBillBo = new WarehouseOutputBillBo();
        warehouseOutputBillBo.setType("籽晶消耗");
        warehouseOutputBillBo.setAutoAudit(true);
        warehouseOutputBillBo.setCreateUserId(BaseContextHandler.getUserID());
        warehouseOutputBillBo.setCreateUserName(BaseContextHandler.getUsername());
        warehouseOutputBillBo.setDestination("车间");
        List<WarehouseOutputBillDetailBo> warehouseOutputBillDetailBos = new ArrayList<>();
        WarehouseOutputBillDetailBo warehouseOutputBillDetailBo = new WarehouseOutputBillDetailBo();
        warehouseOutputBillDetailBo.setRequireCount(new BigDecimal(seedBatchesDto.getWeight()));
        warehouseOutputBillDetailBo.setOutputCount(new BigDecimal(seedBatchesDto.getWeight()));
        warehouseOutputBillDetailBo.setWarehouseCode(warehouseCode);
        warehouseOutputBillDetailBo.setBatchNo(recycleMaterialByRecycleNo.getProduceBatchNo());
        warehouseOutputBillDetailBo.setMaterialModelCode(recycleMaterialByRecycleNo.getMaterialCode());
        warehouseOutputBillDetailBo.setMaterialModelName(recycleMaterialByRecycleNo.getMaterialName());
        warehouseOutputBillDetailBo.setCreateUserId(warehouseOutputBillBo.getCreateUserId());
        warehouseOutputBillDetailBo.setCreateUserName(warehouseOutputBillBo.getCreateUserName());
        warehouseOutputBillDetailBo.setCrystalNo(recycleMaterialByRecycleNo.getDateProduceBatchNo());
        warehouseOutputBillDetailBos.add(warehouseOutputBillDetailBo);
        warehouseOutputBillBo.setOutputBillDetails(warehouseOutputBillDetailBos);
        Result<String> result = storeFeignClients.outputApply(warehouseOutputBillBo);
        if (result.getCode().equals(200)) {
            ReportSapGoodsmvtDto reportSapGoodsmvtDto = new ReportSapGoodsmvtDto();
            List<ReportSapChargItemDto> reportSapChargItemDtos = new ArrayList<>();
            ReportSapChargItemDto reportSapChargItemDto = new ReportSapChargItemDto();
            reportSapChargItemDtos.add(reportSapChargItemDto);
            reportSapGoodsmvtDto.setChargItems(reportSapChargItemDtos);
            reportSapGoodsmvtDto.setAufnr(seedBatchesDto.getPlanCode());
            reportSapGoodsmvtDto.setCharg(recycleMaterialByRecycleNo.getDateProduceBatchNo());
            reportSapGoodsmvtDto.setBwart("261");
            reportSapGoodsmvtDto.setWerks("5041");
            reportSapGoodsmvtDto.setUmcha(recycleMaterialByRecycleNo.getDateProduceBatchNo());
            reportSapGoodsmvtDto.setUmwrk("5041");
            reportSapGoodsmvtDto.setMatnr(recycleMaterialByRecycleNo.getMaterialCode());
            reportSapGoodsmvtDto.setMenge(seedBatchesDto.getWeight().toString());
            reportSapGoodsmvtDto.setMeins("KG");
            reportSapGoodsmvtDto.setZfcpFlag("");
            reportSapGoodsmvtDto.setProcName("籽晶消耗");
            reportSapGoodsmvtDto.setCrystalNo(recycleMaterialByRecycleNo.getDateProduceBatchNo());
            reportSapGoodsmvtDto.setLgort(warehouseCode);
            reportSapGoodsmvtDto.setUmlgo(warehouseCode);
            ReportSapGoodsmvt reportSapGoodsmvt = new ReportSapGoodsmvt();
            BeanUtils.copyProperties(reportSapGoodsmvtDto, reportSapGoodsmvt);
            reportSapGoodsmvt.setAsyn(false);
            reportSapGoodsmvtService.saveOrUpdate(reportSapGoodsmvt);
        }
        return ResultGenerator.success();
    }

    public SeedData fromDto(SeedDataDto dto) {
        SeedData seedData = new SeedData();
        BeanUtils.copyProperties(dto, seedData);
        return seedData;
    }
}
