package com.bawei.es.service.impl;

import com.bawei.common.core.exception.ServiceException;
import com.bawei.es.service.IndexService;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.cluster.metadata.MappingMetadata;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Map;

/**
 * @Author: 31966
 * @Project: mall-product
 * @Package: com.bwie.es.service.impl
 * @ClassName: EsServiceImpl
 * @Description: 请在此处填写具体描述
 * @Date: 2024/4/22 20:56
 */
@Service
public class IndexServiceImpl implements IndexService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public boolean exist(String indexName) {
        if (indexName == null || indexName.isEmpty()){
            throw new ServiceException("索引名称不能为空");
        }
        try {
            GetIndexRequest request = new GetIndexRequest(indexName);
            GetIndexResponse response = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);
            // 检查响应中是否包含指定的索引
            for (String index : response.getIndices()) {
                if (index.equals(indexName)){
                    return true;
                }
            }
        } catch (Exception e) {
            // 处理异常，例如记录日志或返回false表示索引不存在
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean index(String indexName, Map<String, Object> mappings) {
        // 参数校验
        if (indexName == null || indexName.isEmpty()) {
            throw new ServiceException("Index name cannot be null or empty");
        }
        // 判断索引是否存在
        boolean indexExists = exist(indexName);
        if (indexExists) {
            throw new ServiceException("索引 " + indexName + " 已存在");
        }
        // 创建索引并设置映射（根据mappings非空情况）
        try {
            Settings.Builder settingsBuilder = Settings.builder();
            XContentBuilder mappingBuilder = null;

            if (mappings != null && !mappings.isEmpty()) {
                // 设置映射
                mappingBuilder = createMapping(mappings);
            }

            CreateIndexRequest request = new CreateIndexRequest(indexName)
                    .settings(settingsBuilder);
            if (mappingBuilder!=null){
                request.mapping(mappingBuilder);
            }
            CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
            return response.isAcknowledged();
        } catch (IOException e) {
            System.err.println("创建索引时发生错误: " + e.getMessage());
            throw new ServiceException("创建索引时发生错误");
        }
    }

    @Override
    public boolean updataIndex(String indexName, Map<String, Object> mappings) {
        try {
            if (indexName!=null && !indexName.isEmpty()){
                if (Boolean.FALSE.equals(exist(indexName))) {
                    index(indexName,mappings);
                    return true;
                }else {
                    deleteIndex(indexName);
                    index(indexName,mappings);
                    return true;
                }
            }else {
                throw new ServiceException("索引名字为空,请重试!!!");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean deleteIndex(String indexName) {
        // 删除索引
        try {
            restHighLevelClient.indices().delete(new DeleteIndexRequest(indexName), RequestOptions.DEFAULT);
            return true;
        } catch (Exception e) {
            System.err.println("Error deleting index: " + e.getMessage());
            throw new ServiceException("Error deleting index");
        }
    }

    @Override
    public Map<String, Object> getMapping(String indexName) {
        if (indexName == null || indexName.isEmpty()) {
            throw new  ServiceException("索引名称不能为空");
        }
        try {
            GetIndexRequest request = new GetIndexRequest(indexName);
            GetIndexResponse response = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);

            // 检查响应中是否包含指定的索引
            for (String index : response.getIndices()) {
                if (index.equals(indexName)) {
                    Map<String, MappingMetadata> mappings = response.getMappings();

                    // 提取并返回指定索引的映射结构
                    MappingMetadata mappingMetadata = mappings.get(indexName);
                    if (mappingMetadata != null) {
                        Map<String,Object> map = (Map<String, Object>) mappingMetadata.getSourceAsMap().get("properties");
                        if (map==null){
                            throw new ServiceException("索引映射为空");
                        }
                        return map;
                    }
                }
            }
        } catch (Exception e) {
            // 处理异常，例如记录日志
            e.printStackTrace();
        }

        // 索引不存在或获取映射失败，返回null
        throw new ServiceException("索引不存在,请重试");
    }

    /**
     * 根据给定的映射创建XContentBuilder
     */
    private XContentBuilder createMapping(Map<String, Object> mappings) throws IOException {
        XContentBuilder builder = XContentFactory.jsonBuilder()
                .startObject()
                .startObject("properties");

        for (Map.Entry<String, Object> entry : mappings.entrySet()) {
            String fieldName = entry.getKey();
            Object fieldConfig = entry.getValue();

            builder.startObject(fieldName); // Start field mapping

            if (fieldConfig instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> nestedMapping = (Map<String, Object>) fieldConfig;

                for (Map.Entry<String, Object> nestedEntry : nestedMapping.entrySet()) {
                    String nestedFieldName = nestedEntry.getKey();
                    Object nestedFieldConfig = nestedEntry.getValue();

                    builder.field(nestedFieldName, nestedFieldConfig);
                }
            } else {
                builder.field("type", fieldConfig.toString()); // Add field type
            }

            builder.endObject(); // End field mapping
        }

        builder.endObject() // End "properties"
                .endObject(); // End root object

        return builder;
    }

}
