package com.crunii.micro.service.sysmgr.service.impl;


import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.io.resource.InputStreamResource;
import cn.hutool.core.io.resource.MultiResource;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.crunii.micro.common.dto.Result;
import com.crunii.micro.common.utils.UUIDUtil;
import com.crunii.micro.service.sysmgr.dto.sysmgr.PdfDto;
import com.crunii.micro.service.sysmgr.service.IRSSignaturesService;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Arrays;
import java.util.Base64;
import java.util.stream.Collectors;

/**
 * @author lmlkyc
 * @date 2023-10-06 17:37
 */
@Service
@Slf4j
public class IRSSignaturesServiceImpl implements IRSSignaturesService {
    private final static String url = "ping /data_api/dcqc-openapi/v1/openapi/apply/keyToken/dd9d0052d8bce9f672ca95b0bba99fd19bc06305a784dc774b60d7d53aa25adbdffde2c4877ac9121446357129ffce7c757a0074d071e946fffe67f8376d8adf";
    private final static String getDzqzTokenUrl = "https://digitalcq.isigning.cn:30003//paas-api/gateway/paas-auth/oauth/token";
    private final static String UploadDzqzPicture = "https://digitalcq.isigning.cn:30003/paas-api/gateway/paas-standard-sdk/file/upload";
    private final static String clientId = "95ZJ6No1697006505883";
    private final static String clientSecret = "Oe3kndz1697006505883";


    @Override
    public Result getIRSToken(String loginId) {
        JSONObject param = new JSONObject();
        //入参
        param.put("grant_type", "aos_exchange_token");
        param.put("clientToken", loginId);
        param.put("userInfoUrl", "http://test.cert.youth.cq.cqyl.org.cn/api/service-sysmgr/LoginController/getUserInfoIRS");
        String body = HttpRequest.post(getDzqzTokenUrl)
                .header("Content-Type", "application/x-www-form-urlencoded")
                .form(param)
                .basicAuth(clientId, clientSecret)
                .execute().body();
        JSONObject entries = JSONUtil.parseObj(body);
        String data = entries.get("data").toString();
        String token = JSONUtil.parseObj(data).get("access_token").toString();
        return new Result(token);
    }

    @Override
    public Result<String> uploadPicture(MultipartFile file, String token) {
        try {
            MultipartFile[] multipartFiles = {file};
            MultiResource multiResource = new MultiResource(
                    Arrays.stream(multipartFiles)
                            .map(multipartFile -> {
                                try {
                                    return new InputStreamResource(multipartFile.getInputStream(), multipartFile.getOriginalFilename());
                                } catch (IOException e) {
                                    String message = "输入流打开失败";
                                    log.error(message, e);
                                    throw new RuntimeException(message);
                                }
                            }).collect(Collectors.toList())
            );
            HttpResponse execute = HttpRequest.post(UploadDzqzPicture)
                    .header("Content-Type", "multipart/form-data")
                    .header("authorization", "bearer " + token)
                    .form("file", multiResource)
                    .execute();
            JSONObject object = JSONUtil.parseObj(execute.body(), false);
            String data = object.get("data").toString();
            String fileId = JSONUtil.parseObj(data, false).get("fileId").toString();
            return Result.ofSuccess(fileId);
        } catch (HttpException e) {
            return Result.ofFail("上传失败" + e);
        }
    }


    @Override
    public Result<String> pdfToPng(PdfDto dto) {
        String uuid = UUIDUtil.getUUID();
        // 将文件地址和文件名拼接成路径 注意：线上环境不能使用\\拼接
        File file = convertBase64StrToImage(dto.getBase64Str(), uuid + ".pdf");
        try {
            // 写入文件
            PDDocument doc = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            for (int i = 0; i < pageCount; i++) {
                // dpi为144，越高越清晰，转换越慢
                BufferedImage image = renderer.renderImageWithDPI(i, 144); // Windows native DPI
                File png = new File(uuid + ".png");
                // 将图片写出到该路径下
                ImageIO.write(image, "png", png);
                FileInputStream inputFile = new FileInputStream(png);
                byte[] buffer = new byte[(int) png.length()];
                inputFile.read(buffer);
                inputFile.close();
                doc.close();
                file.delete();
                png.delete();
                return Result.ofSuccess(Base64Encoder.encode(buffer));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Base64字符串转图片
     *
     * @param base64String
     * @param imageFileName
     */
    public static File convertBase64StrToImage(String base64String, String imageFileName) {
        ByteArrayInputStream bais = null;
        try {
            //获取JDK8里的解码器Base64.Decoder,将base64字符串转为字节数组
            byte[] bytes = Base64.getDecoder().decode(base64String);
            InputStream ins = new ByteArrayInputStream(bytes);
            File file = new File(imageFileName);
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bais != null) {
                    bais.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}