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


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.Select2;
import com.yihu.hos.standard.model.standard.StdDictionaryEntryModel;
import com.yihu.hos.standard.model.standard.StdDictionaryModel;
import com.yihu.hos.standard.service.bo.StandardVersion;
import com.yihu.hos.web.framework.constant.ErrorCode;
import com.yihu.hos.web.framework.constant.SqlConstants;
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.DictItem;
import com.yihu.hos.web.framework.model.DictionaryResult;
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.RequestParamTransformer;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;

/**
 * @author Sand
 * @version 1.0
 * @created 14-7月-2015 15:44:21
 */
@Transactional
@Service("StdDictService")
public class StdDictService extends SQLGeneralDAO {

    public static final String BEAN_ID = "StdDictService";
    @Autowired
    StdDictEntryService stdDictEntryService;

    public StdDictService() {
    }

    public void finalize() throws Throwable {

    }

    public List<StdDictionaryModel> getList(String stdVersion, String condition, String order, Integer limit, Integer offset) {
        try{
            Map<String, Object> queryMap = RequestParamTransformer.parseJsonToMap(condition);
            Map<String, String> orderMap = RequestParamTransformer.parseJsonToMap(order);
            StandardVersion standardVersion = new StandardVersion(stdVersion);
            return this.getList(standardVersion, queryMap, orderMap, limit, offset);
        }catch (Exception e){
            e.printStackTrace();
        }

        throw new ApiException(ErrorCode.StandardDictGetListFailed);
    }

    public Result add(String stdVersion, String dict) {
        Boolean existFlg = false;
        try {
            StandardVersion standardVersion = new StandardVersion(stdVersion);

            StdDictionaryModel stdDictionaryModel = objectMapper.readValue(dict, StdDictionaryModel.class);
            existFlg = dictCodeValidate(standardVersion, stdDictionaryModel.getCode());
            if (!existFlg) {
                this.add(standardVersion, stdDictionaryModel);

                //取得新增字典表记录
                Map<String, Object> query = new HashMap<>();
                Map<String, String> order = new HashMap<>();
                query.put("code", stdDictionaryModel.getCode());

                List<StdDictionaryModel> list = this.getList(standardVersion, query, order, 1, 0);
                Integer id = list.get(0).getId();
                Integer parentId = list.get(0).getParentId();
                if (parentId != null) {
                    Map<String, Object> query1 = new HashMap<>();
                    Map<String, String> order1 = new HashMap<>();
                    query1.put("dictId", parentId);
                    List<StdDictionaryEntryModel> dicEntryList = this.getDicEntryList(standardVersion,query1,order,null,null);
                    for (StdDictionaryEntryModel entryModel : dicEntryList) {
                        StdDictionaryEntryModel model =  new StdDictionaryEntryModel();
                        model.setDictId(id);
                        model.setstandardId(entryModel.getstandardId());
                        model.setCode(entryModel.getCode());
                        model.setValue(entryModel.getValue());
                        model.setDescription(entryModel.getDescription());
                        stdDictEntryService.add(standardVersion,model);
                    }
                }

                stdDictionaryModel.setSuccessFlg(true);
                stdDictionaryModel.setMessage("保存标准字典成功");
                return stdDictionaryModel;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (existFlg) {
            return Result.error("已存在标准字典编码");
        } else {
            return Result.error("保存标准字典失败");
        }
    }

    public Boolean dictCodeValidate(StandardVersion standardVersion, String code) {
        Map<String, Object> query = new HashMap<>();
        Map<String, String> order = new HashMap<>();
        query.put("code", code);

        List<StdDictionaryModel> list = this.getList(standardVersion, query, order, 1, 0);
        if (!CollectionUtil.isEmpty(list)) {
            return true;
        }
        return false;
    }

    public Result delete(String stdVersion, Integer dictId) {
        try {
            StandardVersion standardVersion = new StandardVersion(stdVersion);
            if (dictId != null) {
                this.delete(standardVersion, dictId);
                return Result.success("删除标准字典成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.success("删除标准字典失败");
    }

    public Boolean dictCodeValidate(StandardVersion standardVersion, Integer dictId, String code) {
        SqlCreator sqlCreator = new SqlCreator(StdDictionaryModel.class);
        sqlCreator.equalCondition("code", code);
        sqlCreator.neCondition("id", dictId);
        String sql = sqlCreator.selectData(standardVersion.getDictTableName());
        Query sessionQuery = getQuery(sqlCreator, sql);
        List<StdDictionaryModel> list = sessionQuery.list();
        if (!CollectionUtil.isEmpty(list)) {
            return true;
        }
        return false;
    }

    public Result update(String stdVersion, String dict) {
        Boolean existFlg = false;
        try {
            StandardVersion standardVersion = new StandardVersion(stdVersion);

            StdDictionaryModel stdDictionaryModel = objectMapper.readValue(dict, StdDictionaryModel.class);
            existFlg = dictCodeValidate(standardVersion, stdDictionaryModel.getId(), stdDictionaryModel.getCode());
            if (!existFlg) {
                this.modify(standardVersion, stdDictionaryModel);
                stdDictionaryModel.setSuccessFlg(true);
                stdDictionaryModel.setMessage("修改标准字典成功");
                return stdDictionaryModel;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (existFlg) {
            return Result.error("已存在标准字典编码");
        } else {
            return Result.error("修改标准字典失败");
        }
    }

    public Result get(String stdVersion, Integer dictId) {
        try {
            StandardVersion standardVersion = new StandardVersion(stdVersion);
            if (dictId != null) {
                StdDictionaryModel stdDictionaryModel = this.get(standardVersion, dictId);
                stdDictionaryModel.setSuccessFlg(true);
                stdDictionaryModel.setMessage("获取标准字典成功");
                return stdDictionaryModel;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.error("获取标准字典失败");
    }

    private StdDictionaryModel get(StandardVersion standardVersion, Integer dictId) {

        Session session = getCurrentSession();
        String dictTableName = standardVersion.getDictTableName();

        String sql = "select id, std_id, code, name, define, description, parent_id from " + dictTableName + " where id = :id";
        Query query = session.createSQLQuery(sql);
        query.setInteger("id", dictId);
        query.setResultTransformer(new BeanTransformer<>(StdDictionaryModel.class));
        return (StdDictionaryModel) query.uniqueResult();
    }

    private void modify(StandardVersion standardVersion, StdDictionaryModel stdDictionaryModel) throws IOException {
        String strTableName = standardVersion.getDictTableName();
        JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(stdDictionaryModel));
        SqlCreator sqlCreator = new SqlCreator(StdDictionaryModel.class);
        String sql = sqlCreator.updateDataByTableKey(strTableName, jsonNode);
        Query query = getExeuteQuery(sqlCreator, sql);
        query.executeUpdate();
    }

    private void delete(StandardVersion standardVersion, Integer dictId) {
        Session session = getCurrentSession();
        String sql = "delete from " + standardVersion.getDictTableName() + " where id = :id";
        Query query = session.createSQLQuery(sql);
        query.setInteger("id", dictId);
        query.executeUpdate();
        sql = "delete from " + standardVersion.getDictEntryTableName() + " where dict_id = :dictId";
        query = session.createSQLQuery(sql);
        query.setInteger("dictId", dictId);
        query.executeUpdate();
    }

    public void add(StandardVersion standardVersion, StdDictionaryModel stdDictionaryModel) throws IOException {
        Session session = getCurrentSession();
        String strTableName = standardVersion.getDictTableName();
        String sql = null;
        sql = "select max(id) from " + strTableName;

        Query query = session.createSQLQuery(sql);
        Object object = query.uniqueResult();
        Integer id = object == null ? 1 : Integer.parseInt(object.toString()) + 1;
        stdDictionaryModel.setId(id);

        JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(stdDictionaryModel));
        SqlCreator sqlCreator = new SqlCreator(StdDictionaryModel.class);
        sql = sqlCreator.insertData(strTableName, jsonNode);
        query = getExeuteQuery(sqlCreator, sql);
        query.executeUpdate();
    }

    private List<StdDictionaryModel> getList(StandardVersion standardVersion, Map<String, Object> query, Map<String, String> order, Integer limit, Integer offset) {
        SqlCreator sqlCreator = new SqlCreator(StdDictionaryModel.class);
        for (String key : query.keySet()) {
            sqlCreator.equalCondition(key, query.get(key));
        }
        for (String key : order.keySet()) {
            sqlCreator.order(key, order.get(key));
        }

        String sql = sqlCreator.selectData(standardVersion.getDictTableName());
        Query sessionQuery = getQuery(sqlCreator, sql);
        if (limit != null) {
            sessionQuery.setMaxResults(limit);
            if (offset != null) {
                sessionQuery.setFirstResult((offset - 1) * limit);
            }
        }
        return (List<StdDictionaryModel>) sessionQuery.list();
    }

    public List<StdDictionaryEntryModel> getDicEntryList(StandardVersion standardVersion, Map<String, Object> query, Map<String, String> order, Integer limit, Integer offset) {
        SqlCreator sqlCreator = new SqlCreator(StdDictionaryEntryModel.class);
        if(null!=query){
            for (String key : query.keySet()) {
                sqlCreator.equalCondition(key, query.get(key));
            }
        }
        if(order!=null){
            for (String key : order.keySet()) {
                sqlCreator.order(key, order.get(key));
            }
        }

        String sql = sqlCreator.selectData(standardVersion.getDictEntryTableName());
        Query sessionQuery = getQuery(sqlCreator, sql);
        if (limit != null) {
            sessionQuery.setMaxResults(limit);
            if (offset != null) {
                sessionQuery.setFirstResult((offset - 1) * limit);
            }
        }
        return (List<StdDictionaryEntryModel>) sessionQuery.list();
    }

    public List<StdDictionaryEntryModel> getDicEntryList(String schemaName,StandardVersion standardVersion, Map<String, Object> query, Map<String, String> order, Integer limit, Integer offset) {
        SqlCreator sqlCreator = new SqlCreator(StdDictionaryEntryModel.class);
        if(null!=query){
            for (String key : query.keySet()) {
                sqlCreator.equalCondition(key, query.get(key));
            }
        }
        if(order!=null){
            for (String key : order.keySet()) {
                sqlCreator.order(key, order.get(key));
            }
        }

        String sql = sqlCreator.selectData(standardVersion.getDictEntryTableName());

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

        Query sessionQuery = getQuery(sqlCreator, completeSql);
        if (limit != null) {
            sessionQuery.setMaxResults(limit);
            if (offset != null) {
                sessionQuery.setFirstResult((offset - 1) * limit);
            }
        }
        return (List<StdDictionaryEntryModel>) sessionQuery.list();
    }

    public DictionaryResult getDictionaryList(String stdVersion, String query, String order, Integer rows, Integer page) {
        try {
            List<StdDictionaryModel> stdDictionaryModelList = getList(stdVersion, query, order, rows, page);
            List<DictItem> detailModelList = new ArrayList<DictItem>();
            DictItem item = new DictItem();
            item.setCode("");
            item.setValue("-无-");
            detailModelList.add(item);
            for (StdDictionaryModel stdDictionaryModel : stdDictionaryModelList) {
                DictItem items = new DictItem();
                Integer  id = stdDictionaryModel.getId();
                String name = stdDictionaryModel.getName();
                items.setCode(id.toString());
                items.setValue(name);
                detailModelList.add(items);
            }
            DictionaryResult dictionaryResult = DictionaryResult.success("获取字典列表成功");
            dictionaryResult.setDetailModelList(detailModelList);
            return dictionaryResult;
        } catch (Exception e) {
            return DictionaryResult.error("获取字典列表失败");
        }
    }

    public DetailModelResult getDetailModelList(String stdVersion, String condition, String order, Integer rows, Integer page) {
        try {
            List<StdDictionaryModel> dictModelList = getDictList(StdDictionaryModel.class, stdVersion, condition, order, rows, page);
            Integer count = getDictInt(StdDictionaryModel.class, stdVersion, condition);
            DetailModelResult result = DetailModelResult.success("获取标准数据字典列表成功");
            result.setDetailModelList(dictModelList);
            result.setTotalCount(count);
            return result;
        } catch (Exception e) {
            return DetailModelResult.error("获取标准字典列表失败");
        }
    }

    public List getDictList(Class tClass, String stdVersion, String condition, String order, Integer limit, Integer offset) {
        StandardVersion standardVersion = new StandardVersion(stdVersion);
        String tableName = standardVersion.getDictTableName();
        SqlCreator sqlCreator = new SqlCreator(tClass);
        try {
            if (!StringUtil.isEmpty(condition)) {
                JsonNode jsonNode = objectMapper.readTree(condition);
                if(jsonNode.get("initVal")!=null && !jsonNode.get("initVal").asText().isEmpty()){
                    String initName = jsonNode.get("initVal").asText();
                    sqlCreator.equalCondition("name",initName);
                }else if(jsonNode.get("name")!=null && !jsonNode.get("name").asText().isEmpty()){
                    String name = jsonNode.get("name").asText();
                    sqlCreator.likeOrCondition("code", "name", 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 stdVersion, String condition) {
        StandardVersion standardVersion = new StandardVersion(stdVersion);
        String tableName = standardVersion.getDictTableName();
        SqlCreator sqlCreator = new SqlCreator(tClass);
        try {
            if (!StringUtil.isEmpty(condition)) {
                JsonNode jsonNode = objectMapper.readTree(condition);
                String name = jsonNode.get("name").asText();
                sqlCreator.likeOrCondition("code", "name", 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 DetailModelResult getDictSelectList(List<StdDictionaryModel> dictList) {
        try {
            List<Select2> detailModelList = new ArrayList<>();
            for (StdDictionaryModel dictModel : dictList) {
                Select2 select2 = new Select2();
                select2.setId(dictModel.getId() + SqlConstants.COMMA + dictModel.getCode());
                select2.setText(dictModel.getName());
                detailModelList.add(select2);
            }
            DetailModelResult detailModelResult = DetailModelResult.success("获取字典下来列表成功");
            detailModelResult.setDetailModelList(detailModelList);
            detailModelResult.setTotalCount(detailModelList.size());
            return detailModelResult;
        } catch (Exception e) {
            return DetailModelResult.error("获取字典下来列表失败");
        }
    }

    public StdDictionaryModel getAdapterDictByCode(String version, String dictCode) {
        try {
            SqlCreator sqlCreator = new SqlCreator(StdDictionaryModel.class);
            sqlCreator.equalCondition("code", dictCode);
            String sql = sqlCreator.selectData("std_dictentry_"+version);
            Query query = getQuery(sqlCreator, sql);
            return (StdDictionaryModel)query.uniqueResult();
        } catch (Exception e) {
            return null;
        }
    }

}
