package com.yihu.hos.standard.service.adapter;


import com.fasterxml.jackson.databind.JsonNode;
import com.yihu.hos.core.datatype.StringUtil;
import com.yihu.hos.standard.dao.IStdDictionaryModelDao;
import com.yihu.hos.standard.dao.StdDictionaryEntryModelDao;
import com.yihu.hos.standard.match.dictionary.DictItemStrategyExecute;
import com.yihu.hos.standard.match.dictionary.DictitemStandardNameStrategy;
import com.yihu.hos.standard.match.matchModel.DictItemMatchVO;
import com.yihu.hos.standard.model.adapter.AdapterDictEntryModel;
import com.yihu.hos.standard.model.adapter.AdapterDictModel;
import com.yihu.hos.standard.model.adapter.AdapterSchemeVersionModel;
import com.yihu.hos.standard.model.standard.StdDictionaryEntryModel;
import com.yihu.hos.standard.model.standard.StdDictionaryModel;
import com.yihu.hos.standard.service.bo.AdapterVersion;
import com.yihu.hos.standard.service.bo.StandardVersion;
import com.yihu.hos.standard.service.standard.StdDictService;
import com.yihu.hos.web.framework.constant.SqlConstants;
import com.yihu.hos.web.framework.dao.SQLGeneralDAO;
import com.yihu.hos.web.framework.model.DetailModelResult;
import com.yihu.hos.web.framework.model.Result;
import com.yihu.hos.web.framework.util.springutil.SpringBeanUtil;
import com.yihu.hos.web.framework.util.sql.SqlCreator;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Transactional
@Service("AdapterDictService")
public class AdapterDictService extends SQLGeneralDAO {

    public static final String BEAN_ID = "AdapterDictService";

    @Autowired
    private AdapterDictEntryService adapterDictEntryService;

    @Autowired
    private AdapterSchemeVersionService adapterSchemeVersionService;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private IStdDictionaryModelDao stdDictionaryDao;

    @Autowired
    private StdDictionaryEntryModelDao stdDictionaryEntryDao;

    @Autowired
    private StdDictService stdDictService;

    private AdapterDictService adapterDictService;

    public AdapterDictService() {
    }

    public void finalize() throws Throwable {
        super.finalize();
    }

    public Result add(String adapterVersion, String dict) {
        try {
            AdapterVersion version = new AdapterVersion(adapterVersion);
            AdapterDictModel adapterDictModel = objectMapper.readValue(dict, AdapterDictModel.class);
            Session session = getCurrentSession();
            String sql = "select max(id) from " + version.getMetaDataTableName();
            Query query = session.createSQLQuery(sql);
            Object object = query.uniqueResult();
            adapterDictModel.setId(object == null ? 1 : Integer.parseInt(object.toString()) + 1);

            JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(adapterDictModel));
            SqlCreator sqlCreator = new SqlCreator(AdapterDictModel.class);
            sql = sqlCreator.insertData(version.getMetaDataTableName(), jsonNode);
            query = getExeuteQuery(sqlCreator, sql);
            query.executeUpdate();
            adapterDictModel.setSuccessFlg(true);
            adapterDictModel.setMessage("保存适配字典成功");
            return adapterDictModel;
        } catch (Exception e) {
           return Result.error("保存适配字典失败");
        }
    }

    public Result delete(String adapterVersion, Integer dictId) {
        try {
            if (adapterVersion == null || adapterVersion.length() == 0) {
                return Result.error("无效适配版本");
            }
            AdapterVersion version = new AdapterVersion(adapterVersion);
            Session session = getCurrentSession();
            String sql = "delete from " + version.getMetaDataTableName() + " where id = :id";
            Query query = session.createSQLQuery(sql);
            query.setInteger("id", dictId);
            query.executeUpdate();
            return Result.success("删除适配字典成功");
        } catch (Exception e) {
            return Result.error("删除适配字典失败");
        }
    }

    public Result modify(String adapterVersion, String dict) {
        try {
            AdapterVersion version = new AdapterVersion(adapterVersion);
            AdapterDictModel adapterDictModel = objectMapper.readValue(dict, AdapterDictModel.class);
            JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(adapterDictModel));

            SqlCreator sqlCreator = new SqlCreator(AdapterDictModel.class);
            String sql = sqlCreator.updateDataByTableKey(version.getMetaDataTableName(), jsonNode);
            Query query = getExeuteQuery(sqlCreator, sql);
            query.executeUpdate();
            adapterDictModel.setSuccessFlg(true);
            adapterDictModel.setMessage("修改适配字典成功");
            return adapterDictModel;
        } catch (Exception e) {
            return Result.error("修改适配字典失败");
        }
    }


    public DetailModelResult getDetailResult(String adapterVersion, String condition, String order, Integer rows, Integer page) {
        try {
            List dictList = getDictList(AdapterDictModel.class, adapterVersion, condition, order, rows, page);
            Integer count = getDictInt(AdapterDictModel.class, adapterVersion, condition);
            DetailModelResult result = DetailModelResult.success("获取适配字典列表成功");
            result.setDetailModelList(dictList);
            result.setTotalCount(count);
            return result;
        } catch (Exception e) {
            return DetailModelResult.error("获取适配字典列表成功");
        }
    }

    public Result get(String version, Integer dictId) {
        try {
            AdapterVersion adapterVersion = new AdapterVersion(version);
            AdapterDictModel adapterDictModel = (AdapterDictModel) get(AdapterDictModel.class, adapterVersion.getDictTableName(), dictId);
            adapterDictModel.setSuccessFlg(true);
            adapterDictModel.setMessage("获取适配字典成功");
            return adapterDictModel;
        } catch (Exception e) {
            return Result.error("获取适配字典失败");
        }
    }

    public List getDictList(Class tClass, String adapterVersion, String condition, String order, Integer limit, Integer offset) {
        AdapterVersion version = new AdapterVersion(adapterVersion);
        String tableName = version.getDictTableName();
        SqlCreator sqlCreator = new SqlCreator(tClass);
        try {
            if (!StringUtil.isEmpty(condition)) {
                JsonNode jsonNode = objectMapper.readTree(condition);
                String name = jsonNode.get("name").asText();
                sqlCreator.likeOrCondition("stdDictCode", "stdDictName", name);
            }
            if (!StringUtil.isEmpty(order)) {
                JsonNode jsonNode = objectMapper.readTree(order);
                Iterator<String> fieldNames = jsonNode.fieldNames();
                while (fieldNames.hasNext()) {
                    String fieldName = fieldNames.next();
                    String value = jsonNode.get(fieldName).asText().toUpperCase();
                    sqlCreator.order(fieldName, value);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        String sql = sqlCreator.selectData(tableName);
        Query query = getQuery(sqlCreator, sql);
        if (limit != null) {
            query.setMaxResults(limit);
            if (offset != null) {
                query.setFirstResult((offset - 1) * limit);
            }
        }
        return query.list();
    }

    public Integer getDictInt(Class tClass, String adapterVersion, String condition) {
        AdapterVersion version = new AdapterVersion(adapterVersion);
        String tableName = version.getDictTableName();
        SqlCreator sqlCreator = new SqlCreator(tClass);
        try {
            if (!StringUtil.isEmpty(condition)) {
                JsonNode jsonNode = objectMapper.readTree(condition);
                String name = jsonNode.get("name").asText();
                sqlCreator.likeOrCondition("stdDictCode", "stdDictName", name);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        String sql = sqlCreator.countData(tableName);
        Query query = getCurrentSession().createSQLQuery(sql);
        for (String key : sqlCreator.getKeyValueMap().keySet()) {
            query.setParameter(key, sqlCreator.getKeyValueMap().get(key));
        }
        Integer count = Integer.parseInt(StringUtil.toString(query.list().get(0)));
        return count;
    }
    public void strategy(String schemaName, String version,String std_version, String adapter_std_version) throws Exception {
        List<AdapterDictEntryModel> unAdapterDictEntryModels= adapterDictEntryService.getAllUnAdaptDictEntry(schemaName,version);//等待适配的标准字典项
        List<AdapterDictEntryModel> adapterDictEntryModels = new ArrayList<AdapterDictEntryModel>();//之前已经适配好的适配方案
        //查找出  之前已经适配好的适配方案
        List<AdapterSchemeVersionModel> all = adapterSchemeVersionService.getAll(schemaName);//
        if(all!=null){
            for(AdapterSchemeVersionModel adapterSchemeVersionModel:all){
                String vers = adapterSchemeVersionModel.getVersion();
                if(org.apache.commons.lang3.StringUtils.isNotBlank(vers)){
                    List<AdapterDictEntryModel> adaptMetadata = adapterDictEntryService.getAllAdaptDictEntry(schemaName,adapterSchemeVersionModel.getVersion());
                    adapterDictEntryModels.addAll(adaptMetadata);
                }
            }
        }
        DictItemMatchVO matchVO= new DictItemMatchVO();
        matchVO.setCodeAdapter(matchVO.geNameGroup(adapterDictEntryModels));

        //設置匹配的机构数据緩存
        StandardVersion standardVersion = new StandardVersion(adapter_std_version);
        List<StdDictionaryEntryModel> dictItems = stdDictService.getDicEntryList(schemaName,standardVersion, null, null, null, null);

        for (StdDictionaryEntryModel stdDictItem:dictItems){
            StdDictionaryModel dictionary = stdDictionaryDao.getDictionaryName(schemaName,adapter_std_version, stdDictItem.getDictId());
            if(dictionary != null){
                DictitemStandardNameStrategy.getNameMap().put(stdDictItem.getValue() + "_" + dictionary.getCode(),stdDictItem);
            }
        }

        //执行匹配
        DictItemStrategyExecute.setFirst(version, unAdapterDictEntryModels.size());//设置第一次匹配

        Set<String> sqlList = new HashSet<String>();

        for (AdapterDictEntryModel unAdapterDictEntryModel : unAdapterDictEntryModels) {
            threadPoolTaskExecutor.execute(new DictItemStrategyExecute(schemaName,unAdapterDictEntryModel, matchVO,std_version,adapter_std_version,version, stdDictionaryDao, stdDictionaryEntryDao,adapterDictEntryService));

            Integer unAdaptDicId = unAdapterDictEntryModel.getStdDictId();
            StdDictionaryModel adapterDictionaryModel = stdDictionaryDao.getDictionaryName(schemaName,adapter_std_version, unAdaptDicId);
            if (adapterDictionaryModel != null) {
                adapterDictService = SpringBeanUtil.getService(AdapterDictService.BEAN_ID);
                AdapterDictModel entity = adapterDictService.getAdapterDictByCode(schemaName,version, adapterDictionaryModel.getCode());
                String sqrSql = null;
                if (null != entity) {
                    sqrSql = adapterDictService.saveAdaptDictSql(schemaName,entity, adapterDictionaryModel, version);
                }
                if (null != sqrSql && !"".equals(sqrSql)) {
                    sqlList.add(sqrSql);
                }
            }
        }
    }

    public void saveAdaptDict(AdapterDictModel strategyDict,StdDictionaryModel orgDict,String version) throws Exception {
        strategyDict.setAdapterDictId(orgDict.getId());
        strategyDict.setAdapterDictCode(orgDict.getCode());
        strategyDict.setAdapterDictName(orgDict.getName());
        JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(strategyDict));
        SqlCreator sqlCreator = new SqlCreator(AdapterDictModel.class);
        String sql = sqlCreator.updateDataByTableKey(new AdapterVersion(version).getDictTableName(), jsonNode);
        Query query = getExeuteQuery(sqlCreator, sql);
        query.executeUpdate();
    }

    public String saveAdaptDictSql(AdapterDictModel strategyDict, StdDictionaryModel orgDict, String version) throws Exception {
        StringBuilder sqlBuffer = new StringBuilder();
        sqlBuffer.append(SqlConstants.UPDATE + new AdapterVersion(version).getDictTableName() + SqlConstants.SET);
        sqlBuffer.append(" adapter_dict_id = " + orgDict.getId());
        sqlBuffer.append(",adapter_dict_code = '" + orgDict.getCode() + "'");
        sqlBuffer.append(",adapter_dict_name = '" + orgDict.getName() + "'");
        sqlBuffer.append(" where id=" + strategyDict.getId());
        return sqlBuffer.toString();
    }

    public String saveAdaptDictSql(String schemaName,AdapterDictModel strategyDict, StdDictionaryModel orgDict, String version) throws Exception {
        StringBuilder sqlBuffer = new StringBuilder();
        sqlBuffer.append(SqlConstants.UPDATE + new AdapterVersion(version).getDictTableName() + SqlConstants.SET);
        sqlBuffer.append(" adapter_dict_id = " + orgDict.getId());
        sqlBuffer.append(",adapter_dict_code = '" + orgDict.getCode() + "'");
        sqlBuffer.append(",adapter_dict_name = '" + orgDict.getName() + "'");
        sqlBuffer.append(" where id=" + strategyDict.getId());

        String myCatAnnotation = "/*#mycat\\:schema=" + schemaName + "*/ ";
        String completeSql = myCatAnnotation + sqlBuffer.toString();

        return completeSql;
    }

    public AdapterDictModel getAdapterDictByCode(String version, String dictCode) {
        try {
            if (StringUtil.isEmpty(dictCode)) {
                return null;
            }
            SqlCreator sqlCreator = new SqlCreator(AdapterDictModel.class);
            sqlCreator.equalCondition("stdDictCode", dictCode);
            String sql = sqlCreator.selectData("adapter_dict_" + version);
            Query query = getQuery(sqlCreator, sql);
            return (AdapterDictModel) query.uniqueResult();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public AdapterDictModel getAdapterDictByCode(String schemaName,String version, String dictCode) {
        try {
            if (StringUtil.isEmpty(dictCode)) {
                return null;
            }
            SqlCreator sqlCreator = new SqlCreator(AdapterDictModel.class);
            sqlCreator.equalCondition("stdDictCode", dictCode);
            String sql = sqlCreator.selectData("adapter_dict_" + version);

            String myCatAnnotation = "/*#mycat\\:schema=" + schemaName + "*/ ";
            String completeSql = myCatAnnotation + sql;

            Query query = getQuery(sqlCreator, completeSql);
            return (AdapterDictModel) query.uniqueResult();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}