package com.ruoyi.hywz.service.impl;

import cn.com.esgcc.ai.matrix.sdk.constant.OcrMethod;
import cn.com.esgcc.ai.matrix.sdk.esgccenum.ExceptionEnum;
import cn.com.esgcc.ai.matrix.sdk.request.QueryData;
import cn.com.esgcc.ai.matrix.sdk.request.RequestClient;
import cn.com.esgcc.ai.matrix.sdk.response.SdkResponse;
import cn.com.esgcc.ai.matrix.sdk.response.SdkTokenResponse;
import cn.com.esgcc.ai.matrix.sdk.util.encrypt.base64.Base64Util;
import cn.com.esgcc.ai.matrix.sdk.util.encrypt.sm2.Sm2KeyVO;
import cn.hutool.json.JSONObject;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.hywz.entity.vo.InvoiceOcrFileVo;
import com.ruoyi.hywz.service.IAdsMatHyxtOcrService;
import com.ruoyi.hywz.utils.BaseFile;
import com.ruoyi.hywz.utils.IdGen;
import com.ruoyi.hywz.utils.OssUploadService;
import com.ruoyi.hywz.utils.PDFUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author: jxh
 * @description:
 * @create: 2024/4/17
 */
@Slf4j
@Service
public class AdsMatHyxtOcrServiceImpl implements IAdsMatHyxtOcrService {

    @Value("${ai.ocr.clientId}")
    private String clientId;
    @Value("${ai.ocr.clientSecret}")
    private String clientSecret;
    @Value("${ai.ocr.username}")
    private String username;
    @Value("${ai.ocr.password}")
    private String password;
    @Value("${ai.ocr.ocrServer}")
    private String ocrServer;
    @Value("${ai.ocr.deviceId}")
    private String deviceId;
    @Value("${ai.ocr.sm2PublicKey}")
    private String sm2PublicKey;
    @Value("${ai.ocr.sm2PrivateKey}")
    private String sm2PrivateKey;
    @Value("${ai.ocr.tempPath}")
    private String tempPath;

    private static final DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyyMMdd");
    private static final DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private final static Logger logger = LoggerFactory.getLogger(AdsMatHyxtOcrServiceImpl.class);

    @Override
    public R invoiceOcrScan(MultipartFile file) {
        List<InvoiceOcrFileVo> result = null;
        try {
            result = this.ossUpload(file);
        } catch (Exception e) {
            e.printStackTrace();
//            return R.fail(e.getMessage());
        }
        try {
            QueryData queryData = new QueryData();
            File tempFolder = new File(tempPath);
            if (!tempFolder.exists()) {
                tempFolder.mkdirs();
            }
            String localFilePath = tempPath + "\\" + this.getFileName(file);
            log.info("[本地上传文件路径][{}]", localFilePath);
            File tempFile = new File(localFilePath);
            FileUtils.copyInputStreamToFile(file.getInputStream(), tempFile);
            File pngFile = null;
            if (PDFUtil.isPdfFile(file)) {
                log.info("上传的文件为pdf格式");
                pngFile = this.pdfToPng(tempFile);
            } else {
                log.info("上传的文件为图片格式");
                pngFile = tempFile;
            }
            String base64String = Base64Util.file2Base64(pngFile);
            queryData.setImg(base64String);
            SdkResponse sdkResponse = getClient().esgccOcr(OcrMethod.BIZ_ZP, queryData);
            if (ExceptionEnum.COMMON_SUCCESS_1B.getResultCode().equals(sdkResponse.getCode())) {
                JSONObject jsonObject1 = (JSONObject) sdkResponse.getData();
                if (jsonObject1 != null) {
                    JSONObject resultStr = jsonObject1.getJSONObject("result");
                    String kprq = resultStr.getStr("发票号码");
                    if (StringUtils.isNotEmpty(kprq)) {
                        kprq = this.formatDate(kprq);
                    }
                    for (InvoiceOcrFileVo vo : result) {
                        vo.setMakeInvoiceDate(kprq);
                        vo.setInvoiceCode(resultStr.getStr("发票代码"));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
//            return R.fail(e.getMessage());
        }
        return R.ok(result);
    }

    private String formatDate(String date) {
        if (StringUtils.isEmpty(date)) {
            return null;
        }
        try {
            LocalDate parse = LocalDate.parse(date, formatter1);
            return parse.format(formatter2);
        } catch (Exception e) {
            return null;
        }
    }

    private List<InvoiceOcrFileVo> ossUpload(MultipartFile file) throws Exception {
        List<InvoiceOcrFileVo> result = new ArrayList<>();
        InvoiceOcrFileVo vo = new InvoiceOcrFileVo();

        String originalFilename = file.getOriginalFilename();
        String suffer = null;
        if (originalFilename != null) {
            suffer = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        Random random = new Random();
        int randomNumber = random.nextInt(89999) + 10000;
        String fileName = "cwzjgk"+ System.currentTimeMillis() + randomNumber + suffer;
        BaseFile baseFile = OssUploadService.ossUpload(file, fileName);

        vo.setFilePath(baseFile.getFilePath());
        vo.setFileName(baseFile.getFileName());
        result.add(vo);

        return result;
    }

    private RequestClient getClient() {
        Sm2KeyVO sm2KeyVO = new Sm2KeyVO();
        sm2KeyVO.setPrivateKey(sm2PrivateKey);
        sm2KeyVO.setPublicKey(sm2PublicKey);
        RequestClient client = new RequestClient(ocrServer, deviceId, clientId, clientSecret, username, password, sm2KeyVO);
        SdkTokenResponse sdkResponse = client.oauthUserToken();
        if (ExceptionEnum.COMMON_SUCCESS_1B.getResultCode().equals(sdkResponse.getCode())) {
            logger.debug(sdkResponse.getAccessToken());
        }
        return client;
    }

    private String getFileName(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        String suffer = fileName.substring(fileName.lastIndexOf("."));
        fileName = IdGen.get32UUID() +suffer;
        return fileName;
    }

    /**
     * pdf转png
     */
    public File pdfToPng(File pdfFile) {
        try {
            // 加载PDF文档
            PDDocument document = PDDocument.load(pdfFile);

            // 创建PDF渲染器
            PDFRenderer pdfRenderer = new PDFRenderer(document);

            // 渲染第一页为图片
            BufferedImage image = pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);

            // 保存图片到文件
            String localPngPath = tempPath + "\\" + IdGen.get32UUID() + ".png";
            log.info("[pdf转png，本地路径为][{}]", localPngPath);
            File outputFile = new File(localPngPath);
            ImageIO.write(image, "PNG", outputFile);

            // 关闭文档
            document.close();

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