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

import cn.estsh.i3plus.ext.mes.pcn.api.base.IMesEquipmentExtService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesCellEquipContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesEquipSpotCheckContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.*;
import cn.estsh.i3plus.pojo.mes.repository.*;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
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.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MesEquipmentExtService implements IMesEquipmentExtService {

    @Autowired
    private MesWcEquipmentRepository wcEquipmentRepository;

    @Autowired
    private MesEquipmentRepository equipmentRepository;

    @Autowired
    private MesEquipmentVariableRepository equipmentVariableRepository;

    @Autowired
    private MesEquipmentVariableCfgRepository equipmentVariableCfgRepository;

    @Autowired
    private MesEquipmentChannelRepository equipmentChannelRepository;

    @Autowired
    private MesEquipmentSpotCheckRepository equipmentSpotCheckRepository;

    @Autowired
    private MesEquipmentSpotCheckPartRepository equipmentSpotCheckPartRepository;

    @Autowired
    private MesEquipmentSpotCheckDetailRepository equipmentSpotCheckDetailRepository;

    @Autowired
    private MesProdRuleIgnoreCfgRepository prodRuleIgnoreCfgRepository;

    @Override
    public List<MesCellEquipContext> getCellEquipmentList(String organizeCode, String workCenterCode, String workCellCode) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(workCenterCode) || StringUtils.isEmpty(workCellCode)) return null;
        List<MesWcEquipment> wcEquipmentDbList = getWcEquipmentList(organizeCode, workCenterCode, workCellCode);
        if (CollectionUtils.isEmpty(wcEquipmentDbList)) return null;
        List<MesCellEquipContext> cellEquipmentContextList = null;
        for (MesWcEquipment wcEquipmentDb : wcEquipmentDbList) {
            if (null == wcEquipmentDb) continue;
            MesEquipment equipmentDb = equipmentRepository.getByProperty(
                    new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.EQUIPMENT_CODE},
                    new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), wcEquipmentDb.getEquipmentCode()});
            if (null == equipmentDb) continue;
            if (CollectionUtils.isEmpty(cellEquipmentContextList)) cellEquipmentContextList = new ArrayList<>();
            MesCellEquipContext cellEquipmentContext = new MesCellEquipContext();
            BeanUtils.copyProperties(wcEquipmentDb, cellEquipmentContext);
            BeanUtils.copyProperties(equipmentDb, cellEquipmentContext);
            cellEquipmentContextList.add(cellEquipmentContext);
        }
        return cellEquipmentContextList;
    }

    @Override
    public List<MesWcEquipment> getWcEquipmentList(String organizeCode, String workCenterCode, String workCellCode) {
        return wcEquipmentRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_CENTER_CODE, MesPcnExtConstWords.WORK_CELL_CODE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workCenterCode, workCellCode});
    }

    @Override
    public MesWcEquipment getWcEquipment(String organizeCode, String workCenterCode, String workCellCode) {
        List<MesWcEquipment> wcEquipmentDbList = getWcEquipmentList(organizeCode, workCenterCode, workCellCode);
        if (CollectionUtils.isEmpty(wcEquipmentDbList)) return null;
        if (wcEquipmentDbList.size() == 1) return wcEquipmentDbList.get(0);
        List<MesWcEquipment> wcEquipmentDbListSort = wcEquipmentDbList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getSeq()))).sorted(Comparator.comparing(MesWcEquipment::getSeq)).collect(Collectors.toList());
        return !CollectionUtils.isEmpty(wcEquipmentDbListSort) ? wcEquipmentDbListSort.get(0) : wcEquipmentDbList.get(0);
    }

    @Override
    public List<MesEquipmentVariableCfg> getEquipmentVariableCfgList(String organizeCode, String variableCfgType) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(variableCfgType)) return null;
        return equipmentVariableCfgRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.VARIABLE_CFG_TYPE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), variableCfgType});
    }

    @Override
    public List<MesEquipmentVariable> getEquipmentVariableList(String organizeCode, String equipmentCode, Integer variableType) {
        if (StringUtils.isEmpty(variableType) || StringUtils.isEmpty(equipmentCode) || StringUtils.isEmpty(variableType)) return null;
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(equipmentCode, MesPcnExtConstWords.EQUIPMENT_CODE, packBean);
        DdlPreparedPack.getNumEqualPack(variableType, MesPcnExtConstWords.VARIABLE_TYPE, packBean);
        return equipmentVariableRepository.findByHqlWhere(packBean);
    }

    @Override
    public List<MesEquipmentChannel> getEquipmentChannelList(String organizeCode, String equipmentCode) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipmentCode)) return null;
        return equipmentChannelRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.EQUIPMENT_CODE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), equipmentCode});
    }

    @Override
    public MesEquipment getMesEquipment(String organizeCode, String equipmentCode) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipmentCode)) return null;
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(equipmentCode, MesPcnExtConstWords.EQUIPMENT_CODE, packBean);
        return equipmentRepository.getByProperty(packBean);
    }

    @Override
    public List<MesEquipmentVariable> getEquipmentVariableList(String organizeCode, List<Long> equipVariableIdList) {
        if (StringUtils.isEmpty(organizeCode) || CollectionUtils.isEmpty(equipVariableIdList)) return null;
        equipVariableIdList = equipVariableIdList.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        if (equipVariableIdList.size() == 1) DdlPreparedPack.getNumEqualPack(equipVariableIdList.get(0), MesPcnExtConstWords.ID, packBean);
        else DdlPreparedPack.getInPackList(equipVariableIdList, MesPcnExtConstWords.ID, packBean);
        return equipmentVariableRepository.findByHqlWhere(packBean);
    }

    @Override
    public MesEquipmentVariable getMesEquipmentVariable(String organizeCode, String equipmentCode, long equipmentVariableId) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipmentCode) || equipmentVariableId == 0) return null;
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(equipmentCode, MesPcnExtConstWords.EQUIPMENT_CODE, packBean);
        DdlPreparedPack.getNumEqualPack(equipmentVariableId, MesPcnExtConstWords.ID, packBean);
        return equipmentVariableRepository.getByProperty(packBean);
    }

    @Override
    public MesEquipmentChannel getMesEquipmentChannel(String organizeCode, String equipmentCode, String channel) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipmentCode) || StringUtils.isEmpty(channel)) return null;
        return equipmentChannelRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.EQUIPMENT_CODE, MesPcnExtConstWords.CHANNEL},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), equipmentCode, channel});
    }

    @Override
    public MesEquipment getMesEquipmentByEquipId(String organizeCode, Integer equipId) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipId)) return null;
        return equipmentRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.EQUIP_ID},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), equipId});
    }

    @Override
    public MesEquipSpotCheckContext getEquipSpotCheckContext(String organizeCode, String workCenterCode, String equipmentCode) {

        MesEquipSpotCheckContext equipSpotCheckContext = new MesEquipSpotCheckContext();

        //查询设备点检主数据
        List<MesEquipmentSpotCheck> equipmentSpotCheckList = equipmentSpotCheckRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_CENTER_CODE, MesPcnExtConstWords.EQUIP_CODE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workCenterCode, equipmentCode});
        //搜集点检方式:非加工前 的设备点检主数据
        equipmentSpotCheckList = CollectionUtils.isEmpty(equipmentSpotCheckList) ? null :
                equipmentSpotCheckList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getSpotCheckType()) && o.getSpotCheckType().compareTo(MesExtEnumUtil.EQUIPMENT_CHECK_INSPECTION_METHOD.BEFORE_PROCESSING.getValue()) != 0)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(equipmentSpotCheckList)) return equipSpotCheckContext;

        //查询设备点检明细数据
        List<MesEquipmentSpotCheckDetail> equipmentSpotCheckDetailList = equipmentSpotCheckDetailRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.EQUIP_CODE, MesPcnExtConstWords.SPOT_CHECK_ITEM_TYPE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), equipmentCode, MesExtEnumUtil.SPOT_CHECK_ITEM_TYPE.AUTO.getValue()});
        if (CollectionUtils.isEmpty(equipmentSpotCheckDetailList)) return equipSpotCheckContext;

        //点检方式:全部点检
        List<Long> pidList = equipmentSpotCheckList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getSpotCheckType()) &&
                o.getSpotCheckType().compareTo(MesExtEnumUtil.EQUIPMENT_CHECK_INSPECTION_METHOD.ALL_INSPECTIONS.getValue()) == 0)).map(MesEquipmentSpotCheck::getId).collect(Collectors.toList());
        //只需要缓存全部点检类型的明细数据
        if (!CollectionUtils.isEmpty(pidList)) {
            equipmentSpotCheckDetailList = equipmentSpotCheckDetailList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getPid()) && pidList.contains(o.getPid()))).collect(Collectors.toList());
            //剔除没有明细数据的全部点检类型的主数据
            List<Long> detailPidList = CollectionUtils.isEmpty(equipmentSpotCheckDetailList) ? null :
                    equipmentSpotCheckDetailList.stream().filter(o -> null != o).map(MesEquipmentSpotCheckDetail::getPid).collect(Collectors.toList());
            List<Long> noDetailPidList = CollectionUtils.isEmpty(detailPidList) ? pidList : pidList.stream().filter(o -> (StringUtils.isEmpty(o) && !detailPidList.contains(o))).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(noDetailPidList)) equipmentSpotCheckList = equipmentSpotCheckList.stream().filter(o -> (null != o && !noDetailPidList.contains(o.getId()))).collect(Collectors.toList());
        }

        //当没有全部点检类型的明细数据时 判断是否存在加工后类型的设备点检主数据, 只需要缓存加工后类型的设备点检主数据
        if (CollectionUtils.isEmpty(equipmentSpotCheckDetailList)) equipmentSpotCheckList = equipmentSpotCheckList.stream().filter(o -> (null != o &&
                !StringUtils.isEmpty(o.getSpotCheckType()) && o.getSpotCheckType().compareTo(MesExtEnumUtil.EQUIPMENT_CHECK_INSPECTION_METHOD.AFTER_PROCESSING.getValue()) == 0)).collect(Collectors.toList());

        //判断经过搜集数据之后是否还存在设备点检主数据
        if (CollectionUtils.isEmpty(equipmentSpotCheckList)) return equipSpotCheckContext;

        //查询设备点检主数据关联零件表数据
        List<MesEquipmentSpotCheckPart> equipmentSpotCheckPartList = equipmentSpotCheckPartRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.EQUIP_CODE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), equipmentCode});

        return equipSpotCheckContext.isExistSpot().equipmentSpotCheckJson(equipmentSpotCheckList).equipmentSpotCheckDetailJson(equipmentSpotCheckDetailList).equipmentSpotCheckPartJson(equipmentSpotCheckPartList);
    }

    //根据设备代码查询加工不可用规则信息
    @Override
    public List<MesProdRuleIgnoreCfg> getProdRuleIgnoreCfgListByEquip(String organizeCode, String equipmentCode) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipmentCode)) return null;
        return prodRuleIgnoreCfgRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.EQUIPMENT_CODE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), equipmentCode});
    }

    //根据设备代码集合查询加工不可用规则信息
    @Override
    public List<MesProdRuleIgnoreCfg> getProdRuleIgnoreCfgListByWcEquips(String organizeCode, List<MesWcEquipment> wcEquipmentList) {
        if (StringUtils.isEmpty(organizeCode) || CollectionUtils.isEmpty(wcEquipmentList)) return null;
        List<String> equipmentCodeList = CollectionUtils.isEmpty(wcEquipmentList) ? null :
                wcEquipmentList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getEquipmentCode()))).map(MesWcEquipment::getEquipmentCode).collect(Collectors.toList());
        return getProdRuleIgnoreCfgListByEquips(organizeCode, equipmentCodeList);
    }

    //根据设备代码集合查询加工不可用规则信息
    @Override
    public List<MesProdRuleIgnoreCfg> getProdRuleIgnoreCfgListByEquips(String organizeCode, List<String> equipmentCodeList) {
        if (StringUtils.isEmpty(organizeCode) || CollectionUtils.isEmpty(equipmentCodeList)) return null;
        equipmentCodeList = equipmentCodeList.stream().filter(o -> StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        if (equipmentCodeList.size() == 1) DdlPreparedPack.getStringEqualPack(equipmentCodeList.get(0), MesPcnExtConstWords.EQUIPMENT_CODE, packBean);
        else DdlPreparedPack.getInPackList(equipmentCodeList, MesPcnExtConstWords.EQUIPMENT_CODE, packBean);
        return prodRuleIgnoreCfgRepository.findByHqlWhere(packBean);
    }

    //根据生产线代码查询加工不可用规则信息
    @Override
    public List<MesProdRuleIgnoreCfg> getProdRuleIgnoreCfgListByCenter(String organizeCode, String workCenterCode) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(workCenterCode)) return null;
        List<MesWcEquipment> wcEquipmentList = wcEquipmentRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_CENTER_CODE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workCenterCode});
        return getProdRuleIgnoreCfgListByWcEquips(organizeCode, wcEquipmentList);
    }

    //根据工位代码查询加工不可用规则信息
    @Override
    public List<MesProdRuleIgnoreCfg> getProdRuleIgnoreCfgListByCell(String organizeCode, String workCenterCode, String workCellCode) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(workCenterCode) || StringUtils.isEmpty(workCellCode)) return null;
        List<MesWcEquipment> wcEquipmentList = wcEquipmentRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_CENTER_CODE, MesPcnExtConstWords.WORK_CELL_CODE},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workCenterCode, workCellCode});
        return getProdRuleIgnoreCfgListByWcEquips(organizeCode, wcEquipmentList);
    }

    //根据设备代码, 来源信息查询加工不可用规则信息
    public List<MesProdRuleIgnoreCfg> getProdRuleIgnoreCfgList(String organizeCode, String equipmentCode, Integer dataSource, Long sourceId) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipmentCode) || StringUtils.isEmpty(dataSource) || StringUtils.isEmpty(sourceId)) return null;
        return prodRuleIgnoreCfgRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.EQUIPMENT_CODE, MesPcnExtConstWords.DATD_SOURCE, MesPcnExtConstWords.SOURCE_ID},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), equipmentCode, dataSource, sourceId});
    }
}
