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

import cn.estsh.i3plus.ext.mes.api.busi.bu3.ISxUnbindProduceSnService;
import cn.estsh.i3plus.ext.mes.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pojo.repository.*;
import cn.estsh.i3plus.ext.mes.pojo.sqlpack.MesExtHqlPack;
import cn.estsh.i3plus.ext.mes.pojo.util.ConvertBeanExt;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtConstWords;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtEnumUtil;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
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.MesPackageDetail;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.i3plus.pojo.mes.repository.MesPackageDetailRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesWorkOrderRepository;
import cn.estsh.impp.framework.boot.auth.AuthUtil;
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @PROJECT_NAME: i3plus-mes-panasonic-dev
 * @DESCRIPTION:
 * @USER: xinwang.yi
 * @DATE: 2023-07-04 17:49
 */
@Service
@Slf4j
public class SxUnbindProduceSnService implements ISxUnbindProduceSnService {

    @Autowired
    private MesWorkOrderRepository workOrderRepository;

    @Autowired
    private MesProduceSnExtRepository produceSnExtRepository;

    @Autowired
    private MesPackageExtRepository packageExtRepository;

    @Autowired
    private MesPackageDetailRepository packageDetailRepository;

    @Autowired
    private MesProdBindRecordExtRepository prodBindRecordExtRepository;

    @Autowired
    private MesUnbindProduceSnRepository unbindProduceSnRepository;

    @Autowired
    private MesUnbindProduceSnTravelRepository unbindProduceSnTravelRepository;

    @Override
    public void doUnbindProduceSn(String organizeCode, String userName, String nowTime, Integer woStatus, List<String> workOrderNoList) {
        if (woStatus == MesExtEnumUtil.WORK_ORDER_STATUS.CLOSE.getValue() && woStatus == MesExtEnumUtil.WORK_ORDER_STATUS.REMOVE.getValue()) {
            List<MesWorkOrder> workOrderList = getMesWorkOrders(organizeCode, workOrderNoList);
            if (!CollectionUtils.isEmpty(workOrderList)) {
                for (MesWorkOrder workOrder : workOrderList) {
                    List<MesProduceSnExt> produceSnExtList = getMesProduceSnExts(organizeCode, workOrder.getOrderNo());

                    // 获取未下线条码
                    produceSnExtList = produceSnExtList.stream().filter(o -> StringUtils.isEmpty(o.getOutWorkCenterTime())).collect(Collectors.toList());

                    if (!CollectionUtils.isEmpty(produceSnExtList)) {
                        List<String> serialNumberList = produceSnExtList.stream().map(MesProduceSnExt::getSerialNumber).collect(Collectors.toList());
                        Map<String, MesProduceSnExt> produceSnExtBySnMap = produceSnExtList.stream().collect(Collectors.toMap(MesProduceSnExt::getSerialNumber, Function.identity(), (x, y) -> y));

                        // 删除包装条码 和 包装明细
                        deletePackage(organizeCode, userName, serialNumberList);

                        // 清空关键件
                        clearProdBindRecord(organizeCode, workOrder.getOrderNo(), nowTime, serialNumberList);

                        // 解绑产品条码
                        unbindProduceSn(userName, nowTime, produceSnExtList);

                        // 放入待绑定条码表 已绑定便进行解绑
                        saveUnBindProduceSn(organizeCode, userName, workOrder, serialNumberList, produceSnExtBySnMap);

                        // 记录解绑条码履历
                        insertUnBindProduceSnRecord(produceSnExtList);

                    }
                }
            }
        }
    }

    @Override
    public List<MesUnbindProduceSn> queryUnbindProduceSn(MesUnbindProduceSn unbindProduceSn) {
        DdlPackBean hqlPack = MesExtHqlPack.getUnbindProduceSn(unbindProduceSn);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.ASC.getValue()}, new String[]{MesExtConstWords.MODIFY_DATE_TIME}, hqlPack);
        //pager = PagerHelper.getPager(pager, unbindProduceSnRepository.findByHqlWhereCount(hqlPack));
        return unbindProduceSnRepository.findByHqlWhere(hqlPack);
    }

    @Override
    public ListPager<MesUnbindProduceSnTravel> queryUnbindProduceSnTravelByPager(MesUnbindProduceSnTravel unbindProduceSnTravel, Pager pager) {
        DdlPackBean hqlPack = MesExtHqlPack.getUnbindProduceSnTravel(unbindProduceSnTravel);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.DESC.getValue()}, new String[]{MesExtConstWords.MODIFY_DATE_TIME}, hqlPack);
        pager = PagerHelper.getPager(pager, unbindProduceSnTravelRepository.findByHqlWhereCount(hqlPack));
        return new ListPager(unbindProduceSnTravelRepository.findByHqlWherePage(hqlPack , pager), pager);
    }

    @Override
    public List<MesUnbindProduceSn> queryUnbindProduceSnBySn(List<String> produceSnList, String organizeCode) {
        if (CollectionUtils.isEmpty(produceSnList)) return null;
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getInPackList(produceSnList, MesExtConstWords.SERIAL_NUMBER, packBean);
        return unbindProduceSnRepository.findByHqlWhere(packBean);
    }

    @Override
    public Map<String, MesUnbindProduceSn> queryUnbindProduceSnBySnMap(List<String> produceSnList, String organizeCode) {
        List<MesUnbindProduceSn> unbindProduceSns = queryUnbindProduceSnBySn(produceSnList, organizeCode);
        if (CollectionUtils.isEmpty(unbindProduceSns)) return null;
        return unbindProduceSns.stream().collect(Collectors.toMap(MesUnbindProduceSn::getSerialNumber, Function.identity(), (x,y) -> y));
    }

    private void saveUnBindProduceSn(String organizeCode, String userName, MesWorkOrder workOrder, List<String> serialNumberList, Map<String, MesProduceSnExt> produceSnExtBySnMap) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getInPackList(serialNumberList, MesExtConstWords.SERIAL_NUMBER, packBean);
        List<MesUnbindProduceSn> unBindProduceSnDbList = unbindProduceSnRepository.findByHqlWhere(packBean);
        Map<String, MesUnbindProduceSn> MesUnbindProduceSnBySnMap = CollectionUtils.isEmpty(unBindProduceSnDbList) ? new HashMap<>(0) :
                unBindProduceSnDbList.stream().collect(Collectors.toMap(MesUnbindProduceSn::getSerialNumber, Function.identity(), (x, y) -> y));

        List<MesUnbindProduceSn> saveUnbindProduceSnList = new ArrayList<>();
        for (String serialNumber : serialNumberList) {
            MesProduceSnExt produceSnExtDb = produceSnExtBySnMap.get(serialNumber);
            if (MesUnbindProduceSnBySnMap.containsKey(serialNumber)) {
                MesUnbindProduceSn MesUnbindProduceSn = MesUnbindProduceSnBySnMap.get(serialNumber);
                MesUnbindProduceSn.setBindStatus(MesExtEnumUtil.PACKAGE_BIND_STATUS.UNBIND.getValue());
                ConvertBean.serviceModelUpdate(MesUnbindProduceSn, userName);
                saveUnbindProduceSnList.add(MesUnbindProduceSn);
            } else {
                MesUnbindProduceSn unBindProduceSn = new MesUnbindProduceSn();
                unBindProduceSn.setPartNo(produceSnExtDb.getPartNo());
                unBindProduceSn.setPartNameRdd(produceSnExtDb.getPartNameRdd());
                unBindProduceSn.setSerialNumber(produceSnExtDb.getSerialNumber());
                unBindProduceSn.setStartTime(workOrder.getStartTime());
                unBindProduceSn.setBindStatus(MesExtEnumUtil.PACKAGE_BIND_STATUS.UNBIND.getValue());
                ConvertBean.serviceModelInitialize(unBindProduceSn, userName);
                saveUnbindProduceSnList.add(unBindProduceSn);
            }
        }

        unbindProduceSnRepository.saveAll(saveUnbindProduceSnList);
    }

    private void insertUnBindProduceSnRecord(List<MesProduceSnExt> produceSnExtList) {
        List<MesUnbindProduceSnTravel> unBindProduceSnTravelList = new ArrayList<>();
        for (MesProduceSnExt produceSnExt : produceSnExtList) {
            MesUnbindProduceSnTravel unBindProduceSnTravel = new MesUnbindProduceSnTravel();
            BeanUtils.copyProperties(produceSnExt, unBindProduceSnTravel, MesExtConstWords.ID, MesExtConstWords.CREATE_USER, MesExtConstWords.CREATE_DATE_TIME, MesExtConstWords.MODIFY_USER, MesExtConstWords.MODIFY_DATE_TIME);
            unBindProduceSnTravelList.add(unBindProduceSnTravel);
        }
        unbindProduceSnTravelRepository.saveAll(unBindProduceSnTravelList);
    }

    private List<MesProduceSnExt> getMesProduceSnExts(String organizeCode, String orderNo) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(orderNo, MesExtConstWords.WORK_ORDER_NO, packBean);
        return produceSnExtRepository.findByHqlWhere(packBean);
    }

    private void unbindProduceSn(String userName, String nowTime, List<MesProduceSnExt> produceSnExtList) {
        for (MesProduceSnExt o : produceSnExtList) {
            o.setWorkOrderNo("");
            o.setWorkTime("");
            o.setShiftCode("");
            o.setLastWorkOrderNo("");
            o.setProcessCode("");
            o.setNextProcessCode("");
            o.setModifyUser(userName);
            o.setModifyDatetime(nowTime);
            o.setSystemSyncStatus(MesExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            new ConvertBeanExt(o);
        }
        produceSnExtRepository.saveAll(produceSnExtList);
    }

    private void clearProdBindRecord(String organizeCode, String orderNo, String nowTime, List<String> serialNumberList) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(orderNo, MesExtConstWords.WORK_ORDER_NO, packBean);
        DdlPreparedPack.getInPackList(serialNumberList, MesExtConstWords.SERIAL_NUMBER, packBean);
        List<MesProdBindRecordExt> prodBindRecordExtList = prodBindRecordExtRepository.findByHqlWhere(packBean);
        prodBindRecordExtList.forEach(o -> {
            o.setIsDeletedExt(MesExtEnumUtil.IS_VAILD.VAILD.getValue());
            o.setIsValidExt(MesExtEnumUtil.IS_VAILD.INVAILD.getValue());
            o.setModifyDatetimeExt(nowTime);
            o.setModifyDatetime(nowTime);
            o.setModifyUser(AuthUtil.getSessionUser().getUserName());
            o.setModifyUserExt(AuthUtil.getSessionUser().getUserName());
        });

        prodBindRecordExtRepository.saveAll(prodBindRecordExtList);
    }

    private void deletePackage(String organizeCode, String userName, List<String> serialNumberList) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getInPackList(serialNumberList, MesExtConstWords.SERIAL_NUMBER, packBean);
        List<MesPackageDetail> packageDetailList = packageDetailRepository.findByHqlWhere(packBean);
        List<String> packageNoList = packageDetailList.stream().map(MesPackageDetail::getPackageNo).distinct().collect(Collectors.toList());

        packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getInPackList(packageNoList, MesExtConstWords.PACKAGENO, packBean);
        List<MesPackageExt> packageExtList = packageExtRepository.findByHqlWhere(packBean);
        packageExtList.forEach(o -> {
            o.setIsValid(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
            o.setIsDeleted(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
            ConvertBean.serviceModelUpdate(o, userName);
            new ConvertBeanExt(o);
        });

        packageDetailList.forEach(o -> {
            o.setIsValid(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
            o.setIsDeleted(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
            ConvertBean.serviceModelUpdate(o, userName);
            new ConvertBeanExt(o);
        });

        packageExtRepository.saveAll(packageExtList);
        packageDetailRepository.saveAll(packageDetailList);
    }

    private List<MesWorkOrder> getMesWorkOrders(String organizeCode, List<String> workOrderNoList) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getInPackList(workOrderNoList, MesExtConstWords.ORDER_NO, packBean);
        return workOrderRepository.findByHqlWhere(packBean);
    }
}
