package com.bocloud.ims.repository.resource.hmc;

import com.alibaba.fastjson.JSON;
import com.bocloud.common.model.Pager;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.MapTools;
import com.bocloud.database.core.intf.impl.JdbcGenericDao;
import com.bocloud.database.utils.QueryBuilder;
import com.bocloud.ims.entity.resource.hmc.HmcPartition;
import com.bocloud.ims.entity.resource.hmc.HmcVirtualDisk;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @author ShaolongTan
 */
@Deprecated
@Component("hmcPartitionRepository")
public class HmcPartitionRepository extends JdbcGenericDao<HmcPartition, Long> {
    private static Logger logger = LoggerFactory.getLogger(HmcPartitionRepository.class);

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

    public List<HmcPartition> list(int page, int rows, List<Param> params, Map<String, String> sorter, Long vendorId,
                                   String serverName, Long tenantId, Long userId) {
        String sql = "select a.*, h.name server_name from hmc_partition a "
                + "left join hmc_server h on a.server_id = h.id " + "left join cloud_vendor c on h.vendor_id = c.id "
                + "where a.is_deleted = 0";
        if (null != vendorId) {
            sql += " and h.vendor_id = " + vendorId;
        }
        if (null != tenantId) {
            sql += " and a.tenant_id =  " + tenantId;
        }

        if (null != userId) {
            sql += " and a.creator_id =  " + userId;
        }
        if (null != serverName) {
            sql += " and h.name =  '" + serverName + "'";
        }
        sql = QueryBuilder.buildRaw(sql, new Pager(page, rows, params, sorter), "a");
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        return this.list(HmcPartition.class, sql, paramMap);
    }

    public List<SimpleBean> list(List<Param> params, Map<String, String> sorter, Long tenantId, Long userId) {
        String sql = "select a.id, a.name, a.hmc_partition_id from hmc_partition a where a.is_deleted = 0";
        if (null != tenantId) {
            sql += " and a.tenant_id =  " + tenantId;
        }

        if (null != userId) {
            sql += " and a.creator_id =  " + userId;
        }
        sql = QueryBuilder.build(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a");
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        List<HmcPartition> pars = this.list(HmcPartition.class, sql, paramMap);
        List<SimpleBean> beans = new ArrayList<SimpleBean>();
        for (HmcPartition par : pars) {
            beans.add(new SimpleBean(par.getId(), par.getName(),
                    par.getHmcPartitionId() == null ? null : par.getHmcPartitionId().toString()));
        }
        return beans;
    }

    public List<HmcPartition> listByVendorId(Long vendorId, String partitionType) {
        return this.list(vendorId, partitionType, null, null);
    }

    public List<HmcPartition> list(Long vendorId, String partitionType, Long serverId, String status) {
        Objects.requireNonNull(vendorId, "vendorId");

        StringBuilder sqlBuffer = new StringBuilder();
        sqlBuffer.append("select a.* from hmc_partition a ");
        sqlBuffer.append(" inner join hmc_server b on a.server_id = b.id ");
        sqlBuffer.append(" where a.is_deleted = 0 and b.vendor_id = :vendorId ");
        if (StringUtils.isNotEmpty(partitionType)) {
            sqlBuffer.append("   and a.partition_type = :partitionType ");
        }
        if (StringUtils.isNotEmpty(status)) {
            sqlBuffer.append("   and a.status = :status ");
        }
        if (serverId != null) {
            sqlBuffer.append("   and a.server_id = :serverId ");
        }

        Map<String, Object> params = new HashMap<>();
        params.put("vendorId", vendorId);
        if (StringUtils.isNotEmpty(partitionType)) {
            params.put("partitionType", partitionType);
        }
        if (StringUtils.isNotEmpty(status)) {
            params.put("status", status);
        }
        if (serverId != null) {
            params.put("serverId", serverId);
        }

        return this.list(HmcPartition.class, sqlBuffer.toString(), params);
    }

    public List<HmcPartition> listByServerId(Long serverId) {
        String sql = "select a.* from hmc_partition a where a.is_deleted = 0 and a.server_id = :serverId";
        Map<String, Object> params = MapTools.simpleMap("serverId", serverId);
        return this.list(HmcPartition.class, sql, params);
    }

    public boolean remove(Long id, Long userId) {
        String sql = "update hmc_partition set is_deleted = true , gmt_modify = :gmtModify ,mender_id = :menderId where is_deleted = 0 and id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        params.put("menderId", userId);
        params.put("gmtModify", new Date());
        return this.execute(sql, params) > 0;
    }

    public int count(List<Param> params, Long vendorId, String serverName, Long tenantId, Long userId) {
        String sql = "select count(1) from hmc_partition a " + "left join hmc_server h on a.server_id = h.id "
                + "left join cloud_vendor c on h.vendor_id = c.id " + "where a.is_deleted = 0";
        if (null != vendorId) {
            sql += " and h.vendor_id = " + vendorId;
        }
        if (null != tenantId) {
            sql += " and a.tenant_id =  " + tenantId;
        }

        if (null != userId) {
            sql += " and a.creator_id =  " + userId;
        }
        if (null != serverName) {
            sql += " and h.name =  '" + serverName + "'";
        }
        sql = QueryBuilder.buildRaw(sql, params, null, "a");
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        return this.countQuery(sql, paramMap).intValue();
    }

    public HmcPartition getMaxPartitionByServerId(Long serverId) {
        String sql = "select a.* from hmc_partition a where a.is_deleted = 0 and a.server_id = :serverId order by hmc_partition_id desc limit 1";
        Map<String, Object> params = MapTools.simpleMap("serverId", serverId);
        List<HmcPartition> list = this.list(HmcPartition.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public HmcPartition getServicePartitionByServerId(Long serverId) {
        String sql = "select a.* from hmc_partition a where a.is_deleted = 0 and a.server_id = :serverId and a.service_partition = 1 limit 1";
        Map<String, Object> params = MapTools.simpleMap("serverId", serverId);
        List<HmcPartition> list = this.list(HmcPartition.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public HmcPartition get(Integer hmcPartitionId, Long serverId) {
        String sql = "select a.* from hmc_partition a where a.is_deleted = 0 and a.hmc_partition_id = :hmcPartitionId"
                + " and a.server_id = :serverId";
        Map<String, Object> params = MapTools.simpleMap("hmcPartitionId", hmcPartitionId);
        params.put("serverId", serverId);
        List<HmcPartition> list = this.list(HmcPartition.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        if (list.size() != 1) {
            logger.warn("使用hmc的id{}和serverId {}查询的分区结果重复:{}", hmcPartitionId, serverId, list);
        }
        return list.get(0);
    }

    public HmcPartition getById(Long id) {
        String sql = "select a.* from hmc_partition a where a.is_deleted = 0 and a.id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        List<HmcPartition> list = this.list(HmcPartition.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public HmcPartition getByHmcPartitionId(Integer hmcPartitionId, Long serverId) {
        String sql = "select a.* from hmc_partition a where a.is_deleted = 0 and "
                + "a.hmc_partition_id = :hmcPartitionId and a.server_id = :serverId";
        Map<String, Object> params = MapTools.simpleMap("hmcPartitionId", hmcPartitionId);
        params.put("serverId", serverId);
        List<HmcPartition> list = this.list(HmcPartition.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public HmcPartition getLatestByHmcPartitionId(Integer hmcPartitionId, Long serverId) {
        String sql = "select a.* from hmc_partition a where "
                + "a.hmc_partition_id = :hmcPartitionId and a.server_id = :serverId order by id desc";
        Map<String, Object> params = MapTools.simpleMap("hmcPartitionId", hmcPartitionId);
        params.put("serverId", serverId);
        List<HmcPartition> list = this.list(HmcPartition.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public List<HmcPartition> getByTopProcessor(Long vendorId, String topType, int limitNum) {
        StringBuilder sb = new StringBuilder();

        sb.append("select a.name, a.processor/c.installed_system_processor_units value ");
        sb.append("  from hmc_partition a ");
        sb.append(" inner join hmc_server b on b.id = a.server_id ");
        sb.append(" inner join hmc_system_processor_config c on c.server_id = b.id ");
        sb.append(" where a.is_deleted = 0 ");
        sb.append("   and b.is_deleted = 0 ");
        sb.append("   and c.installed_system_processor_units > 0 ");
        sb.append("   and b.vendor_id = :vendorId ");
        sb.append("  order by value ");
        if ("MAX".equals(topType)) {
            sb.append("desc");
        } else {
            sb.append("asc");
        }
        sb.append("  limit ");
        sb.append(limitNum);

        String sql = sb.toString();

        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        List<HmcPartition> list = this.list(HmcPartition.class, sql, params);

        return list;
    }

    public List<HmcPartition> getByTopMemory(Long vendorId, String topType, int limitNum) {
        StringBuilder sb = new StringBuilder();

        sb.append("select a.name, a.memory/c.installed_system_memory value ");
        sb.append("  from hmc_partition a ");
        sb.append(" inner join hmc_server b on b.id = a.server_id ");
        sb.append(" inner join hmc_system_memory_config c on c.server_id = b.id ");
        sb.append(" where a.is_deleted = 0 ");
        sb.append("   and b.is_deleted = 0 ");
        sb.append("   and c.installed_system_memory > 0 ");
        sb.append("   and b.vendor_id = :vendorId ");
        sb.append("  order by value ");
        if ("MAX".equals(topType)) {
            sb.append("desc");
        } else {
            sb.append("asc");
        }
        sb.append("  limit ");
        sb.append(limitNum);

        String sql = sb.toString();

        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        List<HmcPartition> list = this.list(HmcPartition.class, sql, params);

        return list;
    }

    public List<HmcVirtualDisk> getScsiDisk(long partitionId, int adapterId) {
        String sql = "select lpc.disk_name, lpc.group_name, lpc.disk_capacity, lpc.type " +
                "from hmc_partition_scsi_adapter lpar_scsi " +
                "join hmc_partition_scsi_adapter vios_scsi  " +
                "  on lpar_scsi.remote_partition_id = vios_scsi.partition_id  " +
                "  and lpar_scsi.remote_slot_number = vios_scsi.adapter_id " +
                "join ( " +
                "  select lv.disk_name, vg.group_name, lv.disk_capacity, lv.vios_id, lv.vios_slot_id, 'lv' as type " +
                "  from hmc_virtual_disk lv join hmc_volume_group vg ON lv.vg_id = vg.id union all " +
                "  select pv.volume_name, '-', pv.volume_capacity, pv.vios_id, pv.vios_slot_id, 'pv' " +
                "  from hmc_physical_disk pv union all " +
                "  select cd.cd_name, '-', cd.cd_size, cd.vios_id, cd.vios_slot, 'cd' " +
                "  from hmc_virtual_cd cd " +
                ") lpc on vios_scsi.partition_id = lpc.vios_id and vios_scsi.adapter_id = lpc.vios_slot_id " +
                "where lpar_scsi.partition_id = :partitionId and lpar_scsi.adapter_id = :adapterId";
        Map<String, Object> params = new HashMap<>();
        params.put("partitionId", partitionId);
        params.put("adapterId", adapterId);
        List<Map<String, Object>> list = list(sql, params);
        return JSON.parseArray(JSON.toJSONString(list), HmcVirtualDisk.class);
    }

    public HmcPartition getByUuid(String uuid) {
        String sql = "select a.* from hmc_partition a where a.is_deleted = 0 and a.uuid = :uuid";
        Map<String, Object> params = new HashMap<>();
        params.put("uuid", uuid);
        List<HmcPartition> partitions = list(HmcPartition.class, sql, params);
        return partitions == null || partitions.size() == 0 ? null : partitions.get(0);
    }
}
