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

import cn.estsh.i3plus.ext.mes.pcn.api.base.IShiftExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IShiftProdCenterRecordService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ShiftProdCenterModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ShiftProdCenterRecordModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ShiftProdModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.sqlpack.MesPcnExtHqlPack;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.ConvertBeanExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtEnumUtil;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.exception.ImppExceptionEnum;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.bean.ListPager;
import cn.estsh.i3plus.pojo.base.common.Pager;
import cn.estsh.i3plus.pojo.base.common.PagerHelper;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesShift;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
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.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wangjie
 * @version 1.0
 * @date 2021/1/13 9:28
 **/
@Slf4j
@Service
public class ShiftProdCenterRecordService implements IShiftProdCenterRecordService {

    @Autowired
    private IShiftExtService shiftExtService;

    @Autowired
    private MesWorkCenterExtRepository workCenterExtRepository;

    @Autowired
    private MesShiftProdCenterRecordRepository shiftProdCenterRecordRepository;

    @Autowired
    private MesShiftProdCenterPmRepository shiftProdCenterPmRepository;

    @Autowired
    private MesShiftProdCenterRepository shiftProdCenterRepository;

    @Autowired
    private MesShiftProdRepository shiftProdRepository;

    @Override
    public List<MesShiftExt> queryShiftAll(MesShiftExt shiftExt) {
        return shiftExtService.queryShiftAll(shiftExt);
    }

    @Override
    public ShiftProdCenterModel queryShiftProdCenterData(MesShiftExt shiftExt) {
        ShiftProdCenterModel shiftProdCenterModel = new ShiftProdCenterModel();
        shiftProdCenterModel.setShiftList(queryShiftAll(shiftExt));
        MesWorkCenterExt workCenter = getWorkCenter(shiftExt.getOrganizeCode(), shiftExt.getAreaCode(), shiftExt.getWorkCenterCode());
        if (null == workCenter) {
            return shiftProdCenterModel;
        }
        shiftProdCenterModel.setWorkCenterCode(workCenter.getWorkCenterCode());
        shiftProdCenterModel.setWorkCenterName(workCenter.getWorkCenterName());
        shiftProdCenterModel.setWorkerQty(workCenter.getWorkerQty());
        shiftProdCenterModel.setWorkTime(workCenter.getWorkTime());
        if (!StringUtils.isEmpty(workCenter.getShiftCode()) && !StringUtils.isEmpty(workCenter.getWorkTime())) {
            shiftProdCenterModel.setShiftCode(workCenter.getShiftCode());
            MesShiftExt shiftExtDb = shiftExtService.getShiftExtByShiftCodeAndCenterCode(shiftExt.getOrganizeCode(), workCenter.getWorkCenterCode(), workCenter.getShiftCode());
            if (null != shiftExtDb) {
                shiftProdCenterModel.setShiftName(shiftExtDb.getShiftName());
                shiftProdCenterModel.setShiftStartTime(shiftExtDb.getStartTime());
                shiftProdCenterModel.setShiftEndTime(shiftExtDb.getEndTime());

                //当前时间(YYYY-MM-dd)
                String currentTimeYmd = workCenter.getWorkTime();
                //判断当前班次时间是否跨天,结束时间小于等于开始时间即跨天,否则当天
                Boolean isNextDayFlagShift = compareHms(shiftExtDb.getStartTime(), shiftExtDb.getEndTime());
                //班次实际开始时间(YYYY-MM-dd HH:mm:ss) [当前年月日 + 班次开始时间]
                String shiftStartYmdHms = currentTimeYmd + MesPcnExtConstWords.ONE_SPACE + shiftExtDb.getStartTime();
                //班次实际结束时间(YYYY-MM-dd HH:mm:ss) [if 当天: 当前年月日 + 班次结束时间][else : 明天年月 + 班次结束时间]
                String shiftEndYmdHms = getEndDateByFlag(isNextDayFlagShift, currentTimeYmd, shiftExtDb.getEndTime());

                shiftProdCenterModel.setShiftStartTimeYmdHms(shiftStartYmdHms);
                shiftProdCenterModel.setShiftEndTimeYmdHms(shiftEndYmdHms);
            }
            List<MesShiftProdCenterRecord> shiftProdCenterRecordList = getShiftProdCenterRecordList(
                    shiftExt.getOrganizeCode(), workCenter.getWorkTime(), workCenter.getWorkCenterCode(), workCenter.getShiftCode());

            MesShiftProdCenterPm mesShiftProdCenterPm = getMesShiftProdCenterPm(shiftExt.getOrganizeCode(), workCenter.getWorkCenterCode(), workCenter.getShiftCode(), workCenter.getWorkTime());

            if (!CollectionUtils.isEmpty(shiftProdCenterRecordList)) {
                shiftProdCenterModel.setShiftProdCenterRecordList(packShiftProdCenterRecordList(shiftProdCenterRecordList, mesShiftProdCenterPm, shiftExtDb));
                ShiftProdCenterRecordModel recordTimeDb = shiftProdCenterModel.getShiftProdCenterRecordList().stream().filter(o -> o.getProdType() == MesPcnExtEnumUtil.SHIFT_PROD_TYPE.START_OR_END_SHIFT_TIME.getValue()).findFirst().get();
                shiftProdCenterModel.setAtHomeNum(recordTimeDb == null ? 0 : recordTimeDb.getAtHomeNum());
            }
        }
        return shiftProdCenterModel;
    }

    private List<ShiftProdCenterRecordModel> packShiftProdCenterRecordList(List<MesShiftProdCenterRecord> shiftProdCenterRecordList, MesShiftProdCenterPm mesShiftProdCenterPm, MesShiftExt shift) {
        List<ShiftProdCenterRecordModel> modelList = new ArrayList<>();
        for (MesShiftProdCenterRecord shiftProdCenterRecord : shiftProdCenterRecordList) {
            if (null == shiftProdCenterRecord) {
                continue;
            }
            ShiftProdCenterRecordModel model = new ShiftProdCenterRecordModel();
            BeanUtils.copyProperties(shiftProdCenterRecord, model);
            model.setProdCategoryName(StringUtils.isEmpty(shiftProdCenterRecord.getProdCategory()) ?
                    null : MesPcnExtEnumUtil.SHIFT_PROD_CATEGORY.valueOfDescription(shiftProdCenterRecord.getProdCategory()));
            model.setProdTypeName(StringUtils.isEmpty(shiftProdCenterRecord.getProdType()) ?
                    null : MesPcnExtEnumUtil.SHIFT_PROD_TYPE.valueOfDescription(shiftProdCenterRecord.getProdType()));
            model.setIsProdTimeName(StringUtils.isEmpty(shiftProdCenterRecord.getIsProdTime()) ?
                    null : MesPcnExtEnumUtil.SHIFT_PROD_IS_PROD_TIME.valueOfDescription(shiftProdCenterRecord.getIsProdTime()));
            if (null != shift) {
                model.setShiftStartTime(shift.getStartTime());
                model.setShiftEndTime(shift.getEndTime());
            }
            modelList.add(model);
        }

        if (mesShiftProdCenterPm != null) {
            ShiftProdCenterRecordModel model = new ShiftProdCenterRecordModel();
            BeanUtils.copyProperties(mesShiftProdCenterPm, model);
            //model.setProdCategoryName(StringUtils.isEmpty(mesShiftProdCenterPm.getProdCategory()) ?
            //        null : MesPcnExtEnumUtil.SHIFT_PROD_CATEGORY.valueOfDescription(mesShiftProdCenterPm.getProdCategory()));
            model.setProdType(MesPcnExtEnumUtil.SHIFT_PROD_TYPE.START_OR_END_SHIFT_TIME.getValue());
            model.setProdTypeName(MesPcnExtEnumUtil.SHIFT_PROD_TYPE.START_OR_END_SHIFT_TIME.getDescription());
            //model.setIsProdTimeName(StringUtils.isEmpty(mesShiftProdCenterPm.getIsProdTime()) ?
            //        null : MesPcnExtEnumUtil.SHIFT_PROD_IS_PROD_TIME.valueOfDescription(mesShiftProdCenterPm.getIsProdTime()));
            if (null != shift) {
                model.setShiftStartTime(shift.getStartTime());
                model.setShiftEndTime(shift.getEndTime());
            }
            modelList.add(model);
        }



        return modelList;
    }

    private List<MesShiftProdCenterRecord> getShiftProdCenterRecordList(String organizeCode, String workTime, String workCenterCode, String shiftCode) {
        return shiftProdCenterRecordRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,
                        MesPcnExtConstWords.WORK_CENTER_CODE, MesPcnExtConstWords.SHIFT_CODE, MesPcnExtConstWords.WORK_TIME},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),
                        workCenterCode, shiftCode, workTime});
    }

    public MesWorkCenterExt getWorkCenter(String organizeCode, String areaCode, String workCenterCode) {
        return workCenterExtRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,
                        MesPcnExtConstWords.AREA_CODE, MesPcnExtConstWords.WORK_CENTER_CODE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),
                        areaCode, workCenterCode});
    }

    @Override
    public void doShiftProdCenterStop(ShiftProdCenterRecordModel centerRecordModel) {
        MesWorkCenterExt workCenterDb = getWorkCenter(centerRecordModel.getOrganizeCode(), centerRecordModel.getAreaCode(), centerRecordModel.getWorkCenterCode());
        if (null == workCenterDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("区域代码[%s]生产线代码[%s]对应的信息不存在", centerRecordModel.getAreaCode(), centerRecordModel.getWorkCenterCode())
                    .build();
        }
        if (StringUtils.isEmpty(workCenterDb.getShiftCode()) || StringUtils.isEmpty(workCenterDb.getWorkTime())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线[%s]未启动班次,不能执行结束班次操作", centerRecordModel.getWorkCenterCode())
                    .build();
        }

        MesShiftProdCenterPm shiftProdCenterPmDb = getMesShiftProdCenterPm(centerRecordModel.getOrganizeCode(), workCenterDb.getWorkCenterCode(), workCenterDb.getShiftCode(), workCenterDb.getWorkTime());

        if (shiftProdCenterPmDb == null) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线[%s]不存在开始/结束班次时间类型停开机记录,不能执行结束班次操作", centerRecordModel.getWorkCenterCode())
                    .build();
        }

        workCenterDb.setShiftCode(null);
        workCenterDb.setWorkTime(null);
        workCenterDb.setWorkerQty(null);
        ConvertBean.serviceModelUpdate(workCenterDb, centerRecordModel.getModifyUser());
        new ConvertBeanExt(workCenterDb).convertBean(workCenterDb);
        workCenterExtRepository.save(workCenterDb);

        shiftProdCenterPmDb.setEndTime(centerRecordModel.getEndTime());
        shiftProdCenterPmDb.setPartCutCount(centerRecordModel.getPartCutCount());
        shiftProdCenterPmDb.setOvertimeNum(centerRecordModel.getOvertimeNum());
        ConvertBean.serviceModelUpdate(shiftProdCenterPmDb,  centerRecordModel.getModifyUser());
        shiftProdCenterPmRepository.save(shiftProdCenterPmDb);
    }

    @Override
    public void doShiftProdCenterStart(ShiftProdCenterRecordModel centerRecordModel) {
        MesShift shiftDb = shiftExtService.getShiftByShiftCodeAndCenterCode(centerRecordModel.getOrganizeCode(), centerRecordModel.getWorkCenterCode(), centerRecordModel.getShiftCode());
        if (null == shiftDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线代码[%s]班次代码[%s]对应的信息不存在", centerRecordModel.getWorkCenterCode(), centerRecordModel.getShiftCode())
                    .build();
        }
        MesWorkCenterExt workCenterDb = getWorkCenter(centerRecordModel.getOrganizeCode(), centerRecordModel.getAreaCode(), centerRecordModel.getWorkCenterCode());
        if (null == workCenterDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("区域代码[%s]生产线代码[%s]对应的信息不存在", centerRecordModel.getAreaCode(), centerRecordModel.getWorkCenterCode())
                    .build();
        }
        //计算作业时间(年月日)
        String workTime = getWorkTime(shiftDb.getStartTime(), shiftDb.getEndTime());

        workCenterDb.setShiftCode(shiftDb.getShiftCode());
        workCenterDb.setWorkerQty(centerRecordModel.getWorkerQty());
        workCenterDb.setWorkTime(workTime);
        ConvertBean.serviceModelUpdate(workCenterDb, centerRecordModel.getModifyUser());
        new ConvertBeanExt(workCenterDb).convertBean(workCenterDb);
        workCenterExtRepository.save(workCenterDb);

        //查询停开机记录表,不存在此维度[作业时间+生产线+班次]数据时,查询产线班次固定作业内容信息,存在则遍历插入停开机记录表,需要冗余班次作业项目信息中的字段
        List<MesShiftProdCenterRecord> shiftProdCenterRecordList = getShiftProdCenterRecordList(
                centerRecordModel.getOrganizeCode(), workTime, centerRecordModel.getWorkCenterCode(), shiftDb.getShiftCode());

        if (CollectionUtils.isEmpty(shiftProdCenterRecordList)) {

            List<MesShiftProdCenter> shiftProdCenterList = getShiftProdCenterList(centerRecordModel.getOrganizeCode(), centerRecordModel.getWorkCenterCode(), shiftDb.getShiftCode());
            if (!CollectionUtils.isEmpty(shiftProdCenterList)) {
                //获取班次作业项目表根据作业内容代码分组的数据
                Map<String, List<MesShiftProd>> prodCodeMap = getProdCodeMap(centerRecordModel.getOrganizeCode(), shiftProdCenterList);
                for (MesShiftProdCenter shiftProdCenter : shiftProdCenterList) {
                    if (null == shiftProdCenter) {
                        continue;
                    }
                    MesShiftProdCenterRecord record = new MesShiftProdCenterRecord();
                    record.setWorkCenterCode(centerRecordModel.getWorkCenterCode());
                    record.setShiftCode(shiftDb.getShiftCode());
                    record.setShiftName(shiftDb.getShiftName());
                    record.setProdCode(shiftProdCenter.getProdCode());
                    List<MesShiftProd> shiftProdList = CollectionUtils.isEmpty(prodCodeMap) ? null : prodCodeMap.get(shiftProdCenter.getProdCode());
                    MesShiftProd shiftProd = CollectionUtils.isEmpty(shiftProdList) ? null : shiftProdList.get(0);
                    if (null != shiftProd) {
                        record.setProdName(shiftProd.getProdName());
                        record.setProdType(shiftProd.getProdType());
                        record.setProdCategory(shiftProd.getProdCategory());
                        record.setIsProdTime(shiftProd.getIsProdTime());
                    }
                    record.setWorkTime(workTime);
                    if (TimeTool.stringParseToDate(shiftProdCenter.getStartTime()).compareTo(TimeTool.stringParseToDate(shiftDb.getStartTime())) < 0) {
                        record.setStartTime(calcDay(workTime, 1) + MesPcnExtConstWords.ONE_SPACE + shiftProdCenter.getStartTime());
                    } else {
                        record.setStartTime(workTime + MesPcnExtConstWords.ONE_SPACE + shiftProdCenter.getStartTime());
                    }
                    if (TimeTool.stringParseToDate(shiftProdCenter.getEndTime()).compareTo(TimeTool.stringParseToDate(shiftDb.getStartTime())) <= 0) {
                        record.setEndTime(calcDay(workTime, 1) + MesPcnExtConstWords.ONE_SPACE + shiftProdCenter.getEndTime());
                    } else {
                        record.setEndTime(workTime + MesPcnExtConstWords.ONE_SPACE + shiftProdCenter.getEndTime());
                    }
                    record.setWorkerQty(centerRecordModel.getWorkerQty());
                    record.setOrganizeCode(centerRecordModel.getOrganizeCode());
                    ConvertBean.serviceModelInitialize(record, centerRecordModel.getModifyUser());
                    shiftProdCenterRecordRepository.insert(record);
                }
            }
        }

        saveProdCenterPm(centerRecordModel, shiftDb, workTime);

    }

    private void saveProdCenterPm(ShiftProdCenterRecordModel centerRecordModel, MesShift shiftDb, String workTime) {

        MesShiftProdCenterPm shiftProdCenterPm = getMesShiftProdCenterPm(centerRecordModel.getOrganizeCode(), centerRecordModel.getWorkCenterCode(), centerRecordModel.getShiftCode(), workTime);

        if (shiftProdCenterPm == null) {
            shiftProdCenterPm = new MesShiftProdCenterPm();
            ConvertBean.serviceModelInitialize(shiftProdCenterPm, centerRecordModel.getModifyUser());
        } else {
            ConvertBean.serviceModelUpdate(shiftProdCenterPm, centerRecordModel.getModifyUser());
        }

        shiftProdCenterPm.setWorkCenterCode(centerRecordModel.getWorkCenterCode());
        shiftProdCenterPm.setStartTime(centerRecordModel.getStartTime());
        shiftProdCenterPm.setShiftCode(shiftDb.getShiftCode());
        shiftProdCenterPm.setShiftName(shiftDb.getShiftName());
        shiftProdCenterPm.setWorkTime(workTime);
        shiftProdCenterPm.setAtHomeNum(centerRecordModel.getAtHomeNum());
        shiftProdCenterPm.setAbsenteeismNum(centerRecordModel.getAbsenteeismNum());
        shiftProdCenterPm.setOvertimeNum(centerRecordModel.getOvertimeNum());
        shiftProdCenterPm.setNewWorkNum(centerRecordModel.getNewWorkNum());
        shiftProdCenterPm.setQuitWorkNum(centerRecordModel.getQuitWorkNum());
        shiftProdCenterPm.setWorkerQty(centerRecordModel.getWorkerQty());
        shiftProdCenterPm.setOrganizeCode(centerRecordModel.getOrganizeCode());

        shiftProdCenterPmRepository.save(shiftProdCenterPm);
    }

    private MesShiftProdCenterPm getMesShiftProdCenterPm(String organizeCode, String workCenterCode, String shiftCode, String workTime) {
        return shiftProdCenterPmRepository.getByProperty(
                    new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,
                            MesPcnExtConstWords.WORK_CENTER_CODE, MesPcnExtConstWords.SHIFT_CODE, MesPcnExtConstWords.WORK_TIME},
                    new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),
                            workCenterCode, shiftCode, workTime});
    }

    private List<MesShiftProdCenter> getShiftProdCenterList(String organizeCode, String workCenterCode, String shiftCode) {
        return shiftProdCenterRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,
                        MesPcnExtConstWords.WORK_CENTER_CODE, MesPcnExtConstWords.SHIFT_CODE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),
                        workCenterCode, shiftCode});
    }

    private Map<String, List<MesShiftProd>> getProdCodeMap(String organizeCode, List<MesShiftProdCenter> shiftProdCenterList) {
        List<String> prodCodeList = (shiftProdCenterList.stream().filter(o -> null != o)
                .map(MesShiftProdCenter::getProdCode).collect(Collectors.toList())).stream().distinct().collect(Collectors.toList());
        List<MesShiftProd> shiftProdList = CollectionUtils.isEmpty(prodCodeList) ? null : getShiftProdListByprodCodeList(organizeCode, prodCodeList);
        return CollectionUtils.isEmpty(shiftProdList) ? null : 
                shiftProdList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesShiftProd::getProdCode));
    }

    private List<MesShiftProd> getShiftProdListByprodCodeList(String organizeCode, List<String> prodCodeList) {
        DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getInPackList(prodCodeList, MesPcnExtConstWords.PROD_CODE, ddlPackBean);
        return shiftProdRepository.findByHqlWhere(ddlPackBean);
    }

    @Override
    public String getWorkTime(String startTime, String endTime) {
        //当前时间(YYYY-MM-dd)
        String currentTimeYmd = TimeTool.getToday();
        //判断当前班次时间是否跨天,结束时间小于等于开始时间即跨天,否则当天
        Boolean isNextDayFlagShift = compareHms(startTime, endTime);
        return !isNextDayFlagShift ?
                currentTimeYmd : //当天:作业时间即为当前年月日
                getWorkTimeForNextDayShift(startTime, endTime, currentTimeYmd); //跨天
    }

    private String getWorkTimeForNextDayShift(String startTime, String endTime, String currentTimeYmd) {
        //跨天
        String currentTimeHms = TimeTool.getNowTime(MesPcnExtConstWords.TIME_FORMAT);
        if (TimeTool.stringParseToDate(currentTimeHms).compareTo(TimeTool.stringParseToDate(startTime)) < 0 &&
                TimeTool.stringParseToDate(currentTimeHms).compareTo(TimeTool.stringParseToDate(endTime)) > 0) {
            //当前时间时分秒小于班次开始时间并且大于班次结束时间时,即班次时间范围外,作业时间即为当前年月日
            return currentTimeYmd;
        } else {
            //当前时间时分秒大于等于班次开始时间或者小于等于班次结束时间时,即班次时间范围内
            if (TimeTool.stringParseToDate(currentTimeHms).compareTo(TimeTool.stringParseToDate(startTime)) >= 0) {
                //当前时间时分秒如果大于等于班次开始时间,作业时间即为当前年月日
                return currentTimeYmd;
            } else {
                //当前时间时分秒如果小于等于班次结束时间,作业时间即为昨天年月日
                return calcDay(currentTimeYmd, -1);
            }
        }
    }

    private Boolean compareHms(String startDate, String endDate) {
        Boolean flag;
        DateFormat sdf = new SimpleDateFormat(MesPcnExtConstWords.TIME_FORMAT);
        try {
            if (sdf.parse(startDate).compareTo(sdf.parse(endDate)) >= 0) {
                flag = true;
            } else {
                flag = false;
            }
        } catch (Exception e) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("时间比较出错")
                    .build();
        }
        return flag;
    }

    private String calcDay(String day, int amount) {
        try {
            DateFormat sdf = new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT);
            return TimeTool.timeCalc(sdf.parse(day), Calendar.DATE, amount, MesPcnExtConstWords.DATE_FORMAT);
        } catch (ParseException e) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("时间计算失败")
                    .build();
        }
    }

    @Override
    public ListPager<ShiftProdModel> queryShiftProdByPager(MesShiftProd shiftProd, Pager pager) {
        DdlPackBean hqlPack = MesPcnExtHqlPack.getShiftProd(shiftProd);
        pager = PagerHelper.getPager(pager, shiftProdRepository.findByHqlWhereCount(hqlPack));
        hqlPack.setOrderByStr(shiftProd.orderBy());
        List<MesShiftProd> shiftProdList = shiftProdRepository.findByHqlWherePage(hqlPack, pager);
        List<ShiftProdModel> modelList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(shiftProdList)) {
            for (MesShiftProd prod : shiftProdList) {
                ShiftProdModel model = new ShiftProdModel();
                BeanUtils.copyProperties(prod, model);
                if (null == prod) {
                    continue;
                }
                model.setProdCategoryName(StringUtils.isEmpty(prod.getProdCategory()) ?
                        null : MesPcnExtEnumUtil.SHIFT_PROD_CATEGORY.valueOfDescription(prod.getProdCategory()));
                model.setProdTypeName(StringUtils.isEmpty(prod.getProdType()) ?
                        null : MesPcnExtEnumUtil.SHIFT_PROD_TYPE.valueOfDescription(prod.getProdType()));
                model.setIsProdTimeName(StringUtils.isEmpty(prod.getIsProdTime()) ?
                        null : MesPcnExtEnumUtil.SHIFT_PROD_IS_PROD_TIME.valueOfDescription(prod.getIsProdTime()));
                modelList.add(model);
            }
        }
        return new ListPager(modelList, pager);
    }

    @Override
    public MesShiftProdCenterRecord insertShiftProdCenterRecord(MesShiftProdCenterRecord record) {
        //校验[开始时间是否小于结束时间]
        ShiftProdCenterRecordModel model = new ShiftProdCenterRecordModel();
        BeanUtils.copyProperties(record, model);
        checkTimeIsValid(model);

        //获取当前选择的班次信息
       /* MesShiftExt shiftExt = getShiftByCenterAndShiftCode(record);

        //校验[开始时间+结束时间] 在班次时间范围内
        checkTimeIsInShiftTime(record, shiftExt);

        //[作业时间+生产线代码+班次代码+作业类型(停机跟生产两个类型)] 校验 [开始时间+结束时间] 重叠
        checkTimeIsOverlap(record);*/

        ConvertBean.serviceModelInitialize(record, record.getModifyUser());
        return shiftProdCenterRecordRepository.insert(record);
    }

    private void checkTimeIsValid(ShiftProdCenterRecordModel record) {
        if (TimeTool.stringParseToDate(record.getStartTime()).compareTo(TimeTool.stringParseToDate(record.getEndTime())) >= 0) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("选择的时间[%s - %s]无效", record.getStartTime(), record.getEndTime())
                    .build();
        }
    }

    private void checkTimeIsOverlap(MesShiftProdCenterRecord record) {
        //获取[作业时间+生产线代码+班次代码+作业类型(停机跟生产两个类型)] 维度的数据
        List<MesShiftProdCenterRecord> shiftProdCenterRecordList = getShiftProdCenterRecordList(record);
        //遍历并判断重叠的情况
        for (MesShiftProdCenterRecord shiftProdCenterRecord : shiftProdCenterRecordList) {
            if (null == shiftProdCenterRecord ||
                    (!StringUtils.isEmpty(record.getId()) && record.getId().compareTo(shiftProdCenterRecord.getId()) == 0)) {
                continue;
            }
            //存在三种时间重叠的情况
            //if 当前 实际开始时间 大于等于db数据的 实际开始时间 并小于db数据的 实际结束时间
            //if 当前 实际结束时间 大于db数据的 实际开始时间 并小于等于db数据的 实际结束时间
            //if 当前 实际开始时间 小于等于db数据的 实际开始时间 并 当前 实际结束时间 大于等于db数据的 实际结束时间
            if ((TimeTool.stringParseToDate(record.getStartTime()).compareTo(TimeTool.stringParseToDate(shiftProdCenterRecord.getStartTime())) >= 0 &&
                    TimeTool.stringParseToDate(record.getStartTime()).compareTo(TimeTool.stringParseToDate(shiftProdCenterRecord.getEndTime())) < 0) ||
                    (TimeTool.stringParseToDate(record.getEndTime()).compareTo(TimeTool.stringParseToDate(shiftProdCenterRecord.getStartTime())) > 0 &&
                            TimeTool.stringParseToDate(record.getEndTime()).compareTo(TimeTool.stringParseToDate(shiftProdCenterRecord.getEndTime())) <= 0) ||
                    (TimeTool.stringParseToDate(record.getStartTime()).compareTo(TimeTool.stringParseToDate(shiftProdCenterRecord.getStartTime())) <= 0 &&
                            TimeTool.stringParseToDate(record.getEndTime()).compareTo(TimeTool.stringParseToDate(shiftProdCenterRecord.getEndTime())) >= 0)) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("选择的时间[%s - %s]与已存在的数据存在时间重叠",
                                record.getStartTime(), record.getEndTime())
                        .build();
            }
        }
    }

    private List<MesShiftProdCenterRecord> getShiftProdCenterRecordList(MesShiftProdCenterRecord record) {
        //获取作业类型的大类，停机或生产
        List<Integer> prodTypeList = getProdTypeList(record.getProdType());
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(record.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(record.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(record.getShiftCode(), MesPcnExtConstWords.SHIFT_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(record.getWorkTime(), MesPcnExtConstWords.WORK_TIME, packBean);
        List<MesShiftProdCenterRecord> shiftProdCenterRecordList = shiftProdCenterRecordRepository.findByHqlWhere(packBean);
        if (!CollectionUtils.isEmpty(shiftProdCenterRecordList)) {
            List<String> prodCodeList = (shiftProdCenterRecordList.stream().filter(o -> null != o)
                    .map(MesShiftProdCenterRecord::getProdCode).collect(Collectors.toList())).stream().distinct().collect(Collectors.toList());
            List<MesShiftProd> shiftProdList = CollectionUtils.isEmpty(prodCodeList) ? null : getShiftProdList(record.getOrganizeCode(), prodCodeList, prodTypeList);
            if (!CollectionUtils.isEmpty(shiftProdList)) {
                prodCodeList = (shiftProdList.stream().filter(o -> null != o)
                        .map(MesShiftProd::getProdCode).collect(Collectors.toList())).stream().distinct().collect(Collectors.toList());
            }
            List<String> finalProdCodeList = prodCodeList;
            shiftProdCenterRecordList = shiftProdCenterRecordList.stream()
                    .filter(o -> (null != o && !CollectionUtils.isEmpty(finalProdCodeList) && finalProdCodeList.contains(o.getProdCode()))).collect(Collectors.toList());
        }
        return shiftProdCenterRecordList;
    }

    private List<MesShiftProd> getShiftProdList(String organizeCode, List<String> prodCodeList, List<Integer> prodTypeList) {
        DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getInPackList(prodCodeList, MesPcnExtConstWords.PROD_CODE, ddlPackBean);
        DdlPreparedPack.getInPackList(prodTypeList, MesPcnExtConstWords.PROD_TYPE, ddlPackBean);
        return shiftProdRepository.findByHqlWhere(ddlPackBean);
    }

    private List<Integer> getProdTypeList(Integer prodType) {
        List<Integer> prodTypeList = new ArrayList<>();
        if (MesPcnExtEnumUtil.SHIFT_PROD_TYPE.NORMAL_STOP_CENTER.getValue() == prodType ||
                MesPcnExtEnumUtil.SHIFT_PROD_TYPE.UNNORMAL_STOP_CENTER.getValue() == prodType) {
            prodTypeList.add(MesPcnExtEnumUtil.SHIFT_PROD_TYPE.NORMAL_STOP_CENTER.getValue());
            prodTypeList.add(MesPcnExtEnumUtil.SHIFT_PROD_TYPE.UNNORMAL_STOP_CENTER.getValue());
        } else {
            prodTypeList.add(MesPcnExtEnumUtil.SHIFT_PROD_TYPE.NORMAL_PROD.getValue());
            prodTypeList.add(MesPcnExtEnumUtil.SHIFT_PROD_TYPE.UNNORMAL_PROD.getValue());
        }
        return prodTypeList;
    }

    private void checkTimeIsInShiftTime(MesShiftProdCenterRecord record, MesShiftExt shiftExt) {
        //当前时间(YYYY-MM-dd)
        String currentTimeYmd = record.getWorkTime();
        //判断当前班次时间是否跨天,结束时间小于等于开始时间即跨天,否则当天
        Boolean isNextDayFlagShift = compareHms(shiftExt.getStartTime(), shiftExt.getEndTime());
        //班次实际开始时间(YYYY-MM-dd HH:mm:ss) [当前年月日 + 班次开始时间]
        String shiftStartYmdHms = currentTimeYmd + MesPcnExtConstWords.ONE_SPACE + shiftExt.getStartTime();
        //班次实际结束时间(YYYY-MM-dd HH:mm:ss) [if 当天: 当前年月日 + 班次结束时间][else : 明天年月 + 班次结束时间]
        String shiftEndYmdHms = getEndDateByFlag(isNextDayFlagShift, currentTimeYmd, shiftExt.getEndTime());

        //判断是否在班次时间范围内 [当前 实际开始时间 小于 班次的 实际开始时间 或者 当前 实际结束时间 大于 班次的 实际结束时间]
        if (TimeTool.stringParseToDate(record.getStartTime()).compareTo(TimeTool.stringParseToDate(shiftStartYmdHms)) < 0 ||
                TimeTool.stringParseToDate(record.getEndTime()).compareTo(TimeTool.stringParseToDate(shiftEndYmdHms)) > 0) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("选择的时间[%s - %s]不在班次时间[%s - %s]的范围内",
                            record.getStartTime(), record.getEndTime(), shiftStartYmdHms, shiftEndYmdHms)
                    .build();
        }
    }

    private String getEndDateByFlag(Boolean isNextDayFlag, String currentTimeYmd, String endTime) {
        return !isNextDayFlag ? (currentTimeYmd + MesPcnExtConstWords.ONE_SPACE + endTime) :
                (calcDay(currentTimeYmd, 1) + MesPcnExtConstWords.ONE_SPACE + endTime);
    }

    private MesShiftExt getShiftByCenterAndShiftCode(MesShiftProdCenterRecord record) {
        MesShiftExt shiftExt = shiftExtService.getShiftExtByShiftCodeAndCenterCode(record.getOrganizeCode(), record.getWorkCenterCode(), record.getShiftCode());
        if (null == shiftExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("生产线代码[%s]班次代码[%s]记录不存在", record.getShiftCode(), record.getWorkCenterCode())
                    .build();
        }
        return shiftExt;
    }

    @Override
    public void updateShiftProdCenterRecord(ShiftProdCenterRecordModel record) {

        //校验[开始时间是否小于结束时间]
        checkTimeIsValid(record);

        if (MesPcnExtEnumUtil.SHIFT_PROD_TYPE.START_OR_END_SHIFT_TIME.getValue() == record.getProdType()) {
            MesShiftProdCenterPm shiftProdCenterPmDb = shiftProdCenterPmRepository.getById(record.getId());

            if (CommonEnumUtil.IS_VAILD.INVAILD.getValue() == shiftProdCenterPmDb.getIsValid()) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("ID[%s]记录已被禁用,不能修改", record.getId())
                        .build();
            }

            shiftProdCenterPmDb.setStartTime(record.getStartTime());
            shiftProdCenterPmDb.setEndTime(record.getEndTime());
            shiftProdCenterPmDb.setWorkerQty(record.getWorkerQty());
            shiftProdCenterPmDb.setMemo(record.getMemo());
            ConvertBean.serviceModelUpdate(shiftProdCenterPmDb, record.getModifyUser());
            shiftProdCenterPmRepository.save(shiftProdCenterPmDb);
        } else {
            MesShiftProdCenterRecord shiftProdCenterRecordDb = getShiftProdCenterRecordById(record.getId());
            if (CommonEnumUtil.IS_VAILD.INVAILD.getValue() == shiftProdCenterRecordDb.getIsValid()) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("ID[%s]记录已被禁用,不能修改", record.getId())
                        .build();
            }

            shiftProdCenterRecordDb.setStartTime(record.getStartTime());
            shiftProdCenterRecordDb.setEndTime(record.getEndTime());
            shiftProdCenterRecordDb.setWorkerQty(record.getWorkerQty());
            shiftProdCenterRecordDb.setMemo(record.getMemo());
            ConvertBean.serviceModelUpdate(shiftProdCenterRecordDb, record.getModifyUser());
            shiftProdCenterRecordRepository.save(shiftProdCenterRecordDb);
        }

        //获取当前选择的班次信息
//        MesShiftExt shiftExt = getShiftByCenterAndShiftCode(record);
//
//        if (!shiftProdCenterRecordDb.getStartTime().equals(record.getStartTime()) ||
//                !shiftProdCenterRecordDb.getEndTime().equals(record.getEndTime())) {
//            //校验[开始时间+结束时间] 在班次时间范围内
//            checkTimeIsInShiftTime(record, shiftExt);
//
//            //[作业时间+生产线代码+班次代码+作业类型(停机跟生产两个类型)] 校验 [开始时间+结束时间] 重叠
//            checkTimeIsOverlap(record);
//        }


    }

    private MesShiftProdCenterRecord getShiftProdCenterRecordById(Long id) {
        return shiftProdCenterRecordRepository.getById(id);
    }

    @Override
    public int deleteShiftProdCenterRecodeById(Long id, String modifyUser) {

        MesShiftProdCenterRecord shiftProdCenterRecordById = shiftProdCenterRecordRepository.getById(id);

        if (shiftProdCenterRecordById == null) {
            MesShiftProdCenterPm shiftProdCenterPmDb = shiftProdCenterPmRepository.getById(id);

            if (shiftProdCenterPmDb != null) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("[%s]类型停开机记录不能删除", MesPcnExtEnumUtil.SHIFT_PROD_TYPE.START_OR_END_SHIFT_TIME.getDescription())
                        .build();
            }

        } else {
            shiftProdCenterRecordById.setIsDeleted(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
            ConvertBean.serviceModelUpdate(shiftProdCenterRecordById, modifyUser);
            shiftProdCenterRecordRepository.save(shiftProdCenterRecordById);
        }

        return 1;
    }
}
