package com.yem.wm.utils;

import com.yem.wm.es.encasement.util.FileUtil;
import kd.bos.context.RequestContext;
import kd.bos.exception.KDBizException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

/**
 * @Description: 合同盖章
 * @Date: 2024/8/8 17:59
 * @Created: by ZZSLL
 */

public class ContactSignUtils {

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

    public static List<CTBookmark> getFileBookMarks(InputStream in) {
        List<CTBookmark> list = new ArrayList<>();
        try {
            try (XWPFDocument doc = new XWPFDocument(in)) {
                for (XWPFParagraph paragraph : doc.getParagraphs()) {
                    list.addAll(paragraph.getCTP().getBookmarkStartList());
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }catch (Exception e ){
            throw new KDBizException("不支持doc格式的word文档，请上传docx格式的word文档!!!");
        }
        return list;
    }

    /**
     * 在 Word 文档中的书签位置插入图片，并保存修改后的文档。
     *
     * @param wordFile     原始 Word 文档
     * @param imageFile    图片文件
     * @param outfileName  修改后的 Word 文档保存路径
     * @param bookmarkName 书签名称
     * @return 修改后的 Word 文件
     * @throws IOException            IO 异常
     * @throws InvalidFormatException 格式异常
     */
    public static File replaceBookmarkWithImage(InputStream wordFile, InputStream imageFile, String outfileName, String bookmarkName) throws IOException {
        byte[] imageBytes = readImageFile(imageFile);

        try (XWPFDocument doc = new XWPFDocument(wordFile)) {
            for (XWPFParagraph paragraph : doc.getParagraphs()) {
                List<CTBookmark> bookmarkStartList = paragraph.getCTP().getBookmarkStartList();
                for (CTBookmark bookmark : bookmarkStartList) {
                    String name = bookmark.getName();
                    if (name.contains(bookmarkName)) {
                        List<XWPFRun> runs = paragraph.getRuns();
                        XWPFRun run;
                        if (!runs.isEmpty()) {
                            run = runs.get(0);
                        } else {
                            run = paragraph.createRun();
                        }
                        //                                                                                                           设置图片大小 长宽比： 1.8586387435
                        run.addPicture(new ByteArrayInputStream(imageBytes), XWPFDocument.PICTURE_TYPE_PNG, "imageName.png", Units.toEMU(74), Units.toEMU(40));
                    }
                }
            }
            FileUtil fileUtil = new FileUtil("sales-order-sign-file");
            File outFile = fileUtil.createNewFile(outfileName);
            try (FileOutputStream out = new FileOutputStream(outFile)) {
                doc.write(out);
            }

            return outFile;
        } catch (InvalidFormatException e) {
            throw new KDBizException("无法解析文件 " + outfileName + " 格式：" + e.getMessage());
        }
    }

    private static byte[] readImageFile(InputStream file) throws IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = file.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            return outputStream.toByteArray();
        }
    }

    public static File convertToPDF(List<Map<String, Object>> files) {
        for (Map<String, Object> file : files) {
            InputStream in = word2PdfByYunpan(file);
            if (in == null) {
                logger.error("word2PdfByYunpan response null");
                return null;
            }
            FileUtil fileUtil = new FileUtil("sales-order-sign-file-pdf");
            try {
                File outFile = fileUtil.createNewFile(changeFileExtension((String) file.get("name"), "pdf"));
                writeToFile(in, outFile);
                return outFile;
            } catch (IOException e) {
                logger.error(e.getMessage());
            }
        }
        return null;
    }

    public static void writeToFile(InputStream in, File file) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
            logger.info("PDF文件写入成功");
        } catch (IOException e) {
            logger.error("PDF文件写入本地失败");
            logger.error(e.getMessage());
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                logger.error(e.getMessage());
            }
        }
    }

    /**
     * 通过预览服务器生成pdf文件
     *
     * @param urlWord 附件面板数据
     * @return 文件流
     */
    public static InputStream word2PdfByYunpan(Map<String, Object> urlWord) {
        //需要添加到附件的文件
        String yunPanUrl = System.getProperty("yunpan.previewUrl");
        String getPdfUrl = yunPanUrl + "/api/officeToPdf";
        // 请求参数
        Map<String, Object> param = new HashMap<>(8);
        //文件id
        param.put("id", urlWord.get("uid"));
        //文件名
        String wordName = urlWord.get("name").toString();
        String[] wordNameStr = wordName.split("\\.");
        //获取文件类型  doc/docx
        param.put("ext", wordNameStr[wordNameStr.length - 1]);
        //构造原始word文件获取的url，需要携带token
        String url = urlWord.get("url").toString();
        logger.info("download_url {}", url);
        param.put("download_url", url
                + "&access_token=" + RequestContext.get().getGlobalSessionId());
        String paramUrl = getGetParamUrl(param);
        String officeToPdfUrl = getPdfUrl + "?" + paramUrl;
        logger.info("officeToPdfUrl {}", officeToPdfUrl);
        //word 转pdf之后的文件流
        return getInputStreamByUrl(officeToPdfUrl);
    }

    /**
     * 通过浏览器下载获取文件流
     * 传入一个url 地址,获取文件二进制流
     *
     * @param pdfUrl 地址
     */
    public static InputStream getInputStreamByUrl(String pdfUrl) {
        //输入流
        try {
            // 当作一个URL来装载文件
            URL url = new URL(pdfUrl);
            URLConnection con = url.openConnection();
            con.setConnectTimeout(3 * 1000);
            return con.getInputStream();
        } catch (Exception e) {
            logger.error("word转pdf失败", e);
        }
        return null;
    }

    /**
     * 把key-value参数序列化成 url get参数
     *
     * @param body key-value
     * @return a=1&b=2
     */
    public static String getGetParamUrl(Map<String, Object> body) {
        String client;
        String strBody = "";
        if (body != null && !body.isEmpty()) {
            Iterator<String> iterator = body.keySet().iterator();
            List<BasicNameValuePair> params = new ArrayList<>();
            while (iterator.hasNext()) {
                client = iterator.next();
                String value = body.get(client).toString();
                params.add(new BasicNameValuePair(client, value));
            }
            try {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
                strBody = EntityUtils.toString(entity);
            } catch (IOException var28) {
                logger.error("Http get error", var28);
            }
        }
        return strBody;
    }

    public static String changeFileExtension(String fileName, String newExtension) {
        String fileNameWithoutExtension = removeFileExtension(fileName);
        return fileNameWithoutExtension + "." + newExtension;
    }

    private static String removeFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf(".");
        if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
            return fileName.substring(0, dotIndex);
        }
        return fileName;
    }
}
