package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.job;

import cn.estsh.i3plus.ext.mes.pcn.api.job.IMesWorkOrderOfflineRestoreDispatchService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesProductionRecordOfflineModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.pojo.base.codemaker.SnowflakeIdMaker;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.*;
import cn.estsh.i3plus.pojo.mes.bean.offline.MesWorkOrderAssemblyOffline;
import cn.estsh.i3plus.pojo.mes.bean.offline.MesWorkOrderOffline;
import cn.estsh.i3plus.pojo.mes.bean.offline.MesWorkOrderPartOffline;
import cn.estsh.i3plus.pojo.mes.repository.*;
import cn.estsh.i3plus.pojo.mes.repository.offline.MesWorkOrderAssemblyOfflineRepository;
import cn.estsh.i3plus.pojo.mes.repository.offline.MesWorkOrderOfflineRepository;
import cn.estsh.i3plus.pojo.mes.repository.offline.MesWorkOrderPartOfflineRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import com.alibaba.fastjson.JSONObject;
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.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MesWorkOrderOfflineRestoreDispatchService implements IMesWorkOrderOfflineRestoreDispatchService {

    @Autowired
    private MesWorkOrderAssemblyOfflineRepository workOrderAssemblyOfflineRepository;

    @Autowired
    private MesWorkOrderOfflineRepository workOrderOfflineRepository;

    @Autowired
    private MesWorkOrderPartOfflineRepository workOrderPartOfflineRepository;

    @Autowired
    private MesWorkOrderAssemblyRepository workOrderAssemblyRepository;

    @Autowired
    private MesProductionAssemblyRepository productionAssemblyRepository;

    @Autowired
    private MesWorkOrderRepository workOrderRepository;

    @Autowired
    private MesWorkOrderPartRepository workOrderPartRepository;

    @Autowired
    private MesProduceSnRepository produceSnRepository;

    @Autowired
    private MesProductionRecordRepository productionRecordRepository;

    @Autowired
    private SnowflakeIdMaker snowflakeIdMaker;

    @Override
    public void saveWorkOrderOffline(MesWorkOrderOffline workOrderOffline, Boolean result) {
        ConvertBean.serviceModelUpdate(workOrderOffline, MesPcnExtConstWords.JOB);
        if (result) workOrderOffline.setSystemSyncStatus(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
        workOrderOfflineRepository.updateNoSync(workOrderOffline);
    }

    @Override
    public Boolean doRestoreWorkOrderOfflineData(String organizeCode, MesWorkOrderOffline workOrderOffline, List<MesWorkOrderAssemblyOffline> workOrderAssemblyOfflineList, String now, Boolean flag) {

        //写入工单; 写入条码
        if (StringUtils.isEmpty(workOrderOffline.getWorkOrderId())) {
            insertOrderAndPs(workOrderOffline, now);
        }

        //写入工单零件
        if (StringUtils.isEmpty(workOrderOffline.getOrderPartStatus()) || workOrderOffline.getOrderPartStatus().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0) {
            insertOrderPart(organizeCode, workOrderOffline, now);
        }

        //写入加工记录, 工单装配件, 装配件装配记录
        insertAssemblyRecord(organizeCode, workOrderOffline, workOrderAssemblyOfflineList, now);

        //补偿修改加工记录的汇报状态: 此前已经标记了汇报工位,但缺失工单零件信息 未进行标记汇报处理状态的数据
        if (!StringUtils.isEmpty(workOrderOffline.getReportCellCode()) &&
                !StringUtils.isEmpty(workOrderOffline.getOrderPartStatus()) && workOrderOffline.getOrderPartStatus().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0 &&
                (StringUtils.isEmpty(workOrderOffline.getReportCellStatus()) || workOrderOffline.getReportCellStatus().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)) {
            saveProductionRecordReportStatus(organizeCode, workOrderOffline);
        }

        //补偿处理的默认返回true, 否则根据已经标记了汇报处理状态的返回true
        return flag ? true : ((StringUtils.isEmpty(workOrderOffline.getReportCellStatus()) || workOrderOffline.getReportCellStatus().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0) ? false : true);

    }

    private void insertOrderAndPs(MesWorkOrderOffline workOrderOffline, String now) {
        //写入工单
        MesWorkOrder workOrder = new MesWorkOrder();
        BeanUtils.copyProperties(workOrderOffline, workOrder, MesPcnExtConstWords.ID);
        workOrder.setScrapPartQty(new Double(0));
        workOrder.setSuspiciousPartQty(new Double(0));
        workOrder.setDisassemblyQty(new Double(0));
        workOrder.setAdjustQty(new Double(0));
        workOrder.setReportedQty(new Double(0));
        workOrder.setUnCompleteQty(new Double(0));
        workOrder.setCompleteQty(new Double(1));
        workOrder.setWorkOrderStatus(MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue());
        workOrder.setCcscStatus(MesExtEnumUtil.OK_NOK.OK.getValue());
        workOrder.setOnlineTime(workOrderOffline.getCreateDatetime());
        workOrder.setOfflineTime(workOrderOffline.getCreateDatetime());
        workOrder.setStartTime(workOrderOffline.getCreateDatetime());
        workOrder.setEndTime(workOrderOffline.getCreateDatetime());
        workOrder.setModifyDatetime(now);
        workOrder.setModifyUser(MesPcnExtConstWords.JOB);
        workOrder.setSystemSyncStatus(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
        workOrder = workOrderRepository.insert(workOrder);

        //写入条码
        MesProduceSn produceSn = new MesProduceSn();
        BeanUtils.copyProperties(workOrder, produceSn, MesPcnExtConstWords.ID);
        produceSn.setSerialNumber(workOrder.getWorkOrderNo());
        produceSn.setProductSn(workOrder.getWorkOrderNo());
        produceSn.setCustSn(workOrder.getCustSn());
        produceSn.setQty(new Double(1));
        produceSn.setSnType(MesExtEnumUtil.PRODUCE_SN_TYPE.STANDARD.getValue());
        produceSn.setSnStatus(MesExtEnumUtil.PRODUCE_SN_STATUS.OFFLINE.getValue());
        produceSn.setQcStatus(MesExtEnumUtil.PRODUCE_QC_STATUS.QUALIFIED.getValue());
        produceSn.setPrintCount(MesPcnExtConstWords.ONE);
        produceSn.setPrintStatus(MesExtEnumUtil.PRINT_STATUS.PRINTED.getValue());
        produceSn.setLotNo(workOrderOffline.getCreateDatetime().substring(0, 10));
        produceSn.setInWorkCenterTime(workOrderOffline.getCreateDatetime());
        produceSn.setOutWorkCenterTime(workOrderOffline.getCreateDatetime());
        produceSn.setFid(UUID.randomUUID().toString());
        produceSn = produceSnRepository.insert(produceSn);

        //离线工单记录进行赋值
        workOrderOffline.setWorkOrderId(workOrder.getId().toString());
        workOrderOffline.setProduceSnId(produceSn.getId().toString());
    }

    private void insertOrderPart(String organizeCode, MesWorkOrderOffline workOrderOffline, String now) {
        if (StringUtils.isEmpty(workOrderOffline.getOrderPartCount()) || workOrderOffline.getOrderPartCount().compareTo(MesPcnExtConstWords.ZERO) <= 0) {
            log.info("--- 异常 --- 补录离线生产工单数据JOB --- 工单:{} --- 工单零件信息数据量[ORDER_PART_COUNT]值异常 ---", workOrderOffline.getWorkOrderNo());
            return;
        }
        List<MesWorkOrderPartOffline> workOrderPartOfflineList = workOrderPartOfflineRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_ORDER_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workOrderOffline.getWorkOrderNo()});
        if (CollectionUtils.isEmpty(workOrderPartOfflineList) || workOrderPartOfflineList.size() != workOrderOffline.getOrderPartCount()) {
            log.info("--- 异常 --- 补录离线生产工单数据JOB --- 工单:{} --- 工单零件信息数据量[ORDER_PART_COUNT]值[{}]与当前查询到的生产工单零件离线信息数据量[{}]不相等 ---",
                    workOrderOffline.getWorkOrderNo(), workOrderOffline.getOrderPartCount(), CollectionUtils.isEmpty(workOrderPartOfflineList) ? MesPcnExtConstWords.ZERO : workOrderPartOfflineList.size());
            return;
        }

        for (MesWorkOrderPartOffline workOrderPartOffline : workOrderPartOfflineList) {
            MesWorkOrderPart workOrderPart = new MesWorkOrderPart();
            BeanUtils.copyProperties(workOrderPartOffline, workOrderPart, MesPcnExtConstWords.ID);
            workOrderPart.setModifyUser(MesPcnExtConstWords.JOB);
            workOrderPart.setSystemSyncStatus(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
            workOrderPartRepository.insert(workOrderPart);
        }
        workOrderOffline.setOrderPartStatus(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
    }

    private void insertAssemblyRecord(String organizeCode, MesWorkOrderOffline workOrderOffline, List<MesWorkOrderAssemblyOffline> workOrderAssemblyOfflineList, String now) {
        if (CollectionUtils.isEmpty(workOrderAssemblyOfflineList)) {
            log.info("--- 异常 --- 补录离线生产工单数据JOB --- 工单:{} --- 当前没有需要补录的工单装配件离线数据 ---", workOrderOffline.getWorkOrderNo());
            return;
        }

        //工单装配件离线数据根据工位进行分组
        Map<String, List<MesWorkOrderAssemblyOffline>> cellMap = CollectionUtils.isEmpty(workOrderAssemblyOfflineList) ? null :
                workOrderAssemblyOfflineList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesWorkOrderAssemblyOffline::getWorkCellCode));

        //解析加工记录工位字段信息    拼接新增过的工位加工记录 [{"id":"1","workCellCode":"100-10"},{"id":"2","workCellCode":"100-20"}....]
        List<MesProductionRecordOfflineModel> productionRecordOfflineModelList = StringUtils.isEmpty(workOrderOffline.getProductionRecord()) ? new ArrayList<>() : JSONObject.parseArray(workOrderOffline.getProductionRecord(), MesProductionRecordOfflineModel.class);
        Map<String, String> productionRecordOfflineMap = CollectionUtils.isEmpty(productionRecordOfflineModelList) ? null :
                productionRecordOfflineModelList.stream().filter(o -> null != o).collect(Collectors.toMap(MesProductionRecordOfflineModel::getWorkCellCode, MesProductionRecordOfflineModel::getId));

        for (Map.Entry<String, List<MesWorkOrderAssemblyOffline>> entry : cellMap.entrySet()) {
            if (null == entry) continue;

            List<MesWorkOrderAssemblyOffline> assemblyOfflineList = entry.getValue();

            Boolean isExistProductionRecord = (CollectionUtils.isEmpty(productionRecordOfflineMap) || !productionRecordOfflineMap.containsKey(entry.getKey())) ? false : true;
            Long productionRecordId = !isExistProductionRecord ? snowflakeIdMaker.nextId() : Long.valueOf(productionRecordOfflineMap.get(entry.getKey()));

            //写入加工记录
            MesProductionRecord productionRecord;
            if (!isExistProductionRecord) {
                productionRecord = new MesProductionRecord();
                productionRecord.setId(productionRecordId);
                productionRecord.setSerialNumber(workOrderOffline.getWorkOrderNo());
                productionRecord.setProductSn(workOrderOffline.getWorkOrderNo());
                productionRecord.setCustSn(workOrderOffline.getCustSn());
                productionRecord.setWorkOrderNo(workOrderOffline.getWorkOrderNo());
                productionRecord.setPartNo(workOrderOffline.getPartNo());
                productionRecord.setPartName(workOrderOffline.getPartName());
                productionRecord.setAreaCode(assemblyOfflineList.get(0).getAreaCode());
                productionRecord.setWorkCenterCode(workOrderOffline.getWorkCenterCode());
                productionRecord.setWorkCellCode(entry.getKey());
                productionRecord.setQty(workOrderOffline.getQty());
                productionRecord.setLotNo(workOrderOffline.getCreateDatetime().substring(0, 10));
                productionRecord.setShiftCode(workOrderOffline.getShiftCode());
                productionRecord.setProcessCode(assemblyOfflineList.get(0).getProcessCode());
                productionRecord.setCraftCode(assemblyOfflineList.get(0).getCraftCode());
                productionRecord.setEquipmentCode(assemblyOfflineList.get(0).getEquipmentCode());
                productionRecord.setMouldRecordId(snowflakeIdMaker.nextId());
                productionRecord.setIsComplete(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
                productionRecord.setStartDateTime(workOrderOffline.getCreateDatetime());
                productionRecord.setCompleteDateTime(workOrderOffline.getCreateDatetime());
                productionRecord.setReportType(MesExtEnumUtil.MES_REPORT_TYPE.NO_REPORT.getValue());
                productionRecord.setReportStatus(MesExtEnumUtil.REPORT_STATUS.REPORT_STATUS_30.getValue());
                productionRecord.setModuleStatisticsStatus(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
                productionRecord.setFid(UUID.randomUUID().toString());
                productionRecord.setOneMouldMoreId(UUID.randomUUID().toString());
                productionRecord.setSystemSyncStatus(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
                productionRecord.setOrganizeCode(organizeCode);
                ConvertBean.serviceModelInitialize(productionRecord, MesPcnExtConstWords.JOB);
            } else {
                productionRecord = productionRecordRepository.getByProperty(
                        new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.ID},
                        new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), productionRecordId});
            }

            for (MesWorkOrderAssemblyOffline assemblyOffline : assemblyOfflineList) {
                if (null == assemblyOffline) continue;

                //写入工单装配件
                MesWorkOrderAssembly workOrderAssembly = new MesWorkOrderAssembly();
                BeanUtils.copyProperties(assemblyOffline, workOrderAssembly, MesPcnExtConstWords.ID);
                workOrderAssembly.setModifyDatetime(now);
                workOrderAssembly.setModifyUser(MesPcnExtConstWords.JOB);
                workOrderAssembly.setSystemSyncStatus(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
                workOrderAssemblyRepository.insert(workOrderAssembly);

                MesProductionAssembly productionAssembly = new MesProductionAssembly();
                BeanUtils.copyProperties(assemblyOffline, productionAssembly, MesPcnExtConstWords.ID);
                productionAssembly.setCustSn(workOrderOffline.getCustSn());
                productionAssembly.setModifyDatetime(now);
                productionAssembly.setModifyUser(MesPcnExtConstWords.JOB);
                productionAssembly.setSystemSyncStatus(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
                productionAssembly.setFid(UUID.randomUUID().toString());
                productionAssembly.setMouldRecordId(productionRecord.getMouldRecordId());
                productionAssembly.setProductionRecordId(productionRecord.getId());
                productionAssemblyRepository.insert(productionAssembly);

                //工单装配件离线数据改已同步
                assemblyOffline.setSystemSyncDatetime(now);
                assemblyOffline.setSystemSyncStatus(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
                workOrderAssemblyOfflineRepository.updateNoSync(assemblyOffline);

                if (StringUtils.isEmpty(workOrderOffline.getReportCellCode()) && !StringUtils.isEmpty(assemblyOffline.getReportType()) && assemblyOffline.getReportType().compareTo(MesExtEnumUtil.MES_REPORT_TYPE.NO_REPORT.getValue()) != 0) {
                    workOrderOffline.setReportCellCode(entry.getKey());
                    workOrderOffline.setReportType(assemblyOffline.getReportType());
                    workOrderOffline.setReportPartNo(!StringUtils.isEmpty(assemblyOffline.getReportPartNo()) ? assemblyOffline.getReportPartNo() : workOrderOffline.getPartNo());
                }

            }

            //判断是否写入汇报状态
            if (!StringUtils.isEmpty(workOrderOffline.getReportCellCode()) && workOrderOffline.getReportCellCode().equals(entry.getKey()) &&
                    !StringUtils.isEmpty(workOrderOffline.getOrderPartStatus()) && workOrderOffline.getOrderPartStatus().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0 &&
                    (StringUtils.isEmpty(workOrderOffline.getReportCellStatus()) || workOrderOffline.getReportCellStatus().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)) {
                productionRecord.setReportType(workOrderOffline.getReportType());
                productionRecord.setReportPartNo(workOrderOffline.getReportPartNo());
                productionRecord.setReportStatus(MesExtEnumUtil.REPORT_STATUS.REPORT_STATUS_10.getValue());
                if (isExistProductionRecord) {
                    productionRecord.setSystemSyncStatus(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
                    ConvertBean.serviceModelUpdate(productionRecord, MesPcnExtConstWords.JOB);
                }
                workOrderOffline.setReportCellStatus(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
            }

            if (isExistProductionRecord) {
                productionRecordRepository.updateNoSync(productionRecord);
            } else {
                productionRecordRepository.insert(productionRecord);
                productionRecordOfflineModelList.add(new MesProductionRecordOfflineModel(entry.getKey(), productionRecord.getId().toString()));
                workOrderOffline.setProductionRecord(JSONObject.toJSONString(productionRecordOfflineModelList));
            }

        }

    }

    private void saveProductionRecordReportStatus(String organizeCode, MesWorkOrderOffline workOrderOffline) {
        List<MesProductionRecordOfflineModel> productionRecordOfflineModelList = JSONObject.parseArray(workOrderOffline.getProductionRecord(), MesProductionRecordOfflineModel.class);
        String productionRecordId = productionRecordOfflineModelList.stream().filter(o -> (null != o && o.getWorkCellCode().equals(workOrderOffline.getReportCellCode()))).findFirst().get().getId();
        MesProductionRecord productionRecord = productionRecordRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.ID},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), productionRecordId});

        productionRecord.setReportType(workOrderOffline.getReportType());
        productionRecord.setReportPartNo(workOrderOffline.getReportPartNo());
        productionRecord.setReportStatus(MesExtEnumUtil.REPORT_STATUS.REPORT_STATUS_10.getValue());
        productionRecord.setSystemSyncStatus(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
        ConvertBean.serviceModelUpdate(productionRecord, MesPcnExtConstWords.JOB);
        productionRecordRepository.updateNoSync(productionRecord);

        workOrderOffline.setReportCellStatus(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
    }

}
