package cn.com.poc.thirdparty.resource.text_in.api;

/**
 * @author alex.yao
 * @date 2025/5/7
 */

import cn.com.poc.common.utils.DocumentLoad;
import cn.com.poc.common.utils.JsonUtils;
import cn.com.poc.common.utils.StringUtils;
import cn.com.poc.common.utils.http.LocalHttpClient;
import cn.com.poc.thirdparty.resource.text_in.entity.doc_flow.FileFetchRequest;
import cn.com.poc.thirdparty.resource.text_in.entity.doc_flow.FileUploadRequest;
import cn.com.poc.thirdparty.resource.text_in.entity.doc_flow.FileUploadResponse;
import cn.com.poc.thirdparty.resource.text_in.entity.doc_flow.fileFetchResponse.FileFetchResponse;
import cn.com.poc.thirdparty.resource.text_in.entity.extraction.entity.*;
import cn.com.poc.thirdparty.resource.text_in.entity.imageEdgeTriming.ImageEdgeTrimingResult;
import cn.com.yict.framemax.core.exception.BusinessException;
import cn.hutool.core.net.url.UrlBuilder;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.StringEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class TextInClient {

    private Logger logger = LoggerFactory.getLogger(TextInClient.class);
    private final String appId = "145b4303badd1da2f1628cf28534967a";
    private final String secretCode = "5fe7d03b56714ec708f4ec6149d3a20c";
    private final String appId_for_docFlow = "dafd04a574230c00ccba61132160de0c";
    private final String secretCode_for_docFlow = "3bc03c7e6f9402963e6e71d16d786a9c";

    public TextInClient() {
    }

    /**
     * ocr
     *
     * @param fileContent
     * @param options
     * @return
     * @throws IOException
     */
    public String OCR(byte[] fileContent, HashMap<String, Object> options) throws IOException {
        StringBuilder queryParams = new StringBuilder();
        for (Map.Entry<String, Object> entry : options.entrySet()) {
            if (queryParams.length() > 0) {
                queryParams.append("&");
            }
            queryParams.append(URLEncoder.encode(entry.getKey(), "UTF-8"))
                    .append("=")
                    .append(URLEncoder.encode(entry.getValue().toString(), "UTF-8"));
        }
        HttpURLConnection connection = getOCRHttpURLConnection(queryParams);
        try (OutputStream os = connection.getOutputStream()) {
            os.write(fileContent);
            os.flush();
        }

        int responseCode = connection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            try (BufferedReader in = new BufferedReader(
                    new InputStreamReader(connection.getInputStream()))) {
                StringBuilder response = new StringBuilder();
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                return response.toString();
            }
        } else {
            logger.error("HTTP request failed with code: {}, Error message view :{}", responseCode, "https://www.textin.com/document/pdf_to_markdown");
            throw new IOException("HTTP request failed with code: " + responseCode);
        }
    }

    private HttpURLConnection getOCRHttpURLConnection(StringBuilder queryParams) throws IOException {
        String baseUrl = "https://api.textin.com/ai/service/v1/pdf_to_markdown";
        String fullUrl = baseUrl + (queryParams.length() > 0 ? "?" + queryParams : "");
        URL url = new URL(fullUrl);

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("x-ti-app-id", appId);
        connection.setRequestProperty("x-ti-secret-code", secretCode);
        connection.setRequestProperty("Content-Type", "text/plain;charset=utf-8");
        connection.setDoOutput(true);
        return connection;
    }

    /**
     * OCR
     *
     * @param fileContent
     * @param options
     * @return
     * @throws IOException
     */
    public String recognize(byte[] fileContent, HashMap<String, Object> options) throws IOException {
        StringBuilder queryParams = new StringBuilder();
        for (Map.Entry<String, Object> entry : options.entrySet()) {
            if (queryParams.length() > 0) {
                queryParams.append("&");
            }
            queryParams.append(URLEncoder.encode(entry.getKey(), "UTF-8"))
                    .append("=")
                    .append(URLEncoder.encode(entry.getValue().toString(), "UTF-8"));
        }
        String baseUrl = "https://api.textin.com/ai/service/v1/pdf_to_markdown";
        String fullUrl = baseUrl + (queryParams.length() > 0 ? "?" + queryParams : "");
        URL url = new URL(fullUrl);

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("x-ti-app-id", appId);
        connection.setRequestProperty("x-ti-secret-code", secretCode);
        connection.setRequestProperty("Content-Type", "text/plain;charset=utf-8");
        connection.setDoOutput(true);
        try (OutputStream os = connection.getOutputStream()) {
            os.write(fileContent);
            os.flush();
        }

        int responseCode = connection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            try (BufferedReader in = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
                StringBuilder response = new StringBuilder();
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                return response.toString();
            }
        } else {
            logger.error("HTTP request failed with code: {}, Error message view :{}", responseCode, "https://www.textin.com/document/pdf_to_markdown");
            throw new IOException("HTTP request failed with code: " + responseCode);
        }
    }

    /**
     * 文档图像切边增强矫正<br>
     * 文档图像切边矫正与图片切边增强合并产品；边缘背景去除，文档图像形变矫正，增强显示效果。<br>
     * https://www.textin.com/document/crop_enhance_image
     *
     * @param input 文件路径或URL，取决于 isUrl 参数的值。如果为 true，则视为 URL；否则视为本地文件路径。
     * @param isUrl 指示输入是 URL 还是本地文件路径。如果为 true，则视为 URL；否则视为本地文件路径。
     * @return 处理后的图像数据或错误信息。如果请求成功，返回处理后的图像数据；否则返回错误信息。
     */
    public ImageEdgeTrimingResult imageEdgeTrimming(String input, boolean isUrl) {
        // 文档图像切边增强矫正
        String url = "https://api.textin.com/ai/service/v1/crop_enhance_image";
        BufferedReader in = null;
        DataOutputStream out = null;
        try {
            byte[] requestData;
            if (isUrl) {
                requestData = input.getBytes(StandardCharsets.UTF_8); // 将 URL 转为字节数组
            } else {
                requestData = readFile(input); // 读取文件内容
            }

            URL realUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Content-Type", isUrl ? "text/plain" : "application/octet-stream");
            conn.setRequestProperty("x-ti-app-id", appId);
            conn.setRequestProperty("x-ti-secret-code", secretCode);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");

            // 发送请求体
            out = new DataOutputStream(conn.getOutputStream());
            out.write(requestData);
            out.flush();

            // 读取响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            StringBuilder result = new StringBuilder();
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            ImageEdgeTrimingResult imageEdgeTrimingResult = JsonUtils.deSerialize(result.toString(), ImageEdgeTrimingResult.class);
            return imageEdgeTrimingResult;
        } catch (Exception e) {
            logger.error("图像增强失败", e);
            throw new BusinessException("图像增强失败");
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                logger.error("关闭流出现异常！", ex);
            }
        }
    }

    /**
     * 读取文件内容为字节数组
     *
     * @param path 文件路径
     * @return 文件的字节数组
     */
    public byte[] readFile(String path) {
        InputStream in = null;
        byte[] data = null;
        try {
            in = Files.newInputStream(Paths.get(path));
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            logger.error("读取文件出错！", e);
        }
        return data;
    }


    /**
     * 【合同抽取】- 创建抽取<br>
     * 接口文档：<br>
     * https://www.textin.com/document/doc_extraction_create
     *
     * @param fileUrl     PDF文件URL
     * @param keyInfoList 抽取字段列表
     * @return 任务ID
     */

    public String extraction(String fileUrl, List<KeyInfo> keyInfoList) {
        try {
            // 读取文件并将其转换为Base64编码
            File file = DocumentLoad.downloadURLDocument(fileUrl);
            byte[] fileData = Files.readAllBytes(file.toPath());
            String base64FileData = Base64.getEncoder().encodeToString(fileData);

            // 获取文件名
            String fileName = file.getName();

            Config config = new Config();
            config.setEngine("table");
            config.setRemove_watermark("false");
            config.setUse_pdf_parser("true");
            config.setUse_semantic_match("true");

            CreateExtractionResponse response = new CreateExtractionResponse();
            response.setConfig(config);
            response.setCreator("");
            response.setFiledata(base64FileData);
            response.setFilename(fileName);
            response.setKey_info_list(keyInfoList);
            response.setToken_mode(1L);

            // 构建请求数据
            String json = JSONObject.toJSONString(response);

            HttpUriRequest httpUriRequest = RequestBuilder.post()
                    .setUri("https://doc-compare.intsig.com/api/contracts/v3/extraction/external/create")
                    .addHeader("x-ti-app-id", appId)
                    .addHeader("x-ti-secret-code", secretCode)
                    .addHeader("Content-Type", "application/json;charset=utf-8")
                    .setEntity(new StringEntity(json, StandardCharsets.UTF_8))
                    .build();

            CreateResult createResult = LocalHttpClient.executeJsonResult(httpUriRequest, CreateResult.class);
            if (createResult == null) {
                throw new BusinessException("创建抽取任务失败");
            }
            if (createResult.getCode().equals(200)) {
                return createResult.getData().getTask_id();
            } else {
                logger.error("创建抽取任务失败，错误码：{},msg:{}", createResult.getCode(), createResult.getMsg());
                throw new BusinessException("创建抽取任务失败");
            }
        } catch (IOException e) {
            throw new BusinessException("创建抽取任务失败");
        }
    }

    /**
     * 【合同抽取】 - 获取抽取结果 <br>
     * 接口文档： <br>
     * https://www.textin.com/document/doc_extraction_result
     *
     * @param taskId
     * @return
     */
    public ExtractionResult extractedResults(String taskId) {
        String baseUrl = "https://doc-compare.intsig.com/doc_extraction/keyinfo/extracted_results?format=json&task_id=" + taskId;
        HttpUriRequest httpUriRequest = RequestBuilder.get()
                .setUri(baseUrl)
                .addHeader("x-ti-app-id", appId)
                .addHeader("x-ti-secret-code", secretCode)
                .addHeader("Content-Type", "application/json;charset=utf-8")
                .build();
        ExtractionResult result = LocalHttpClient.executeJsonResult(httpUriRequest, ExtractionResult.class);
        if (result == null) {
            logger.error("获取抽取结果失败");
            return null;
        }
        if (result.getCode().equals(209L)) {
            logger.info("任务未完成，继续等待");
            return result;
        } else if (result.getCode().equals(200L)) {
            return result;
        } else {
            logger.error("获取token失败，错误码：{},msg:{}", result.getCode(), result.getMsg());
            return result;
        }
    }

    // https://docflow.apifox.cn/fetch
    public static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().readTimeout(300, TimeUnit.SECONDS).build();

    public FileUploadResponse fileUpload(FileUploadRequest fileUploadRequest) throws IOException {

        MultipartFile multipartFile = fileUploadRequest.getFile();

        File file = File.createTempFile("temp", "." + getFileExtension(multipartFile.getOriginalFilename()));

        // 将MultipartFile内容传输到临时文件
        multipartFile.transferTo(file);

        RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                .addFormDataPart("file", file.getName(), RequestBody.create(null, file))
                .build();

        StringBuilder stringBuilder = new StringBuilder("https://docflow.textin.com/api/app-api/sip/platform/v2/file/upload");
        if (StringUtils.isNotBlank(fileUploadRequest.getWorkspaceid())) {
            logger.info("------workspace_id-----:", fileUploadRequest.getWorkspaceid());
//            urlBuilder.addQuery("workspace_id", fileUploadRequest.getWorkspaceid());
//            urlBuilder.
            stringBuilder.append("?workspace_id=" + fileUploadRequest.getWorkspaceid());
        }
        if (StringUtils.isNotBlank(fileUploadRequest.getCategory())) {
            stringBuilder.append("&category=" + fileUploadRequest.getCategory());
        }

        Request request = new Request.Builder()
                .url(stringBuilder.toString())
                .method("POST", body)
                .addHeader("Content-Type", "multipart/form-data")
                .addHeader("x-ti-app-id", appId_for_docFlow)
                .addHeader("x-ti-secret-code", secretCode_for_docFlow)
                .addHeader("Content-Type", "application/json;charset=utf-8")
                .build();
        String response = HTTP_CLIENT.newCall(request).execute().body().string();
        Gson gson = new Gson();
        return gson.fromJson(response, FileUploadResponse.class);
    }

//    public static void main(String[] args) throws IOException {
//        FileFetchRequest fileFetchRequest =  new FileFetchRequest();
//        fileFetchRequest.setWorkspaceid("1960977364788809728");
//        fileFetchRequest.setFileid("1961336933658497024");
//        FileFetchResponse fileFetchResponse = fileFetch(fileFetchRequest);
//        System.out.println(JsonUtils.serialize(fileFetchResponse));
//    }


    public FileFetchResponse fileFetch(FileFetchRequest fileFetchRequest) throws IOException {
        StringBuilder urlBuilder = new StringBuilder("https://docflow.textin.com/api/app-api/sip/platform/v2/file/fetch");

        if (StringUtils.isNotBlank(fileFetchRequest.getWorkspaceid())) {
            urlBuilder.append("?workspace_id=" + fileFetchRequest.getWorkspaceid());
        }

        if (StringUtils.isNotBlank(fileFetchRequest.getFileid())) {
            urlBuilder.append("&file_id=" + fileFetchRequest.getFileid());
        }

        HttpUriRequest httpUriRequest = RequestBuilder.get()
                .setUri(urlBuilder.toString())
//                .addHeader("x-ti-app-id", appId_for_docFlow)
//                .addHeader("x-ti-secret-code", secretCode_for_docFlow)
                .addHeader("x-ti-app-id", "dafd04a574230c00ccba61132160de0c")
                .addHeader("x-ti-secret-code", "3bc03c7e6f9402963e6e71d16d786a9c")
                .addHeader("Content-Type", "application/json;charset=utf-8")
                .build();
        FileFetchResponse result = LocalHttpClient.executeJsonResult(httpUriRequest, FileFetchResponse.class);
        return result;
    }

    private String getFileExtension(String fileName) {
        if (fileName == null || fileName.lastIndexOf(".") == -1) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

}