package com.bocloud.ims.repository.topology;

import com.bocloud.common.model.Param;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.MapTools;
import com.bocloud.database.core.intf.impl.BasicGenericDao;
import com.bocloud.database.utils.PageHelper;
import com.bocloud.ims.entity.topology.Instance;
import com.bocloud.ims.entity.topology.InstanceValue;
import com.bocloud.ims.entity.topology.Property;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Instance Dao层实现类
 *
 * @author lyy
 * @Version 1.0
 * @since 2017年9月15日
 */
@Repository("instanceRepository")
public class InstanceRepository extends BasicGenericDao<Instance, Long> {

    @Autowired
    private InstanceValueRepository instanceValueRepository;

    public InstanceRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate) {
        super(jdbcTemplate, npJdbcTemplate);
    }

    public List<Map<String, Object>> list(int page, int rows, List<Param> params, Map<String, String> sorter,
                                          List<Property> propertiesAll, Boolean simple, Boolean showTitle) throws Exception {
        String moduleId = getField(params, "moduleId");
        if (moduleId == null) {
            throw new Exception("查询失败");
        }
        String sql = buildSql(moduleId, page, rows, params, sorter, propertiesAll, simple);
        List<Map<String, Object>> list = this.list(sql);
        if (list == null) {
            list = new ArrayList<>();
        }
        // simple是true的话 就多给出title
        if (showTitle != null && showTitle) {
            for (Map<String, Object> map : list) {
                InstanceValue instanceValue = instanceValueRepository.queryTitleByInstanceId((Long) map.get("id"));
                if (instanceValue != null) {
                    map.put("bname", instanceValue.getPropertyValue());
                }
            }
        }
        return list;
    }

    private String buildSql(String moduleId, int page, int rows, List<Param> params, Map<String, String> sorter,
                            List<Property> propertiesAll, Boolean simple) throws Exception {
        // 行转列的表头
        String sql = "SELECT GROUP_CONCAT('MAX(IF(PRO.ID = ',PRO.id,',PV.PROPERTY_VALUE,NULL)) AS ''',lower(PRO.code),'''') as sqlResult"
                + " from ci_property AS PRO  where module_id=" + moduleId;

        String sqlResult;
        // 只查询选中的列
        if (propertiesAll != null && propertiesAll.size() > 0) {
            StringBuilder whereSql = new StringBuilder();
            boolean checkedFlag = false;
            whereSql.append(" and id in(");
            for (Iterator<Property> iterator = propertiesAll.iterator(); iterator.hasNext(); ) {
                Property property = (Property) iterator.next();
                if (property.getChecked()) {
                    whereSql.append(property.getId()).append(",");
                    checkedFlag = true;
                }
            }
            if (checkedFlag) {
                sql += whereSql.substring(0, whereSql.length() - 1) + ")";
                List<Map<String, Object>> result = this.list(sql);
                if (result == null || result.isEmpty()) {
                    throw new Exception("查询失败，模型无法使用");
                }
                sqlResult = result.get(0).get("sqlResult").toString();
            } else {
                sqlResult = "";
            }
        } else {
            sqlResult = "";
        }
        // 拼接sql
        StringBuilder sqlBuilder = new StringBuilder();
        sqlBuilder.append("SELECT ins.id,ins.b_name as bname,ins.module_id");
        if (sqlResult != null && !"".equals(sqlResult)) {
            sqlBuilder.append(",");
            sqlBuilder.append(sqlResult);
        }
        sqlBuilder.append(" FROM	ci_instance ins");
        sqlBuilder.append(" LEFT JOIN ci_instance_value AS PV ON ins.ID = PV.instance_id ");
        sqlBuilder.append(
                "LEFT JOIN ci_property AS PRO ON ins.module_id = PRO.module_id and PV.property_id=PRO.id  where 1=1 and ins.is_deleted=0 and ins.b_name is not null ");
        sqlBuilder.append(" and ins.module_id=" + moduleId);
        String search = getField(params, "bname");
        if (search != null) {
            sqlBuilder
                    .append(" and (exists( select 1 from ci_instance_value v LEFT JOIN ci_property_item it on it.property_id=v.property_id and v.property_value=it.value where  v.instance_id=ins.id and (v.property_value  like "
                            + "\'%" + search.trim() + "%\' or it.name  like " + "\'%" + search.trim() + "%\')) "
                            + "or exists(select 1 from ci_instance_grid g where g.instance_id = ins.id and ("
                            + "desc1 like  \'%" + search.trim() + "%\' " + "or desc2 like  \'%" + search.trim() + "%\' "
                            + "or desc3 like  \'%" + search.trim() + "%\' " + "or desc4 like  \'%" + search.trim()
                            + "%\' " + "or desc5 like  \'%" + search.trim() + "%\' " + "or desc6 like  \'%"
                            + search.trim() + "%\' " + "or desc7 like  \'%" + search.trim() + "%\' "
                            + "or desc8 like  \'%" + search.trim() + "%\' " + "or desc9 like  \'%" + search.trim()
                            + "%\' " + "or desc10 like  \'%" + search.trim() + "%\' " + "or desc11 like  \'%"
                            + search.trim() + "%\' " + "or desc12 like  \'%" + search.trim() + "%\' "
                            + "or desc13 like  \'%" + search.trim() + "%\' " + "or desc14 like  \'%" + search.trim()
                            + "%\' " + "or desc15 like  \'%" + search.trim() + "%\' " + "or desc16 like  \'%"
                            + search.trim() + "%\' " + "or desc17 like  \'%" + search.trim() + "%\' "
                            + "or desc18 like  \'%" + search.trim() + "%\' " + "or desc19 like  \'%" + search.trim()
                            + "%\' " + "or desc20 like  \'%" + search.trim() + "%\' " + "or desc21 like  \'%"
                            + search.trim() + "%\' " + "or desc22 like  \'%" + search.trim() + "%\' "
                            + "or desc23 like  \'%" + search.trim() + "%\' " + "or desc24 like  \'%" + search.trim()
                            + "%\' " + "or desc25 like  \'%" + search.trim() + "%\' " + "or desc26 like  \'%"
                            + search.trim() + "%\' " + "or desc27 like  \'%" + search.trim() + "%\' "
                            + "or desc28 like  \'%" + search.trim() + "%\' " + "or desc29 like  \'%" + search.trim()
                            + "%\' " + "or desc30 like  \'%" + search.trim() + "%\')))");
        }
        sqlBuilder.append(" GROUP BY ins.ID order by ins.id desc");

        sql = sqlBuilder.toString();
        if (simple == null || simple.booleanValue() == false) {
            if (page != 0) {
                sql += PageHelper.buildPageSql(page, rows);
            }
        }
        return sql;
    }

    /**
     * 从params找到moduleid
     *
     * @param params
     * @return
     */
    public String getField(List<Param> params, String field) {

        if ((null != params) && (!params.isEmpty())) {
            for (Param param : params) {
                for (String key : param.getParam().keySet()) {
                    if (field.equals(key)) {
                        return param.getParam().get(key).toString();
                    }
                }
            }
        }
        return null;
    }

    public Instance query(Long id) throws Exception {
        String sql = "select * from ci_instance a where a.id = :id and a.is_deleted=0";
        Map<String, Object> params = MapTools.simpleMap(Common.ID, id);
        List<Instance> instance = this.list(Instance.class, sql, params);
        if (instance.isEmpty()) {
            return null;
        }
        return instance.get(0);
    }

    public Instance queryByBname(Long moduleId, String bname) throws Exception {
        String sql = "select * from ci_instance a where a.b_name = :bname and a.module_id=:moduleId and a.is_deleted=0";
        Map<String, Object> params = MapTools.simpleMap("bname", bname);
        params.put("moduleId", moduleId);
        List<Instance> instance = this.list(Instance.class, sql, params);
        if (instance.isEmpty()) {
            return null;
        }
        return instance.get(0);
    }

    public Instance queryByBnameOrTitle(Long moduleId, String bname) throws Exception {
        String sql = "select * from ci_instance a where a.module_id=:moduleId and a.is_deleted=0 and (a.b_name = :bname or exists("
                + "select 1 from ci_instance_value v ,ci_property p where v.instance_id=a.id and p.id=v.property_id and p.is_title=1 and v.property_value=:bname))";
        Map<String, Object> params = MapTools.simpleMap("bname", bname);
        params.put("moduleId", moduleId);
        List<Instance> instance = this.list(Instance.class, sql, params);
        if (instance.isEmpty()) {
            return null;
        }
        return instance.get(0);

    }

    public Instance uniqueValidateByBname(Long moduleId, String bname, Long id) throws Exception {
        String sql = "select * from ci_instance a where a.b_name = :bname and a.module_id=:moduleId and a.is_deleted=0 and id!=:id";
        Map<String, Object> params = MapTools.simpleMap("bname", bname);
        params.put("moduleId", moduleId);
        params.put("id", id);
        List<Instance> instance = this.list(Instance.class, sql, params);
        if (instance.isEmpty()) {
            return null;
        }
        return instance.get(0);
    }

    public boolean delete(Long id) throws Exception {
        String sql = "update  ci_instance set is_deleted=1 where id = :id";
        Map<String, Object> params = MapTools.simpleMap(Common.ID, id);
        return this.execute(sql, params) > 0;
    }

    public int count(List<Param> params) throws Exception {
        String moduleId = getField(params, "moduleId");
        if (moduleId == null) {
            throw new Exception("查询失败");
        }
        String sql = buildSql(moduleId, 0, 0, params, null, null, false);
        sql = "select count(1) from (" + sql + ") B";
        return this.countQuery(sql, null).intValue();
    }

    public int countSimple(Long moduleId) throws Exception {
        String sql = "select count(1) from ci_instance where is_deleted=0 and b_name is not null and module_id=:moduleId";
        Map<String, Object> params = MapTools.simpleMap("moduleId", moduleId);
        return this.countQuery(sql, params).intValue();
    }

    public List<Instance> listAll(Long moduleId) throws Exception {
        String sql = "select * from ci_instance a where a.module_id = :moduleId  and a.is_deleted=0 and b_name is not null order by a.id desc";
        Map<String, Object> params = MapTools.simpleMap("moduleId", moduleId);
        List<Instance> list = this.list(Instance.class, sql, params);
        List<Instance> instances = new ArrayList<>();
        for (Object object : list) {
            instances.add((Instance) object);
        }
        return instances;
    }

    public List<Instance> queryByModuleId(Long moduleId) throws Exception {
        String sql = "select * from ci_instance a where a.module_id = :moduleId and a.is_deleted=0";
        Map<String, Object> params = MapTools.simpleMap("moduleId", moduleId);
        List<Instance> list = this.list(Instance.class, sql, params);
        return list;
    }

    public List<Instance> queryByModuleId(Long sourceId, Long targetId) throws Exception {
        String sql = "select * from ci_instance a where (a.module_id = :sourceId or a.module_id = :targetId) and a.is_deleted=0";
        Map<String, Object> params = MapTools.simpleMap("sourceId", sourceId);
        params.put("targetId", targetId);
        List<Instance> instanceList = this.list(Instance.class, sql, params);
        return instanceList;
    }

    public boolean deleteByModuleId(Long moduleId) throws Exception {
        String sql = "update ci_instance set is_deleted=1 where module_id = :moduleId and is_deleted=0";
        Map<String, Object> params = MapTools.simpleMap("moduleId", moduleId);
        return this.execute(sql, params) > 0;
    }

    public Instance uniqueValidateByProperty(Long moduleId, Long instanceId, String propertyCode, String propertyValue)
            throws Exception {
        String sql = "select a.* from ci_instance a,ci_instance_value b where a.id=b.instance_id and a.id !=:instanceId and a.is_deleted=0 and a.module_id=:moduleId and b.property_code=:propertyCode and b.property_value=:propertyValue";
        Map<String, Object> params = MapTools.simpleMap("moduleId", moduleId);
        params.put("instanceId", instanceId);
        params.put("propertyCode", propertyCode);
        params.put("propertyValue", propertyValue);
        List<Instance> instance = this.list(Instance.class, sql, params);
        if (instance.isEmpty()) {
            return null;
        }
        return instance.get(0);
    }

    public Instance queryByUuid(String uuid) throws Exception {
        String sql = "select * from ci_instance a where a.uuid = :uuid and a.is_deleted=0";
        Map<String, Object> params = MapTools.simpleMap("uuid", uuid);
        List<Instance> instance = this.list(Instance.class, sql, params);
        if (instance.isEmpty()) {
            return null;
        }
        return instance.get(0);
    }

    public boolean deletePhysical(Long id) throws Exception {
        String sql = "delete  ci_instance  where id=:id";
        Map<String, Object> params = MapTools.simpleMap(Common.ID, id);
        return this.execute(sql, params) > 0;
    }

    public Map<Long, Instance> queryAll() throws Exception {
        String sql = "select * from ci_instance a where a.is_deleted=0";
        List<Instance> list = this.list(Instance.class, sql, null);
        Map<Long, Instance> map = Maps.newHashMap();
        if (list.isEmpty()) {
            return map;
        }
        for (Instance instance : list) {
            map.put(instance.getId(), instance);
        }
        return map;
    }

    public List<Instance> queryQuoteByInstanceId(List<Long> propertyIds, Long instanceId) throws Exception {
        String sql = "select ins.* from ci_instance ins,ci_instance_value v where ins.id=v.instance_id and ins.is_deleted=0 and v.property_value=:instanceId and v.property_id in (:propertyIds) ";
        Map<String, Object> paramMap = MapTools.simpleMap("instanceId", instanceId);
        paramMap.put("propertyIds", propertyIds);
        List<Instance> list = this.list(Instance.class, sql, paramMap);
        return list;
    }
}
