package com.goomood.es.service;

import com.goomood.common.config.GooMoodConfig;
import com.goomood.common.constant.Constants;
import com.goomood.common.utils.StringUtils;
import com.goomood.es.dto.DelFIleIndexDto;
import com.goomood.phm.domain.dto.CataiDTO;
import com.goomood.phm.utils.HttpUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.ingest.GetPipelineRequest;
import org.elasticsearch.action.ingest.GetPipelineResponse;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * @author pawn
 * @version 1.0
 * @description: 文件service
 * @date 2024/11/19 15:52
 */
@Service
public class FileService {


    @Autowired
    private RestHighLevelClient restHighLevelClient;





    /**
     * 读取文件并存储到 Elasticsearch
     *
     * @param fileAllPath 文件路径
     * @param type 所属类型
     * @param id 所属 ID
     * @param name 所属名称
     * @throws IOException 异常
     */
    public void saveOrUpdateDocument(String fileAllPath, String type, Long id, String name) throws IOException {
        // 确保 Attachment Pipeline 存在
        ensureAttachmentPipeline();

        // 拼接完整文件路径
        String localPath = GooMoodConfig.getProfile();
        String downloadPath = localPath + StringUtils.substringAfter(fileAllPath, Constants.RESOURCE_PREFIX);
        Path filePath = Paths.get(downloadPath);

        if (!Files.exists(filePath)) {
            throw new FileNotFoundException("File not found at path: " + filePath.toString());
        }

        // 生成唯一 ID
        String documentId = generateDocumentId(getFileName(fileAllPath), type, id);


        // 读取文件内容并编码为 Base64
        byte[] fileBytes = Files.readAllBytes(filePath);
        String base64Content = Base64.getEncoder().encodeToString(fileBytes);

        // 构造文档
        Map<String, Object> document = new HashMap<>();
        document.put("fileName", getFileName(fileAllPath));
        document.put("fileUrl", fileAllPath);
        document.put("fileContent", base64Content); // 将文件内容编码为 Base64
        document.put("fileType", getFileType(fileAllPath));
        document.put("belongType", type);
        document.put("belongId", id);
        document.put("belongName", name);

        // 使用 attachment Pipeline 存储文档
        IndexRequest request = new IndexRequest("file_content_index")
                .source(document)
                .id(documentId)
                .setPipeline("attachment");

        restHighLevelClient.index(request, RequestOptions.DEFAULT);
    }


    @Async("fileTaskExecutor")
    public void fileToEs(String filePaths,String type, Long id, String name){
        if(StringUtils.isNotEmpty(filePaths)){
            String []  filePathAarry = filePaths.split(",");
            for (String filePath: filePathAarry){
                try {
                    this.saveOrUpdateDocument(filePath,type,id,name);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 删除文档
     *
     * @param dto 删除文件索引入参
     * @throws IOException 异常
     */
    public void deleteDocument(DelFIleIndexDto dto) throws IOException {
        if(null == dto || dto.getBelongId() == null){
            return;
        }
        // 生成唯一 ID
        String documentId = generateDocumentId(getFileName(dto.getFilePath()), dto.getBelongType(), dto.getBelongId());
        // 删除文档
        DeleteRequest deleteRequest = new DeleteRequest("file_content_index", documentId);
        restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
    }


    /**
     * 根据所属删除
     * @param filePaths
     * @param type
     * @param id
     * @throws IOException
     */
    public void deleteDocumentByBelong(String filePaths,String type,Long id) throws IOException {
        if(StringUtils.isNotEmpty(filePaths)){
            String []  filePathAarry = filePaths.split(",");
            for (String filePath: filePathAarry){
                // 生成唯一 ID
                String documentId = generateDocumentId(getFileName(filePath), type,id);
                // 删除文档
                DeleteRequest deleteRequest = new DeleteRequest("file_content_index", documentId);
                restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
            }
        }
    }

    /**
     * 确保 Attachment Pipeline 存在
     *
     * @throws IOException 异常
     */
    private void ensureAttachmentPipeline() throws IOException {
        // 检查 Pipeline 是否存在

        try {
            GetPipelineRequest getPipelineRequest = new GetPipelineRequest("attachment");
            GetPipelineResponse o =  restHighLevelClient.ingest().getPipeline(getPipelineRequest, RequestOptions.DEFAULT);
            System.out.println(o.toString());
            if(o.toString().equals("{}")){
                // Pipeline 不存在，创建它
                createAttachmentPipeline();
            }
        } catch (ElasticsearchStatusException e) {
            if (e.status().getStatus() == 404) {
                // Pipeline 不存在，创建它
                createAttachmentPipeline();
            } else {
                throw e;
            }
        }
    }

    /**
     * 创建 Attachment Pipeline
     *
     * @throws IOException 异常
     */
    private void createAttachmentPipeline() throws IOException {
        // 定义 Pipeline 配置
        String pipelineDefinition = "{\n" +
                "  \"description\": \"Extract attachment information\",\n" +
                "  \"processors\": [\n" +
                "    {\n" +
                "      \"attachment\": {\n" +
                "        \"field\": \"fileContent\",\n" +
                "        \"indexed_chars\": -1\n" +
                "      }\n" +
                "    }\n" +
                "  ]\n" +
                "}";

        // 使用低级客户端发送请求
        Request request = new Request("PUT", "/_ingest/pipeline/attachment");
        request.setJsonEntity(pipelineDefinition);

        Response response = restHighLevelClient.getLowLevelClient().performRequest(request);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200 && statusCode != 201) {
            throw new IOException("Failed to create attachment pipeline, status code: " + statusCode);
        }
    }



    /**
     * 生成文档的唯一 ID
     *
     * @param fileName 文件名称（带后缀）
     * @param belongType 所属类型
     * @param belongId 所属 ID
     * @return 文档的唯一 ID
     */
    public static String generateDocumentId(String fileName, String belongType, Long belongId) {
        // 拼接唯一字符串，保留文件扩展名
        String source = fileName + "_" + belongType + "_" + belongId;

        try {
            // 使用 MD5 生成哈希值
            MessageDigest digest = MessageDigest.getInstance("MD5");
            byte[] hash = digest.digest(source.getBytes());
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Error generating document ID", e);
        }
    }



    /**
     * 获取文件名称的方法(包含文件名)
     * @param filePath
     * @return
     */
    public static String getFileName(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return null;
        }
        return filePath.substring(filePath.lastIndexOf("/") + 1);
    }



    /**
     * 获取文件类型的方法
     * @param filePath
     * @return
     */
    public static String getFileType(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return null;
        }
        String fileName = getFileName(filePath);
        if (fileName != null && fileName.contains(".")) {
            return fileName.substring(fileName.lastIndexOf(".") + 1);
        }
        return null;
    }


}
