package com.jay.monitor.data.server.store.es;

import cn.hutool.core.bean.BeanUtil;
import com.jay.monitor.data.core.model.response.PageResponseModel;
import com.jay.monitor.data.server.componts.ElasticSearchPartition;
import com.jay.monitor.data.server.utils.ESUtils;
import com.jay.monitor.data.server.utils.JayDataUtils;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.zxp.esclientrhl.repository.PageList;
import org.zxp.esclientrhl.repository.Sort;
import org.zxp.esclientrhl.util.IndexTools;
import org.zxp.esclientrhl.util.MetaData;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 通用的ES增删改查
 *
 * @param <ENTITY> ES内部Index
 * @param <REQ>    外部的传输对象
 */
public abstract class AbstractCRUDElasticSearch<ENTITY, REQ> {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    protected ElasticSearchPartition elasticSearchPartition;

    public abstract Class<ENTITY> getEntityClazz();

    public abstract Class<REQ> getReqClazz();

    public List<REQ> queryList(REQ req) {
        try {
            ENTITY entity = convertEntity(req);
            QueryBuilder queryBuilder = ESUtils.beanToQueryBuilder(entity);
            List<ENTITY> search = elasticSearchPartition.search(queryBuilder, getEntityClazz());
            return convertReqList(search);
        } catch (Exception e) {
            logger.error("es查询失败", e);
        }
        return null;
    }

    public boolean save(REQ req) {
        try {
            ENTITY entity = convertEntity(req);
            // 初始化值
            BeanUtil.setFieldValue(entity, "createDate", new Date());
            BeanUtil.setFieldValue(entity, "id", null);
            boolean save = elasticSearchPartition.save(entity);
            ESUtils.setId(req, entity);
            return save;
        } catch (Exception e) {
            logger.error("es 保存失败", e);
        }
        return false;
    }

    public boolean delete(String id) {
        try {
            return elasticSearchPartition.deleteById(id, getEntityClazz());
        } catch (Exception e) {
            logger.error("删除失败!", e);
        }
        return false;
    }

    public boolean update(REQ req) {
        try {
            ENTITY entity = convertEntity(req);
            // 初始化值
            BeanUtil.setFieldValue(entity, "updated", new Date());
            return elasticSearchPartition.update(entity);
        } catch (Exception e) {
            logger.error("es 修改失败", e);
        }
        return false;
    }

    public REQ queryById(String id) {
        try {
            ENTITY entity = (ENTITY)elasticSearchPartition.getById(id, getEntityClazz());
            return convertReq(entity);
        } catch (Exception e) {
            logger.error("查询数据失败", e);
        }
        return null;
    }

    protected REQ convertReq(ENTITY entity) throws Exception {
        if (entity == null) {
            return null;
        }
        REQ req = getReqClazz().newInstance();
        BeanUtils.copyProperties(entity, req);
        return req;
    }

    protected ENTITY convertEntity(REQ req) throws Exception {
        ENTITY entity = getEntityClazz().newInstance();
        BeanUtils.copyProperties(req, entity);
        return entity;
    }

    protected List<REQ> convertReqList(List<ENTITY> entities) throws Exception {
        if (entities == null || entities.isEmpty()) {
            return null;
        } else if (entities.size() == 1) {
            return Arrays.asList(convertReq(entities.get(0)));
        }

        List<REQ> list = new ArrayList<>();
        for (int i = 0; i < entities.size(); i++) {
            ENTITY entity = entities.get(i);
            REQ req = getReqClazz().newInstance();
            BeanUtils.copyProperties(entity, req);
            list.add(req);
        }

        return list;
    }

    public PageResponseModel<REQ> searchDataByList(Integer pageNo, Integer pageSize, REQ query) throws Exception {
        ENTITY entity = convertEntity(query);
        MetaData metaData = IndexTools.getIndexType(getEntityClazz());
        PageList pageList = elasticSearchPartition
            .searchPartitionPage(metaData.getIndexname(), entity, pageNo, pageSize,
                new Sort.Order[] {new Sort.Order(SortOrder.DESC, "createDate")});
        PageResponseModel<REQ> pageResponseModel = JayDataUtils
            .builderPageResponseModel(pageNo, pageSize, pageList.getTotalPages(), convertReqList(pageList.getList()));
        return pageResponseModel;
    }

}
