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.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.tool.ConvertUtil;
import cn.estsh.i3plus.pojo.base.bean.BaseBean;
import cn.estsh.i3plus.pojo.base.jpa.dao.BaseRepository;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
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;

@Slf4j
public class SxThirdPartyDbCollectDataProxyDynamicsService implements ISxThirdPartyDbCollectDataStrategyService {

    private ISxThirdPartyDbCollectDataStrategyService proxyObject;

    public SxThirdPartyDbCollectDataProxyDynamicsService(ISxThirdPartyDbCollectDataStrategyService proxyObject) {
        this.proxyObject = proxyObject;
    }

    @Override
    public void exec(SxThirdPartyDbCollectDataModel collect) {

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

        if (!checkFieldIsNull(collect)) return;

        BaseBean baseBean = instanceDynamicsTable(collect);

        BaseRepository baseRepository = instanceDynamicsRepository(collect, baseBean);

        proxyObject.exec(collect);

        saveDynamicsData(collect, baseBean, baseRepository);

        saveParitySyncData(collect);

        proxyObject.exec(collect);

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

    }

    private Boolean checkFieldIsNull(SxThirdPartyDbCollectDataModel collect) {
        if (!checkFieldIsNull(collect, collect.getDynamicsTableName(), MesPcnExtConstWords.DYNAMICS_TABLE_NAME, "动态表名")) return false;
        if (!checkFieldIsNull(collect, collect.getDynamicsReflectField(), MesPcnExtConstWords.DYNAMICS_REFLECT_FIELD, "动态")) return false;
        return true;
    }

    private BaseBean instanceDynamicsTable(SxThirdPartyDbCollectDataModel collect) {
        try {
            Class clazz = Class.forName(collect.getDynamicsTableName());
            return (BaseBean) clazz.newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            throw new ImppBusiException(String.format("动态表名[%s]反射异常:%s", collect.getDynamicsTableName(), e.getMessage()));
        }
    }

    private BaseRepository instanceDynamicsRepository(SxThirdPartyDbCollectDataModel collect, BaseBean baseBean) {
        try {
            return  (BaseRepository) SpringContextsUtil.getBean(ConvertUtil.toLowerCaseFirstOne(baseBean.getClass().getSimpleName()) + MesPcnExtConstWords.Repository);
        } catch (Exception e) {
            throw new ImppBusiException(String.format("动态表名[%s]注入Repository类异常:%s", collect.getDynamicsTableName(), e.getMessage()));
        }
    }

    private List<BaseBean> saveDynamicsData(SxThirdPartyDbCollectDataModel collect, BaseBean baseBean, BaseRepository baseRepository) {
        if (CollectionUtils.isEmpty(collect.getMapList())) return null;
        packBasicDynamicsData(collect, baseBean);
        packDefaultField(collect, baseBean);

        List<BaseBean> resultList = new ArrayList<>();
        for (Map<String, Object> map : collect.getMapList()) {
            BaseBean result = instanceDynamicsTable(collect);
            BeanUtils.copyProperties(baseBean, result);
            packResult(collect, map, result);
            execMethodField(collect, result);
            resultList.add(result);
            baseRepository.insert(result);
        }
        return resultList;
    }

    private void packBasicDynamicsData(SxThirdPartyDbCollectDataModel collect, BaseBean baseBean) {
        baseBean.setOrganizeCode(collect.getOrganizeCode());
        ConvertBean.serviceModelInitialize(baseBean, collect.getUserInfo());
        setObjectAttr(baseBean, MesPcnExtConstWords.SYSTEM_SYNC_STATUS, MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        new ConvertBeanExt(baseBean).convertBean(baseBean);
    }

    private void packResult(SxThirdPartyDbCollectDataModel collect, Map<String, Object> map, BaseBean result) {
        if (!StringUtils.isEmpty(collect.getSerialNumberArrField()))
            setObjectAttr(result, MesPcnExtConstWords.SERIAL_NUMBER, assembleSn(map, collect.getSerialNumberArrField()));
        if (!StringUtils.isEmpty(collect.getProductSnArrField()))
            setObjectAttr(result, MesPcnExtConstWords.PRODUCT_SN, assembleSn(map, collect.getProductSnArrField()));
        result.setId(null);
        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 void packDefaultField(SxThirdPartyDbCollectDataModel collect, BaseBean baseBean) {
        if (StringUtils.isEmpty(collect.getDefaultValueField())) return;
        proxyObject.packDefaultField(collect, baseBean);
    }

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

    @Override
    public void setObjectAttr(Object obj, String fieldName, Object value) {
        proxyObject.setObjectAttr(obj, fieldName, value);
    }

    @Override
    public void execMethodField(SxThirdPartyDbCollectDataModel collect, Object obj) {
        if (StringUtils.isEmpty(collect.getMethodField())) return;
        proxyObject.execMethodField(collect, 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);
    }

}
