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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.aspect.MonitorLog;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
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.MesProduceSn;
import cn.estsh.i3plus.pojo.mes.bean.MesProductionRecord;
import cn.estsh.i3plus.pojo.mes.bean.MesQueueOrder;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.repository.MesProduceSnRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesQueueOrderRepository;
import lombok.extern.slf4j.Slf4j;
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.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MesProduceSnExtService implements IMesProduceSnExtService {

    @Autowired
    private MesProduceSnRepository produceSnRepository;

    @Autowired
    private MesQueueOrderRepository queueOrderRepository;

    @Override
    public MesProduceSn getProduceSnForBox(String produceSn, String partNo,String organizeCode) {
        DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(produceSn,"productSn",ddlPackBean);
        DdlPreparedPack.getStringEqualPack(partNo,"partNo",ddlPackBean);
        List<MesProduceSn> produceSnList = produceSnRepository.findByHqlWhere(ddlPackBean);
        return produceSnList.isEmpty() ? null : produceSnList.get(0);
    }

    //根据零件条码查询零件条码信息
    @Override
    public List<MesProduceSn> getProduceSnList(String organizeCode, List<String> productSnList) {

        if (StringUtils.isEmpty(organizeCode) || CollectionUtils.isEmpty(productSnList)) return null;

        productSnList = productSnList.size() == 1 ? productSnList : productSnList.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        if (productSnList.size() == 1) DdlPreparedPack.getStringEqualPack(productSnList.get(0), MesPcnExtConstWords.PRODUCT_SN, packBean);
        else DdlPreparedPack.getInPackList(productSnList, MesPcnExtConstWords.PRODUCT_SN, packBean);

        return produceSnRepository.findByHqlWhere(packBean);
    }

    //根据零件条码查询零件条码信息
    @Override
    public List<MesProduceSn> getProduceSnList(String organizeCode, String productSn) {

        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(productSn)) return null;

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(productSn, MesPcnExtConstWords.PRODUCT_SN, packBean);
        List<MesProduceSn> snList = produceSnRepository.findByHqlWhere(packBean);
        if (CollectionUtils.isEmpty(snList)) {
            DdlPackBean packCustSnBean = DdlPackBean.getDdlPackBean(organizeCode);
            DdlPreparedPack.getStringEqualPack(productSn, MesPcnExtConstWords.CUST_SN, packCustSnBean);
            snList = produceSnRepository.findByHqlWhere(packCustSnBean);
        }
        return snList;
    }

    //根据零件条码查询零件条码信息, 创建时间倒序
    @Override
    public List<MesProduceSn> getProduceSnListCreateDatetimeDesc(String organizeCode, String productSn) {
        List<MesProduceSn> produceSnList = getProduceSnList(organizeCode, productSn);
        if (CollectionUtils.isEmpty(produceSnList)) return produceSnList;
        return produceSnList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesProduceSn::getCreateDatetime).reversed()).collect(Collectors.toList());
    }

    //根据产品条码查询零件条码信息[非排序],创建时间最新
    @Override
    public MesProduceSn getProduceSnCreateDatetimeDesc(String organizeCode, String productSn) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(productSn)) return null;
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(productSn, MesPcnExtConstWords.PRODUCT_SN, packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.DESC.getValue()}, new String[]{MesPcnExtConstWords.CREATE_DATE_TIME}, packBean);
        return produceSnRepository.getByProperty(packBean);
    }

    //根据客户条码查询零件条码信息[排序]
    @Override
    public MesProduceSn getProduceSnByCustSn(String organizeCode, String custSn) {

        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(custSn)) return null;

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(custSn, MesPcnExtConstWords.CUST_SN, packBean);

        return produceSnRepository.getByProperty(packBean);
    }

    //根据产品条码查询零件条码信息[排序]
    @Override
    public MesProduceSn getProduceSn(String organizeCode, String productSn, String workOrderNo) {

        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(productSn)) return null;

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(productSn, MesPcnExtConstWords.PRODUCT_SN, packBean);
        DdlPreparedPack.getStringEqualPack(workOrderNo, MesPcnExtConstWords.WORK_ORDER_NO, packBean);

        return produceSnRepository.getByProperty(packBean);
    }

    //根据零件条码ID查询零件条码信息
    @Override
    public MesProduceSn getProduceSn(String organizeCode, Long id) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(id)) return null;
        return produceSnRepository.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(), id});
    }

    //根据零件条码查询零件条码信息
    @Override
    public Map<String, List<MesProduceSn>> getProduceSnMap(String organizeCode, List<String> productSnList) {

        List<MesProduceSn> produceSnList = getProduceSnList(organizeCode, productSnList);
        //先排序再分组
        return CollectionUtils.isEmpty(produceSnList) ? null : produceSnList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesProduceSn::getProductSn));

    }

    @Override
    public List<MesProduceSn> findProduceSnByCustSn(String organizeCode, List<String> custSnList) {
        if (StringUtils.isEmpty(organizeCode) || CollectionUtils.isEmpty(custSnList)) return null;

        custSnList = custSnList.size() == MesPcnExtConstWords.ONE ? custSnList : custSnList.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        if (custSnList.size() == MesPcnExtConstWords.ONE) {
            DdlPreparedPack.getStringEqualPack(custSnList.get(MesPcnExtConstWords.ZERO), MesPcnExtConstWords.CUST_SN, packBean);
        } else {
            DdlPreparedPack.getInPackList(custSnList, MesPcnExtConstWords.CUST_SN, packBean);
        }

        return produceSnRepository.findByHqlWhere(packBean);
    }

    @Override
    public Map<String, List<MesProduceSn>> getProduceSnByCustSnMap(String organizeCode, List<String> custSnList) {
        List<MesProduceSn> produceSnList = findProduceSnByCustSn(organizeCode, custSnList);
        if(CollectionUtils.isEmpty(produceSnList)) return null;
        //先排序再分组
        produceSnList = produceSnList.stream().sorted(Comparator.comparing(MesProduceSn::getCreateDatetime).reversed()).collect(Collectors.toList());
        return produceSnList.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(MesProduceSn::getCustSn));
    }

    //根据生产工单,生产线,工位查询工位队列信息
    @Override
    public List<MesQueueOrder> getQueueOrderList(String organizeCode, String workCenterCode, String workCellCode, String workOrderNo) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(workOrderNo)) return null;
        return queueOrderRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_CENTER_CODE, MesPcnExtConstWords.WORK_CELL_CODE, MesPcnExtConstWords.WORK_ORDER_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workCenterCode, workCellCode, workOrderNo});
    }

    //根据零件条码,生产线,工位查询工位队列信息
    @Override
    public List<MesQueueOrder> getQueueOrderList(String organizeCode, String workCenterCode, String workCellCode, List<String> productSnList) {

        if (StringUtils.isEmpty(organizeCode) || CollectionUtils.isEmpty(productSnList)) return null;

        productSnList = productSnList.size() == 1 ? productSnList : productSnList.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(workCenterCode, MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(workCellCode, MesPcnExtConstWords.WORK_CELL_CODE, packBean);
        if (productSnList.size() == 1) DdlPreparedPack.getStringEqualPack(productSnList.get(0), MesPcnExtConstWords.PRODUCT_SN, packBean);
        else DdlPreparedPack.getInPackList(productSnList, MesPcnExtConstWords.PRODUCT_SN, packBean);

        return queueOrderRepository.findByHqlWhere(packBean);
    }

    //根据零件条码,生产线,工位查询工位队列信息
    @Override
    public MesQueueOrder getQueueOrder(String organizeCode, String workCenterCode, String workCellCode, String productSn) {

        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(productSn)) return null;

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(workCenterCode, MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(workCellCode, MesPcnExtConstWords.WORK_CELL_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(productSn, MesPcnExtConstWords.PRODUCT_SN, packBean);

        return queueOrderRepository.getByProperty(packBean);
    }

    //根据零件条码,生产线,工位查询工位队列信息
    @Override
    public Map<String, List<MesQueueOrder>> getQueueOrderMap(String organizeCode, String workCenterCode, String workCellCode, List<String> productSnList) {
        //根据零件条码,生产线,工位查询工位队列信息
        List<MesQueueOrder> queueOrderList = getQueueOrderList(organizeCode, workCenterCode, workCellCode, productSnList);
        //先排序再分组
        return CollectionUtils.isEmpty(queueOrderList) ? null : queueOrderList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesQueueOrder::getProductSn));
    }

    private List<MesProduceSn> distinctProduceSnList(List<MesProduceSn> produceSnDataList) {
        return CollectionUtils.isEmpty(produceSnDataList) ? null :
                produceSnDataList.stream().filter(o -> null != o).distinct().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(MesProduceSn::getProductSn))), ArrayList::new));
    }

    @Override
    public void saveProduceSnList(StationRequestBean reqBean, Integer snStatus, List<Long> idList) {
        idList = CollectionUtils.isEmpty(idList) ? idList : idList.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(idList)) return;
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        if (idList.size() == 1) DdlPreparedPack.getNumEqualPack(idList.get(0), MesPcnExtConstWords.ID, packBean);
        else DdlPreparedPack.getInPackList(idList, MesPcnExtConstWords.ID, packBean);
        produceSnRepository.updateByPropertiesNoSync(
                new String[]{MesPcnExtConstWords.WORK_CENTER_CODE, MesPcnExtConstWords.WORK_CELL_CODE, MesPcnExtConstWords.SN_STATUS,
                        MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS, MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME},
                new Object[]{reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), snStatus,
                        reqBean.getUserInfo(), TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtConstWords.EMPTY},
                packBean);

    }

    @Override
    public void saveProduceSnStatusByDdlPackBean(DdlPackBean packBean, String userInfo, Integer snStatus) {
        if (StringUtils.isEmpty(userInfo) || StringUtils.isEmpty(snStatus)) return;
        produceSnRepository.updateByPropertiesNoSync(
                new String[]{MesPcnExtConstWords.SN_STATUS, MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS, MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME},
                new Object[]{snStatus, userInfo, TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtConstWords.EMPTY},
                packBean);
    }

    @Override
    @MonitorLog
    public MesProduceSn insert(MesProduceSn item) {
        return produceSnRepository.insert(item);
    }

    @Override
    @MonitorLog
    public void update(MesProduceSn item) {
        produceSnRepository.update(item);
    }

    @Override
    @MonitorLog
    public void updateNoSync(MesProduceSn item) {
        produceSnRepository.updateNoSync(item);
    }

    @Override
    public ListPager<MesProduceSn> queryMesProduceSn(MesProduceSn mesProduceSn, Pager pager) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(mesProduceSn.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(mesProduceSn.getWorkOrderNo(),"workOrderNo",packBean);
        DdlPreparedPack.getStringEqualPack(mesProduceSn.getPartNo(),"partNo",packBean);
        DdlPreparedPack.getStringEqualPack(mesProduceSn.getPartName(),"partName",packBean);
        pager = PagerHelper.getPager(pager, produceSnRepository.findByHqlWhereCount(packBean));
        List<MesProduceSn> resultList = produceSnRepository.findByHqlWherePage(packBean, pager);
        return new ListPager<>(resultList, pager);
    }

    @Override
    public String queryPartNoByProduceSn(String productSn, String organizeCode) {
        MesProduceSn produceSn = getProduceSnCreateDatetimeDesc(organizeCode, productSn);
        return null == produceSn ? "" : produceSn.getPartNo();
    }
}
