package com.ningdatech.pmapi.todocenter.utils;


import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.UUID;

import org.springframework.stereotype.Component;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.BaseFont;
import com.ningdatech.basic.exception.BizException;

import lombok.extern.slf4j.Slf4j;

/**
 * pdf生成工具类
 *
 * @author CMM
 * @since 2023/03/13 17:01
 */
@Slf4j
@Component
public class PdfUtils {
    /**
     * 生成PDF文件
     *
     * @return int
     * @author CMM
     * @since 2023/03/13 17:07
     */
    public byte[] generatePdf(InputStream templateHtmlInputStream, Map<String, Object> paramsMap){
        FileInputStream inputStream = null;

        try {
            File directory = new File("");
            //临时文件输出路径
            String filePath = directory.getAbsolutePath() + File.separator + "fileout";
            //字体格式
            String fontPath = directory.getAbsolutePath() + File.separator + "font" +  File.separator + "simsun.ttc";
            if(!new File(filePath).exists()){
                new File(filePath).mkdir();
            }
            StringBuilder stringBuilder = new StringBuilder();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(templateHtmlInputStream, StandardCharsets.UTF_8));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line);
            }
            String htmlInfo = stringBuilder.toString();

            //替换参数、多个参数多次替换
            for (String fieldName : paramsMap.keySet()) {
                if (paramsMap.get(fieldName) == null) {
                    // 没有值的字段使用-覆盖
                    htmlInfo = htmlInfo.replace("#" + fieldName + "#", "");
                }else {
                    // 设置占位字段
                    htmlInfo = htmlInfo.replace("#" + fieldName + "#", paramsMap.get(fieldName).toString());
                }
            }

            //生成临时文件
            String htmlFileName =  UUID.randomUUID().toString().replace("-","") + ".html";
            String htmlFilePath = filePath + File.separator + htmlFileName;
            File file = new File(htmlFilePath);
            FileOutputStream fop = new FileOutputStream(file);
            if (!file.exists()) {
                file.createNewFile();
            }
            byte[] contentInBytes = htmlInfo.getBytes();
            fop.write(contentInBytes);
            fop.flush();
            fop.close();

            //生成pdf
            String fileName =  UUID.randomUUID().toString().replace("-","") + ".pdf";
            String pdfFilePath = filePath + File.separator + fileName;
            String url = new File(htmlFilePath).toURI().toURL().toString();
            OutputStream os = Files.newOutputStream(Paths.get(pdfFilePath));

            ITextRenderer renderer = new ITextRenderer();
            renderer.setDocument(url);
            ITextFontResolver fontResolver = renderer.getFontResolver();
            fontResolver.addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            renderer.layout();
            renderer.createPDF(os);
            os.flush();
            os.close();

            inputStream = new FileInputStream(pdfFilePath);

            // 返回生成的pdf文件字节数组
            return readBytes(inputStream);
        } catch (IOException e) {
            throw new BizException("生成pdf文件失败!" + e.getMessage());
        } catch (DocumentException e) {
            throw new BizException("生成pdf文件失败!" +e.getMessage());
        } finally {
            try {
                if (null != inputStream) {

                    inputStream.close();
                }
            } catch (IOException e) {
                    log.error("close resource error", e.getMessage());
                }
            }
        }


    /**
     * 读取输入流到字节数组
     *
     * @param in
     * @return
     * @throws IOException
     */
    private byte[] readBytes(InputStream in) throws IOException {
        //读取字节的缓冲
        byte[] buffer = new byte[1024];
        //最终的数据
        byte[] result = new byte[0];
        int size = 0;
        while ((size = in.read(buffer)) != -1) {
            int oldLen = result.length;
            byte[] tmp = new byte[oldLen + size];
            if (oldLen > 0) {//copy 旧字节
                System.arraycopy(result, 0, tmp, 0, oldLen);
            }
            //copy 新字节
            System.arraycopy(buffer, 0, tmp, oldLen, size);

            result = tmp;
        }
        return result;
    }

}
