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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.ISxThirdPartyDbCollectDataStrategyService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.SxThirdPartyDbCollectDataModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtEnumUtil;
import cn.estsh.i3plus.mes.pcn.api.iservice.base.IBaseDataService;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesDatasource;
import cn.estsh.i3plus.pojo.mes.bean.MesEquipment;
import cn.estsh.i3plus.pojo.mes.bean.MesObjectCfg;
import cn.estsh.i3plus.pojo.mes.bean.MesProductData;
import cn.estsh.i3plus.pojo.mes.model.ProductDataModel;
import cn.estsh.i3plus.pojo.mes.repository.MesProductDataRepository;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
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.Optional;
import java.util.stream.Collectors;

@Slf4j
public class SxThirdPartyDbCollectDataProxyProdDataService implements ISxThirdPartyDbCollectDataStrategyService {

    private ISxThirdPartyDbCollectDataStrategyService proxyObject;

    private IBaseDataService baseDataService;

    private MesProductDataRepository productDataRepository;

    public SxThirdPartyDbCollectDataProxyProdDataService(ISxThirdPartyDbCollectDataStrategyService proxyObject) {
        this.proxyObject = proxyObject;
        baseDataService = (IBaseDataService) SpringContextsUtil.getBean("baseDataService");
        productDataRepository = (MesProductDataRepository) SpringContextsUtil.getBean("mesProductDataRepository");
    }

    @Override
    public void exec(SxThirdPartyDbCollectDataModel collect) {

        log.info("工厂{}第三方DB数据采集 --- CFG_CODE: {} EXEC --- CFG_KEY: {} EXEC --- EXEC PROXY PROD DATA --- START ---", collect.getOrganizeCode(), collect.getCfgCode(), collect.getObjectCode());

        if (!checkFieldIsNull(collect)) return;

        proxyObject.exec(collect.noExtraValidate(false));

        if (!checkObjectCfgList(collect)) return;

        proxyObject.exec(collect);

        saveProductData(collect);

        saveParitySyncData(collect);

        proxyObject.exec(collect);

        log.info("工厂{}第三方DB数据采集 --- CFG_CODE: {} EXEC --- CFG_KEY: {} EXEC --- EXEC PROXY PROD DATA --- END ---", collect.getOrganizeCode(), collect.getCfgCode(), collect.getObjectCode());

    }

    private Boolean checkFieldIsNull(SxThirdPartyDbCollectDataModel collect) {
        if (!checkFieldIsNull(collect, collect.getSerialNumberArrField(), MesPcnExtConstWords.SERIAL_NUMBER_ARR_FIELD, "过程条码")) return false;
        if (!checkFieldIsNull(collect, collect.getProductSnArrField(), MesPcnExtConstWords.PRODUCT_SN_ARR_FIELD, "产品条码")) return false;
        return true;
    }

    private Boolean checkObjectCfgList(SxThirdPartyDbCollectDataModel collect) {
        if (CollectionUtils.isEmpty(collect.getObjectCfgList())) return false;
        List<String> fieldCodeList = collect.getObjectCfgList().stream().filter(o -> (null != o &&
                o.getIsSave() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue())).map(MesObjectCfg::getFieldCode).collect(Collectors.toList());
        if (!checkFieldIsExistObjectCfg(collect, getArr(collect.getSerialNumberArrField()), fieldCodeList, MesPcnExtConstWords.SERIAL_NUMBER_ARR_FIELD)) return false;
        if (!checkFieldIsExistObjectCfg(collect, getArr(collect.getProductSnArrField()), fieldCodeList, MesPcnExtConstWords.PRODUCT_SN_ARR_FIELD)) return false;
        return true;
    }

    private List<MesProductData> saveProductData(SxThirdPartyDbCollectDataModel collect) {
        if (CollectionUtils.isEmpty(collect.getMapList())) return null;
        MesProductData productData = getBasicProductData(collect);
        return saveProductDataList(collect, productData);
    }

    private MesProductData getBasicProductData(SxThirdPartyDbCollectDataModel collect) {
        MesProductData productData = new MesProductData();
        productData.setObjectCode(collect.getObjectCode());
        productData.setObjectName(collect.getDataObject().getObjectName());
        productData.setOrganizeCode(collect.getOrganizeCode());
        getEquipment(productData, collect.getDataSource());
        ConvertBean.serviceModelInitialize(productData, collect.getUserInfo());
        return productData;
    }

    private void getEquipment(MesProductData productData, MesDatasource dataSource) {
        if (StringUtils.isEmpty(dataSource.getEquipmentCode())) return;
        productData.setEquCode(dataSource.getEquipmentCode());
        MesEquipment equipment = baseDataService.getEqpByCode(dataSource.getEquipmentCode(), productData.getOrganizeCode());
        if (null == equipment) return;
        productData.setEquName(equipment.getEquipmentName());
    }

    private List<MesProductData> saveProductDataList(SxThirdPartyDbCollectDataModel collect, MesProductData productData) {
        List<MesProductData> resultList = new ArrayList<>();
        for (Map<String, Object> map : collect.getMapList()) {
            MesProductData result = new MesProductData();
            BeanUtils.copyProperties(productData, result);
            packResult(collect, map, result);
            resultList.add(result);
            productDataRepository.insert(result);
        }
        return resultList;
    }

    private void packResult(SxThirdPartyDbCollectDataModel collect, Map<String, Object> map, MesProductData result) {
        result.setSerialNumber(assembleSn(map, collect.getSerialNumberArrField()));
        result.setProductSn(assembleSn(map, collect.getProductSnArrField()));
        result.setId(null);
        List<ProductDataModel> productDataModels = new ArrayList<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Optional<MesObjectCfg> optional = collect.getObjectCfgList().stream().filter(o ->
                    (null != o && o.getFieldCode().equals(entry.getKey()) && o.getIsSave() != null && o.getIsSave() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue())).findFirst();
            if (null != optional && optional.isPresent()) {
                ProductDataModel productDataModel = new ProductDataModel(
                        String.valueOf(entry.getKey()).replaceAll(MesPcnExtConstWords.ONE_SPACE, MesPcnExtConstWords.EMPTY).trim(),
                        optional.get().getFieldName().replaceAll(MesPcnExtConstWords.ONE_SPACE, MesPcnExtConstWords.EMPTY).trim(),
                        String.valueOf(entry.getValue()).replaceAll(MesPcnExtConstWords.ONE_SPACE, MesPcnExtConstWords.EMPTY).trim());
                productDataModels.add(productDataModel);
            }
        }
        result.setLineData(JSON.toJSONString(productDataModels));
        result.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());

        packDynamicsField(collect, map, result);
    }

    @Override
    public Boolean checkFieldIsNull(SxThirdPartyDbCollectDataModel collect, String fieldValue, String field, String fieldName) {
        return proxyObject.checkFieldIsNull(collect, fieldValue, field, fieldName);
    }

    @Override
    public Boolean checkFieldIsExistObjectCfg(SxThirdPartyDbCollectDataModel collect, String[] arr, List<String> fieldCodeList, String field) {
        return proxyObject.checkFieldIsExistObjectCfg(collect, arr, fieldCodeList, field);
    }

    @Override
    public String[] getArr(String snField) { return proxyObject.getArr(snField); }

    @Override
    public void packDynamicsField(SxThirdPartyDbCollectDataModel collect, Map<String, Object> map, Object obj) {
        proxyObject.packDynamicsField(collect, map, obj);
    }

    @Override
    public String assembleSn(Map<String, Object> map, String snField) {
        return proxyObject.assembleSn(map, snField);
    }

    @Override
    public Boolean saveParitySyncData(SxThirdPartyDbCollectDataModel collect) {
        if (CollectionUtils.isEmpty(collect.getMapList())) return false;
        return proxyObject.saveParitySyncData(collect);
    }

}
