package com.czg.utils;

import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.dashscope.app.Application;
import com.alibaba.dashscope.app.ApplicationParam;
import com.alibaba.dashscope.app.ApplicationResult;
import com.alibaba.dashscope.app.RagOptions;
import com.aliyun.bailian20231229.Client;
import com.aliyun.bailian20231229.models.AddFileResponse;
import com.aliyun.bailian20231229.models.ApplyFileUploadLeaseResponse;
import com.aliyun.bailian20231229.models.ApplyFileUploadLeaseResponseBody;
import com.aliyun.bailian20231229.models.DescribeFileResponse;
import com.czg.exception.CzgException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
 * 支付宝通用SDK工具类
 *
 * @author tankaikai
 * @since 2024-09-23 16:15
 */

@Slf4j
@Component
public class AliOcrUtil {
    /**
     * <b>description</b> :
     * <p>使用凭据初始化账号Client</p>
     *
     * @return Client
     */
    public static com.aliyun.bailian20231229.Client createClient() {

        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 配置 AccessKey ID，请确保代码运行环境设置了环境变量。
                .setAccessKeyId("LTAI5t8dEAHVd3HqaaS48fK9")
                // 配置 AccessKey Secret，请确保代码运行环境设置了环境变量。
                .setAccessKeySecret("fzfNGiuvpC21yuT3OgbJ7MJJT0dPX0")
                .setEndpoint("bailian.cn-beijing.aliyuncs.com");

        try {
            return new Client(config);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(byte[] bytes, String fileName) {

        String md5 = DigestUtil.md5Hex(bytes);
        com.aliyun.bailian20231229.Client client = createClient();
        com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest applyFileUploadLeaseRequest = new com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest()
                .setFileName(fileName)
                .setMd5(md5)
                .setSizeInBytes(String.valueOf(bytes.length))
                .setCategoryType("SESSION_FILE")
                .setUseInternalEndpoint(false);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        java.util.Map<String, String> headers = new java.util.HashMap<>();
        try {
            // 复制代码运行请自行打印 API 的返回值
            ApplyFileUploadLeaseResponse aDefault = client.applyFileUploadLeaseWithOptions("default", "llm-9zg04s7wlbvi32tq", applyFileUploadLeaseRequest, headers, runtime);
            if (!"Success".equals(aDefault.getBody().getCode())) {
                throw new CzgException(aDefault.getBody().getMessage());
            }
            return aDefault.getBody().getData();
        } catch (Exception error) {
            throw new RuntimeException(error);
        }
    }

    public static String getSessionId(byte[] bytes, String fileName) {
        String leaseId = null;
        try {
            leaseId = uploadFile(bytes, fileName);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        com.aliyun.bailian20231229.Client client = createClient();
        com.aliyun.bailian20231229.models.AddFileRequest addFileRequest = new com.aliyun.bailian20231229.models.AddFileRequest()
                .setLeaseId(leaseId)
                .setParser("DASHSCOPE_DOCMIND")
                .setCategoryId("default")
                .setCategoryType("SESSION_FILE");
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        java.util.Map<String, String> headers = new java.util.HashMap<>();
        try {
            // 复制代码运行请自行打印 API 的返回值
            AddFileResponse addFileResponse = client.addFileWithOptions("llm-9zg04s7wlbvi32tq", addFileRequest, headers, runtime);
            String fileId = addFileResponse.getBody().getData().getFileId();
            int count = 0;
            while (!getFileStatus(fileId) && count++ < 300) {
                Thread.sleep(100);
            }
            return fileId;
        } catch (Exception error) {
            throw new RuntimeException(error);
        }
    }

    public static boolean getFileStatus(String fileId) {
        com.aliyun.bailian20231229.Client client = createClient();
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        java.util.Map<String, String> headers = new java.util.HashMap<>();
        try {
            // 复制代码运行请自行打印 API 的返回值
            DescribeFileResponse describeFileResponse = client.describeFileWithOptions("llm-9zg04s7wlbvi32tq", fileId, headers, runtime);

            log.info("file status: {}", describeFileResponse.getStatusCode());
            return describeFileResponse.getBody().getData() != null && "FILE_IS_READY".equals(describeFileResponse.getBody().getData().getStatus());
        } catch (Exception error) {
            throw new RuntimeException(error);
        }
    }


    public static String uploadFile(byte[] bytes, String fileName) throws Exception {

        ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyInfo = applyFileUpload(bytes, fileName);

        Map<String, String> headers = (Map<String, String>) applyInfo.getParam().getHeaders();

        // 补充必须的 Content-Type
        if (!headers.containsKey("Content-Type")) {
            headers.put("Content-Type", "application/octet-stream");
        }

        HttpRequest request = HttpRequest.put(applyInfo.getParam().getUrl());

        // 设置所有 header
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            request.header(entry.getKey(), entry.getValue());
        }

        // 设置文件内容
        request.body(bytes);

        HttpResponse resp = request.execute();

        log.info("upload status: {}", resp.getStatus());
        if (resp.getStatus() != 200) {
            throw new CzgException("OSS 上传失败: " + resp.body());
        }

        return applyInfo.getFileUploadLeaseId();
    }


    //地址 https://bailian.console.aliyun.com
    public static String appCall(byte[] bytes, String fileName, String detail) {
        String id;
        try {
            id = getSessionId(bytes, fileName);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        ApplicationParam param = ApplicationParam.builder()
                .apiKey("sk-2343af4413834ad1ab43b036e3a903de")
                .appId("cd612ac509a4499f8ac68a656532d4ae")
                .prompt(detail)
                .ragOptions(RagOptions.builder()
                        .sessionFileIds(List.of(id))
                        .build())
                .build();

        Application application = new Application();
        ApplicationResult result = null;
        try {
            result = application.call(param);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        log.info("{}",
                result.getOutput().getText());
        return result.getOutput().getText();
    }

}
