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


import com.fasterxml.jackson.databind.JsonNode;
import com.yihu.hos.core.datatype.CollectionUtil;
import com.yihu.hos.core.datatype.StringUtil;
import com.yihu.hos.standard.model.adapter.AdapterDictEntryModel;
import com.yihu.hos.standard.model.adapter.AdapterDictModel;
import com.yihu.hos.standard.model.adapter.AdapterSchemeModel;
import com.yihu.hos.standard.model.adapter.resultModel.AdapterDictEntryResultDetailModel;
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.web.framework.constant.ErrorCode;
import com.yihu.hos.web.framework.dao.SQLGeneralDAO;
import com.yihu.hos.web.framework.exception.ApiException;
import com.yihu.hos.web.framework.model.DetailModelResult;
import com.yihu.hos.web.framework.model.Result;
import com.yihu.hos.web.framework.util.sql.BeanTransformer;
import com.yihu.hos.web.framework.util.sql.SqlCreator;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;
@Transactional
@Service("AdapterDictEntryService")
public class AdapterDictEntryService extends SQLGeneralDAO {

    public static final String BEAN_ID = "AdapterDictEntryService";


    public AdapterDictEntryService() {
    }

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

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

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

    public void delete(String adapterVersion, Integer dictentryId) {
        try {
            if (adapterVersion == null || adapterVersion.length() == 0) throw new IllegalArgumentException("无效版本");
            AdapterVersion version = new AdapterVersion(adapterVersion);
            Session session = getCurrentSession();
            String sql = "delete from " + version.getDictEntryTableName() + " where id = :id";
            Query query = session.createSQLQuery(sql);
            query.setInteger("id", dictentryId);
            query.executeUpdate();
        } catch (Exception e) {
            throw new ApiException(ErrorCode.DeleteDictEntryFailed);
        }
    }

    public Result modify(String adapterVersion, String dictentry) {
        try {
            AdapterVersion version = new AdapterVersion(adapterVersion);
            AdapterDictEntryModel adapterDictEntryModel = objectMapper.readValue(dictentry, AdapterDictEntryModel.class);
            JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(adapterDictEntryModel));
            SqlCreator sqlCreator = new SqlCreator(AdapterDictEntryModel.class);
            String sql = sqlCreator.updateDataByTableKey(version.getDictEntryTableName(), jsonNode);
            Query query = getExeuteQuery(sqlCreator, sql);
            query.executeUpdate();
            adapterDictEntryModel.setSuccessFlg(true);
            adapterDictEntryModel.setMessage("获取适配字典项成功");
            return adapterDictEntryModel;
        } catch (Exception e) {
            return Result.error("获取适配字典项失败");
        }
    }

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

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

    public List getDictEntryList(Class tClass, String adapterVersion, String condition, String order, Integer limit, Integer offset) throws Exception{
        AdapterVersion version = new AdapterVersion(adapterVersion);
        String tableName = version.getDictEntryTableName();
        SqlCreator sqlCreator = new SqlCreator(tClass);
        if (!StringUtil.isEmpty(condition)) {
            try {
                JsonNode jsonNode = objectMapper.readTree(condition);
                String name = jsonNode.get("name").asText();
                sqlCreator.equalCondition("stdDictId", jsonNode.get("stdDictId").asInt());
                sqlCreator.likeOrCondition("stdEntryCode", "stdEntryValue", name);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            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);
            }
        }
        List<AdapterDictEntryModel> modelList = query.list();
        List<Integer> idList = new ArrayList<>();
        Map<Integer, StdDictionaryModel> stdDictModelMap = new HashMap<>();
        Integer schemeId = null;
        for (AdapterDictEntryModel model : modelList) {
            if (model.getAdapterDictId() != null) {
                schemeId = model.getSchemeId();
                idList.add(model.getAdapterDictId());
            }
        }

        if (!CollectionUtil.isEmpty(idList)) {
            AdapterSchemeModel scheme = getEntity(AdapterSchemeModel.class, schemeId);
            StandardVersion standardVersion = new StandardVersion(scheme.getAdapterStdVersion());
            tableName = standardVersion.getDictTableName();
            sqlCreator = new SqlCreator(StdDictionaryModel.class);
            sqlCreator.inCondition("id", idList);
            sql = sqlCreator.selectData(tableName);
            query = getQuery(sqlCreator, sql);
            List<StdDictionaryModel> stdDictModelList = query.list();
            for (StdDictionaryModel model : stdDictModelList) {
                stdDictModelMap.put(model.getId(), model);
            }
        }

        List<AdapterDictEntryResultDetailModel> detailModelList = new ArrayList<>();
        for (AdapterDictEntryModel model : modelList) {
            AdapterDictEntryResultDetailModel detailModel = new AdapterDictEntryResultDetailModel();
            detailModel.setId(model.getId());
            detailModel.setSchemeId(model.getSchemeId());
            detailModel.setAdapterDictId(model.getAdapterDictId());
            detailModel.setAdapterEntryId(model.getAdapterEntryId());
            detailModel.setAdapterEntryCode(model.getAdapterEntryCode());
            detailModel.setAdapterEntryValue(model.getAdapterEntryValue());
            detailModel.setStdDictId(model.getStdDictId());
            detailModel.setStdEntryId(model.getStdEntryId());
            detailModel.setStdEntryCode(model.getStdEntryCode());
            detailModel.setStdEntryValue(model.getStdEntryValue());
            detailModel.setAdapterInfo(model.getAdapterInfo());
            if (stdDictModelMap.get(model.getAdapterDictId()) != null) {
                detailModel.setAdapterDictCode(stdDictModelMap.get(model.getAdapterDictId()).getCode());
                detailModel.setAdapterDictName(stdDictModelMap.get(model.getAdapterDictId()).getName());
            }
            detailModelList.add(detailModel);
        }
        return detailModelList;
    }

    public Integer getDictEntryInt(Class tClass, String adapterVersion, String condition) {
        AdapterVersion version = new AdapterVersion(adapterVersion);
        String tableName = version.getDictEntryTableName();
        SqlCreator sqlCreator = new SqlCreator(tClass);
        if (!StringUtil.isEmpty(condition)) {
            try {
                JsonNode jsonNode = objectMapper.readTree(condition);
                String name = jsonNode.get("name").asText();
                sqlCreator.equalCondition("stdDictId", jsonNode.get("stdDictId").asInt());
                sqlCreator.likeOrCondition("stdEntryCode", "stdEntryValue", name);
            } catch (IOException 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 DetailModelResult updateDictEntrys(String adapterVersion, String list) {
        try {
            AdapterVersion version = new AdapterVersion(adapterVersion);
            List<AdapterDictEntryResultDetailModel> adapterDictEntryList = Arrays.asList(objectMapper.readValue(list, AdapterDictEntryResultDetailModel[].class));
            List<Integer> idList = new ArrayList<>();
            Map<Integer, AdapterDictEntryResultDetailModel> dictEntryResultMap = new HashMap<>();
            Integer maxId = null;
            for (AdapterDictEntryResultDetailModel dictEntryModel : adapterDictEntryList) {
                AdapterDictEntryModel adapterDictEntryModel = new AdapterDictEntryModel();
                adapterDictEntryModel.setId(dictEntryModel.getId());
                adapterDictEntryModel.setSchemeId(dictEntryModel.getSchemeId());
                adapterDictEntryModel.setAdapterDictId(dictEntryModel.getAdapterDictId());
                adapterDictEntryModel.setAdapterEntryId(dictEntryModel.getAdapterEntryId());
                adapterDictEntryModel.setAdapterEntryCode(dictEntryModel.getAdapterEntryCode());
                adapterDictEntryModel.setAdapterEntryValue(dictEntryModel.getAdapterEntryValue());
                adapterDictEntryModel.setStdDictId(dictEntryModel.getStdDictId());
                adapterDictEntryModel.setStdEntryId(dictEntryModel.getStdEntryId());
                adapterDictEntryModel.setStdEntryCode(dictEntryModel.getStdEntryCode());
                adapterDictEntryModel.setStdEntryValue(dictEntryModel.getStdEntryValue());
                adapterDictEntryModel.setAdapterInfo(dictEntryModel.getAdapterInfo());
                idList.add(dictEntryModel.getStdDictId());
                dictEntryResultMap.put(dictEntryModel.getStdDictId(), dictEntryModel);
                SqlCreator sqlCreator = new SqlCreator(AdapterDictEntryModel.class);
                String sql;
                if (dictEntryModel.getId() == null) {
                    if (maxId == null) {
                        sql = "select max(id) from " + version.getDictEntryTableName();
                        Query query = getCurrentSession().createSQLQuery(sql);
                        Object object = query.uniqueResult();
                        maxId = object == null ? 1 : Integer.parseInt(object.toString()) + 1;
                    }
                    adapterDictEntryModel.setId(maxId++);
                    JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(adapterDictEntryModel));
                    sql = sqlCreator.insertData(version.getDictEntryTableName(), jsonNode);
                } else {
                    JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(adapterDictEntryModel));
                    sql = sqlCreator.updateDataByTableKey(version.getDictEntryTableName(), jsonNode);
                }

                Query query = getExeuteQuery(sqlCreator, sql);
                query.executeUpdate();
            }
            if (!CollectionUtil.isEmpty(idList)) {
                String tableName = version.getDictTableName();
                SqlCreator sqlCreator = new SqlCreator(AdapterDictModel.class);
                sqlCreator.inCondition("stdDictId", idList);
                String sql = sqlCreator.selectData(tableName);
                Query query = getQuery(sqlCreator, sql);
                List<AdapterDictModel> adapterDictModelList = query.list();
                for (AdapterDictModel model : adapterDictModelList) {
                    AdapterDictEntryResultDetailModel dictentryModel = dictEntryResultMap.get(model.getStdDictId());
                    model.setAdapterDictId(dictentryModel.getAdapterDictId());
                    model.setAdapterDictCode(dictentryModel.getAdapterDictCode());
                    model.setAdapterDictName(dictentryModel.getAdapterDictName());
                    JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(model));
                    sqlCreator = new SqlCreator(AdapterDictModel.class);
                    sql = sqlCreator.updateDataByTableKey(version.getDictTableName(), jsonNode);
                    query = getExeuteQuery(sqlCreator, sql);
                    query.executeUpdate();
                }
            }
            DetailModelResult detailModelResult = DetailModelResult.success("保存适配字典项成功");
            detailModelResult.setDetailModelList(adapterDictEntryList);
            return detailModelResult;
        } catch (Exception e) {
            return DetailModelResult.error("保存适配字典项失败");
        }
    }

    public Result deleteMultiple(String adapterVersion, Integer dictEntryId, Integer stdDictId, Integer adapterDictId) {
        try {
            if (adapterVersion == null || adapterVersion.length() == 0) {
                return Result.error("无效适配版本");
            }
            AdapterVersion version = new AdapterVersion(adapterVersion);
            Session session = getCurrentSession();

            String sql = "delete from " + version.getDictEntryTableName() + " where id = :id";
            Query query = session.createSQLQuery(sql);
            query.setInteger("id", dictEntryId);
            query.executeUpdate();

            SqlCreator sqlCreator = new SqlCreator(AdapterDictEntryModel.class);
            sqlCreator.equalCondition("stdDictId", stdDictId);
            sqlCreator.equalCondition("adapterDictId", adapterDictId);
            sql = sqlCreator.countData(version.getDictEntryTableName());
            query = getExeuteQuery(sqlCreator, sql);
            Integer count = Integer.parseInt(StringUtil.toString(query.list().get(0)));
            if (count == 0) {
                sql = "delete from " + version.getDictTableName() + " where std_dict_id = :stdDictId and adapter_dict_id = :adapterDictId";
                query = session.createSQLQuery(sql);
                query.setInteger("stdDictId", stdDictId);
                query.setInteger("adapterDictId", adapterDictId);
                query.executeUpdate();
            }
            return Result.success("删除适配字典项成功");
        } catch (Exception e) {
            return Result.error("删除适配字典项失败");
        }
    }

    public AdapterDictEntryModel getAdapterDictItemBydictCode(String version,AdapterDictModel adapterDictT, String dictCode) {
        try {
            SqlCreator sqlCreator = new SqlCreator(AdapterDictEntryModel.class);
            sqlCreator.equalCondition("stdDictId", adapterDictT.getStdDictId());
            sqlCreator.equalCondition("stdEntryCode", dictCode);
            String sql = sqlCreator.selectData("std_dictionary_entry_"+version);
            Query query = getQuery(sqlCreator, sql);
            return (AdapterDictEntryModel)query.uniqueResult();
        } catch (Exception e) {
            return null;
        }
    }

    public AdapterDictEntryModel getAdapterDictItemBydictValue(String version,AdapterDictModel adapterDictT, String dictValue) {
        try {
            SqlCreator sqlCreator = new SqlCreator(AdapterDictEntryModel.class);
            sqlCreator.equalCondition("stdDictId", adapterDictT.getStdDictId());
            sqlCreator.equalCondition("stdEntryValue", dictValue);
            String sql = sqlCreator.selectData("std_dictionary_entry_"+version);
            Query query = getQuery(sqlCreator, sql);
            return (AdapterDictEntryModel)query.uniqueResult();
        } catch (Exception e) {
            return null;
        }
    }
    public List<AdapterDictEntryModel> getAllUnAdaptDictEntry(String version){
        AdapterVersion adapterVersion = new AdapterVersion(version);
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT m.*").append(" FROM "+adapterVersion.getDictEntryTableName()).append(" m where m.adapter_entry_id is null");
        Query query = getCurrentSession().createSQLQuery(sql.toString());
        query.setResultTransformer(new BeanTransformer(AdapterDictEntryModel.class));
        List<AdapterDictEntryModel> list = query.list();
        return list;
    }

    public List<AdapterDictEntryModel> getAllUnAdaptDictEntry(String schemaName, String version){
        AdapterVersion adapterVersion = new AdapterVersion(version);
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT m.*").append(" FROM "+adapterVersion.getDictEntryTableName()).append(" m where m.adapter_entry_id is null");

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

        Query query = getCurrentSession().createSQLQuery(completeSql);
        query.setResultTransformer(new BeanTransformer(AdapterDictEntryModel.class));
        List<AdapterDictEntryModel> list = query.list();
        return list;
    }

    public List<AdapterDictEntryModel> getAllAdaptDictEntry(String version) {
        AdapterVersion adapterVersion = new AdapterVersion(version);
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT m.*").append(" FROM "+adapterVersion.getDictEntryTableName()).append(" m where m.adapter_entry_id is not null");
        Query query = getCurrentSession().createSQLQuery(sql.toString());
        query.setResultTransformer(new BeanTransformer(AdapterDictEntryModel.class));
        List<AdapterDictEntryModel> list = query.list();
        return list;
    }

    public List<AdapterDictEntryModel> getAllAdaptDictEntry(String schemaName,String version) {
        AdapterVersion adapterVersion = new AdapterVersion(version);
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT m.*").append(" FROM "+adapterVersion.getDictEntryTableName()).append(" m where m.adapter_entry_id is not null");

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

        Query query = getCurrentSession().createSQLQuery(completeSql);
        query.setResultTransformer(new BeanTransformer(AdapterDictEntryModel.class));
        List<AdapterDictEntryModel> list = query.list();
        return list;
    }

    public void saveAdapt(AdapterDictEntryModel adapterDictEntryModel, StdDictionaryEntryModel stdDictionaryEntryModel, String version,String adapterInfo) throws  Exception{
        adapterDictEntryModel.setAdapterDictId(stdDictionaryEntryModel.getDictId());
        adapterDictEntryModel.setAdapterEntryId(stdDictionaryEntryModel.getId());
        adapterDictEntryModel.setAdapterEntryCode(stdDictionaryEntryModel.getCode());
        adapterDictEntryModel.setAdapterEntryValue(stdDictionaryEntryModel.getValue());
        adapterDictEntryModel.setAdapterInfo(adapterInfo);
        JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(adapterDictEntryModel));
        SqlCreator sqlCreator = new SqlCreator(AdapterDictEntryModel.class);
        String sql = sqlCreator.updateDataByTableKey(new AdapterVersion(version).getDictEntryTableName(), jsonNode);
        Query query = getExeuteQuery(sqlCreator, sql);
        query.executeUpdate();
    }

    public void saveAdapt(String schemaName,AdapterDictEntryModel adapterDictEntryModel, StdDictionaryEntryModel stdDictionaryEntryModel, String version,String adapterInfo) throws  Exception{
        adapterDictEntryModel.setAdapterDictId(stdDictionaryEntryModel.getDictId());
        adapterDictEntryModel.setAdapterEntryId(stdDictionaryEntryModel.getId());
        adapterDictEntryModel.setAdapterEntryCode(stdDictionaryEntryModel.getCode());
        adapterDictEntryModel.setAdapterEntryValue(stdDictionaryEntryModel.getValue());
        adapterDictEntryModel.setAdapterInfo(adapterInfo);
        JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(adapterDictEntryModel));
        SqlCreator sqlCreator = new SqlCreator(AdapterDictEntryModel.class);
        String sql = sqlCreator.updateDataByTableKey(new AdapterVersion(version).getDictEntryTableName(), jsonNode);

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

        Query query = getExeuteQuery(sqlCreator, completeSql);
        query.executeUpdate();
    }
}