package com.goafanti.common.utils.pdf;

import com.goafanti.RD.bo.OutWordRdDetails;
import com.goafanti.common.constant.AFTConstants;
import com.goafanti.common.utils.DateUtils;
import com.goafanti.common.utils.excel.FileUtils;
import com.goafanti.expenseAccount.bo.MainExpenseAccount;
import com.itextpdf.text.Document;
import com.itextpdf.text.Font;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.*;
import org.docx4j.Docx4J;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.springframework.http.MediaType;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Date;

public class PDFUtils {


    /**
     * 删除临时目录及其内容
     *
     * @param dir 临时目录
     */
    private static void deleteTempDirectory(File dir) {
        if (dir.exists() && dir.isDirectory()) {
            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteTempDirectory(file);
                    } else {
                        file.delete();
                    }
                }
            }
            dir.delete();
        }
    }





    /**
     * 将Word文档转换为PDF文件
     *
     * @param wordFilePath Word文件路径
     * @param pdfFilePath 生成的PDF文件路径
     * @throws IOException
     * @throws DocumentException
     */
    public static void convertWordToPDF(String wordFilePath, String pdfFilePath)
            throws IOException, DocumentException {

        Document document = new Document(PageSize.A4);

        try (InputStream in = new FileInputStream(wordFilePath)) {
            // 创建PDF写入器
            FileOutputStream outputStream = new FileOutputStream(pdfFilePath);
            PdfWriter.getInstance(document, outputStream);

            document.open();

            // 处理Word文档内容
            processWordDocument(wordFilePath, document);

            document.close();
            outputStream.close();
        }
    }

    /**
     * 将XLSX文件转换为PDF文件
     *
     * @param xlsxFilePath XLSX文件路径
     * @param pdfFilePath  生成的PDF文件路径
     * @throws IOException
     * @throws DocumentException
     */
    public static void convertXlsxToPDF(String xlsxFilePath, String pdfFilePath)
            throws IOException, DocumentException {

        Document document = new Document(PageSize.A4.rotate()); // 使用横向页面以适应更多列

        try (InputStream in = new FileInputStream(xlsxFilePath)) {
            Workbook workbook = new XSSFWorkbook(in);

            // 创建PDF写入器
            FileOutputStream outputStream = new FileOutputStream(pdfFilePath);
            PdfWriter.getInstance(document, outputStream);

            document.open();

            // 处理Excel工作簿内容
            processExcelWorkbook(workbook, document);

            document.close();
            outputStream.close();
            workbook.close();
        }
    }

    /**
     * 将Word文档转换为PDF并提供下载
     *
     * @param wordFilePath Word文件路径
     * @param response HttpServletResponse对象
     * @param pdfFileName 生成的PDF文件名
     * @param uploadPath 上传路径
     * @throws IOException
     * @throws DocumentException
     */
    public static void convertWordToPDFForDownload(String wordFilePath,
                                                   HttpServletResponse response,
                                                   String pdfFileName,
                                                   String uploadPath)
            throws IOException, DocumentException {

        String realFileName = uploadPath + "/tmp/" + System.currentTimeMillis() + ".pdf";
        Document document = new Document(PageSize.A4);

        try (InputStream in = new FileInputStream(wordFilePath)) {
            // 设置响应头，用于文件下载
            FileUtils.setAttachmentResponseHeader(response, pdfFileName, pdfFileName + ".pdf");

            // 创建PDF写入器
            FileOutputStream outputStream = new FileOutputStream(realFileName);
            PdfWriter.getInstance(document, outputStream);

            document.open();

            // 处理Word文档内容
            processWordDocument(wordFilePath, document);

            document.close();
            outputStream.close();

            // 提供文件下载
            FileUtils.writeBytes(realFileName, response.getOutputStream());
            FileUtils.deleteFile(realFileName);
        }
    }

    /**
     * 处理Word文档并将其内容添加到PDF文档中
     *
     * @param wordFilePath Word文件路径
     * @param document PDF文档对象
     * @throws IOException
     * @throws DocumentException
     */
    private static void processWordDocument(String wordFilePath, Document document)
            throws IOException, DocumentException {

        try (InputStream in = new FileInputStream(wordFilePath)) {
            XWPFDocument xwpfDocument = new XWPFDocument(in);
            // 获取文档中的所有段落
            java.util.List<XWPFParagraph> paragraphs = xwpfDocument.getParagraphs();
            for (XWPFParagraph paragraph : paragraphs) {
                // 创建PDF段落
                Paragraph pdfParagraph = new Paragraph();
                paragraph.getRuns().forEach(run -> {
                    System.out.println(run.getPictureText());
                    System.out.println(run.getFontSize());
                });
                // 设置段落对齐方式
                switch (paragraph.getAlignment()) {
                    case CENTER:
                        pdfParagraph.setAlignment(Element.ALIGN_CENTER);
                        break;
                    case RIGHT:
                        pdfParagraph.setAlignment(Element.ALIGN_RIGHT);
                        break;
                    case LEFT:
                    case BOTH:
                    default:
                        pdfParagraph.setAlignment(Element.ALIGN_LEFT);
                        break;
                }
                // 处理段落中的所有文本块(XWPFRun)
                for (XWPFRun run : paragraph.getRuns()) {
                    String text = run.getText(0);
                    if (text != null) {
                        // 创建带样式的PDF字体
                        Font pdfFont = createPDFFontFromRun(run);
                        Chunk chunk = new Chunk(text, pdfFont);
                        pdfParagraph.add(chunk);
                    }
                }

                // 只有当段落有内容时才添加到文档中
                if (pdfParagraph.size() > 0 && !pdfParagraph.getContent().toString().trim().isEmpty()) {
                    document.add(pdfParagraph);
                }
            }

            // 处理表格（如果有）
            java.util.List<XWPFTable> tables = xwpfDocument.getTables();
            for (XWPFTable table : tables) {
                // 处理表格中的每一行
                java.util.List<XWPFTableRow> rows = table.getRows();
                for (XWPFTableRow row : rows) {
                    StringBuilder rowText = new StringBuilder();
                    java.util.List<XWPFTableCell> cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        String cellText = cell.getText();
                        rowText.append(cellText).append(" | ");
                    }
                    if (rowText.length() > 0) {
                        document.add(new Paragraph(rowText.toString()));
                    }
                }
            }
        }
    }


    /**
     * 处理Excel工作簿并将其内容添加到PDF文档中
     *
     * @param workbook Excel工作簿对象
     * @param document PDF文档对象
     * @throws DocumentException
     */
    private static void processExcelWorkbook(Workbook workbook, Document document)
            throws DocumentException {

        // 添加文档标题（文件名）
        document.add(Chunk.NEWLINE);

        // 处理每个工作表
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            Sheet sheet = workbook.getSheetAt(i);

            // 添加工作表名称
//            Paragraph sheetTitle = new Paragraph("工作表: " + sheet.getSheetName(), PDFUtils.getBigFont());
//            document.add(sheetTitle);
//            document.add(Chunk.NEWLINE);

            // 计算需要的列数
            int columnCount = 0;
            for (Row row : sheet) {
                int lastCellNum = row.getLastCellNum();
                if (lastCellNum > columnCount) {
                    columnCount = lastCellNum;
                }
            }

            if (columnCount > 0) {
                // 创建表格
                PdfPTable table = new PdfPTable(columnCount);
                table.setWidthPercentage(100);
                float[] columnWidths = new float[columnCount];
                for (int j = 0; j < columnCount; j++) {
                    if (j==1||j==0){
                        columnWidths[j] = 30f;
                    }else {
                        columnWidths[j] = 10f;
                    }
                }
                table.setWidths(columnWidths);
                // 处理行数据
                int rowCount = 0;
                for (Row row : sheet) {
                    // 处理每行的单元格
                    for (int colIndex = 0; colIndex < columnCount; colIndex++) {
                        Cell cell = row.getCell(colIndex);
                        String cellValue = getCellValue(cell);
                        Font font = PDFUtils.getFont(10);
                        PdfPCell pdfCell = new PdfPCell(new Phrase(cellValue, font));
                        pdfCell.setPadding(1);

                        // 设置表头样式
                        if (rowCount == 0) {
                            pdfCell.setBackgroundColor(BaseColor.LIGHT_GRAY);
                            pdfCell.setHorizontalAlignment(Element.ALIGN_CENTER);
                            //第一行合并
                            pdfCell.setColspan(columnCount);
                        }

                        table.addCell(pdfCell);
                    }
                    rowCount++;

                    // 限制处理的行数，避免内容过多
//                    if (rowCount > 100) {
//                        PdfPCell pdfCell = new PdfPCell(new Phrase("... (内容过多，省略剩余部分)", PDFUtils.getFont()));
//                        pdfCell.setColspan(columnCount);
//                        pdfCell.setHorizontalAlignment(Element.ALIGN_CENTER);
//                        table.addCell(pdfCell);
//                        break;
//                    }
                }

                document.add(table);
            }

            document.add(Chunk.NEWLINE);
        }
    }


    /**
     * 获取单元格的值
     *
     * @param cell Excel单元格
     * @return 单元格内容字符串
     */
    private static String getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }

        switch (cell.getCellType()) {
            case Cell.CELL_TYPE_STRING:
                return cell.getStringCellValue();
            case Cell.CELL_TYPE_NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    // 避免科学计数法显示数字
                    return String.valueOf(cell.getNumericCellValue());
                }
            case Cell.CELL_TYPE_BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case Cell.CELL_TYPE_FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }



    /**
     * 根据Word文档中的Run样式创建PDF字体
     *
     * @param run Word文档中的文本块
     * @return PDF字体
     */
    private static Font createPDFFontFromRun(XWPFRun run) {
        // 获取字体大小，默认为12
        int fontSize = 12;
        if (run.getFontSize() != -1) {
            fontSize = run.getFontSize();
        }

        // 设置字体样式
        int fontStyle = Font.NORMAL;
        if (run.isBold() && run.isItalic()) {
            fontStyle = Font.BOLDITALIC;
        } else if (run.isBold()) {
            fontStyle = Font.BOLD;
        } else if (run.isItalic()) {
            fontStyle = Font.ITALIC;
        }

        // 创建字体
        Font font = PDFUtils.getFont(fontSize);
        font.setStyle(fontStyle);

        // 处理字体颜色
        if (run.getColor() != null) {
            // 注意：Word中的颜色格式与PDF中的颜色格式可能不同
            // 这里简化处理，实际应用中可能需要转换颜色格式
        }

        return font;
    }

    public static void newConvertWordToPDF(String s, String s1) {
        try (FileOutputStream fos = new FileOutputStream(s1)) {
            WordprocessingMLPackage wordMLPackage = Docx4J.load(new File(s));
            Docx4J.toPDF(wordMLPackage, fos);
        } catch (Docx4JException e) {
            throw new RuntimeException("转换Word文档到PDF失败: " + s, e);
        } catch (FileNotFoundException e) {
            throw new RuntimeException("找不到文件: " + s + " 或 " + s1, e);
        } catch (IOException e) {
            throw new RuntimeException("写入PDF文件时发生IO错误: " + s1, e);
        }
    }


    public  void pushRd(OutWordRdDetails data, HttpServletResponse response,String uploadPath) {
        String attName = data.getRdName()+new Date().getTime() + ".pdf";
        String realFileName = uploadPath+"/tmp/"+new Date().getTime() + ".pdf";
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        Document document=new Document();
        try {
            FileUtils.setAttachmentResponseHeader(response, data.getRdName(),attName);
            FileOutputStream outputStream = new FileOutputStream(realFileName);
            PdfWriter.getInstance(document, outputStream);
            document.open();
            Paragraph paragraph = new Paragraph(data.getRdName(), getTitleFont());
            paragraph.setAlignment(1);
            document.add(paragraph);
            addPDFDocument(document,"项目起止时间： ",data.getStartEndTime());
            addPDFDocument(document,"公司名称： ",data.getUserName());
            addPDFDocument(document,"项目负责人： ",data.getConsultantName());
            addPDFDocument(document,"技术领域： ",data.getTechnicalField());
            addPDFDocument(document,"技术来源： ",data.getTechnologySource());
            addPDFDocument(document,"研发费用总预计： ",data.getTotalAmount().toEngineeringString()+" 万元");
            addPDFDocument(document,"研发目的/立项目的/实施方式",null);
            addPDFContent(document,"        "+data.getRdObjective());
            addPDFDocument(document,"核心技术/创新点",null);
            addPDFContent(document,"        "+data.getCoreTechnology());
            addPDFDocument(document,"成果",null);
            addPDFContent(document,"        "+data.getAchieveResults());
            document.close();
            outputStream.close();
            FileUtils.writeBytes(realFileName, response.getOutputStream());
            FileUtils.deleteFile(realFileName);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private  void addPDFDocument(Document document, String key, String value) throws DocumentException {
        if(key!=null) {
            document.add(new Chunk(key, getBigFont()));
        }
        Phrase phrase = new Phrase(value, getFont());
        phrase.setLeading(40);
        if(value!=null)document.add(phrase);
        document.add(Chunk.NEWLINE);
    }

    private static  void addPDFDocument(Document document,  String value) throws DocumentException {
        Phrase phrase = new Phrase(value, getFont());
        phrase.setLeading(40);
        if(value!=null)document.add(phrase);
        document.add(Chunk.NEWLINE);
    }

    private void addPDFContent(Document document,  String value) throws DocumentException {
        Phrase phrase = new Phrase(value, getFont());
        phrase.setLeading(25);
        if(value!=null)document.add(phrase);
        document.add(Chunk.NEWLINE);
        document.add(Chunk.NEWLINE);
    }


    public static Font getTitleFont(){
        return setFont(24,Font.NORMAL);
    }

    public static Font getBigFont(){
        return setFont(16,Font.NORMAL);
    }

    public static Font getFont(){
        Font font =setFont(12,Font.NORMAL);
        return font;
    }

    public static Font getFont(int size){
        Font font =setFont(size,Font.NORMAL);
        return font;
    }


    /**
     *
     * @param size  大小
     * @return
     */
    public static Font setFont(Integer size,Integer style){
            BaseFont baseFont = null;
            Font font=null;
        try {
            baseFont=BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            font=new Font(baseFont,size,style);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return font;
    }




    private static String   CHECKNO="报销编号：";
    private static String   APPLYDEP="申请部门：";
    private static String   ANAME="报销人：";
    private static String   CREATETIME="报销日期：";
    private static String   REMARKS="报销事由：";
    private static String   BANK_ACCOUNT="收款方式：";
    private static String   BLANK="      ";
    public static void pushExpenseTitle(Document document, MainExpenseAccount mainExpenseAccount) throws DocumentException {


        StringBuilder builder = new StringBuilder();
        builder.append(CHECKNO).append(mainExpenseAccount.getCheckNo()).append(BLANK)
                    .append(APPLYDEP).append(mainExpenseAccount.getApplyDepName()).append(BLANK).append(BLANK).append(BLANK)
                    .append(ANAME).append(mainExpenseAccount.getAname());
        Paragraph tile1=new Paragraph(builder.toString(),getFont(8));
        document.add(tile1);
        String creactTime= DateUtils.formatDate(mainExpenseAccount.getCreateTime(), AFTConstants.YYYYMMDD);
        int x2 = CREATETIME.length() + creactTime.length()/2 +
                REMARKS.length() + mainExpenseAccount.getRemarks().length() +
                BANK_ACCOUNT.length() + mainExpenseAccount.getBank().length() +
                mainExpenseAccount.getAccounts().length()/2 + mainExpenseAccount.getName().length();
        builder.setLength(0);
        if (x2>55){
            builder.append(CREATETIME).append(creactTime).append(BLANK)
                    .append(REMARKS).append(mainExpenseAccount.getRemarks()).append(BLANK)
                    .append(BANK_ACCOUNT).append(mainExpenseAccount.getBank()).append(BLANK)
                    .append(mainExpenseAccount.getAccounts()).append(BLANK)
                    .append(mainExpenseAccount.getName());
        }else {
            int y =(60-x2)*2;
            StringBuilder blank= new StringBuilder();
            for (int i = 0; i < y; i++) {
                blank.append(" ");
            }
            builder.append(CREATETIME).append(creactTime).append(blank)
                    .append(REMARKS).append(mainExpenseAccount.getRemarks()).append(blank)
                    .append(BANK_ACCOUNT).append(mainExpenseAccount.getBank()).append(BLANK)
                    .append(mainExpenseAccount.getAccounts()).append(BLANK)
                    .append(mainExpenseAccount.getName());
        }
        Paragraph tile2=new Paragraph(builder.toString(),getFont(8));
        document.add(tile2);
    }
}
