package com.ruoyi.project.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;


import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hslf.usermodel.HSLFShape;
import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.hslf.usermodel.HSLFTextShape;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.ooxml.POIXMLProperties;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextShape;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;

@Component
public class DocumentUtil {
    private static final Map<String, String> FILE_TYPE_MAP = new HashMap<>();
    static {
        FILE_TYPE_MAP.put("FFD8FF", "jpg");
        FILE_TYPE_MAP.put("89504E47", "png");
        FILE_TYPE_MAP.put("47494638", "gif");
        FILE_TYPE_MAP.put("424D", "bmp");
        FILE_TYPE_MAP.put("49492A00", "tif");
        FILE_TYPE_MAP.put("4D4D002A", "tif");
        FILE_TYPE_MAP.put("52494646", "webp");
        FILE_TYPE_MAP.put("25504446", "pdf");
        FILE_TYPE_MAP.put("504B0304", "zip or office (docx, xlsx, pptx)");
        FILE_TYPE_MAP.put("D0CF11E0", "office (doc, xls, ppt)");
//        FILE_TYPE_MAP.put("52617221", "rar");
        FILE_TYPE_MAP.put("526172211C07", "rar5");
        FILE_TYPE_MAP.put("526172211A07", "rar");
        FILE_TYPE_MAP.put("377ABCAF271C", "7z");
        FILE_TYPE_MAP.put("74686573", "txt");  // 以 "the" 开头的文本文件
        FILE_TYPE_MAP.put("8A9DE0D14725E20B7A74", "jiami");  // 以 "the" 开头的文本文件
    }

    public String getFileTypeByMagicNumber(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(b & 0xFF).toUpperCase();
            if (hex.length() == 1) {
                hexString.append("0");
            }
            hexString.append(hex);
        }

        // 判断是否为 RAR 格式
        if (hexString.toString().startsWith("52617221")) {
            // 如果是以 "52617221" 开头，则进一步检查是否为 RAR5
            if (hexString.toString().startsWith("526172211A0701")) {
                return "rar5";  // RAR5 格式
            } else {
                return "rar";   // 普通 RAR 格式
            }
        }

        for (Map.Entry<String, String> entry : FILE_TYPE_MAP.entrySet()) {
            if (hexString.toString().startsWith(entry.getKey())) {
                return entry.getValue();
            }
        }

        if (hexString.toString().matches("[0-9A-Fa-f]*") && hexString.length() > 0) {
            // 若符合文本文件的条件（只包含ASCII字符），认为是txt文件
            return "txt";
        }


        return null;
    }

    public String checkZipOrOfficeFile(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        if (fileName != null) {
            if (fileName.endsWith(".xlsx")) return "xlsx";
            if (fileName.endsWith(".docx")) return "docx";
            if (fileName.endsWith(".pptx")) return "pptx";
            if (fileName.endsWith(".zip")) return "zip";
        }
        return "unknown zip format";
    }

    public String checkLegacyOfficeFile(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        if (fileName != null) {
            if (fileName.endsWith(".xls")) return "xls";
            if (fileName.endsWith(".doc")) return "doc";
            if (fileName.endsWith(".ppt")) return "ppt";
        }
        return "unknown office format";
    }

    public String extractContent(String fileType, InputStream inputStream) throws IOException {
        String content = "";
        if (fileType.equals("doc")) {
            content = extractDocContent(inputStream);
        } else if (fileType.equals("docx")) {
            content = extractDocxContent(inputStream);
        } else if (fileType.equals("txt")) {
            content = extractTxtContent(inputStream);
        }  else if (fileType.equals("pdf")) {
            content = extractPDFContent(inputStream);
        } else if (fileType.equals("xls")) {
            content = extractXLSContent(inputStream);
        } else if (fileType.equals("xlsx")) {
            content = extractXLSXContent(inputStream);
        } else if (fileType.equals("ppt")) {
            content = extractPPTContent(inputStream);
        } else if (fileType.equals("pptx")) {
            content = extractPPTXContent(inputStream);
        } else {
            System.out.println("Unsupported file format.");
        }
        return content;
    }



    public String extractPPTXContent(InputStream inputStream) {
        StringBuilder extractedText = new StringBuilder();
        try {
            XMLSlideShow pptx = new XMLSlideShow(inputStream);

            for (XSLFSlide slide : pptx.getSlides()) {
                for (XSLFShape shape : slide.getShapes()) {
                    if (shape instanceof XSLFTextShape) {
                        XSLFTextShape textShape = (XSLFTextShape) shape;
                        extractedText.append(textShape.getText()+"\n");
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return extractedText.toString().replaceAll("\\r?\\n", "</br>").replaceAll("\\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
    }
    // 提取 .ppt 文件的文本内容
    public String extractPPTContent(InputStream inputStream) {
        StringBuilder extractedText = new StringBuilder();
        try {
            HSLFSlideShow ppt = new HSLFSlideShow(inputStream);

            for (HSLFSlide slide : ppt.getSlides()) {
                // 遍历幻灯片中的所有形状
                for (HSLFShape shape : slide.getShapes()) {
                    extractedText.append(slide.getSlideNumber() + "\n");
                    if (shape instanceof HSLFTextShape) {
                        HSLFTextShape textShape = (HSLFTextShape) shape;
                        extractedText.append(textShape.getText() + "\n");
                    }
                }
                extractedText.append("\n");
            }
            //jsonObject.put("content",extractedText.toString());
            return extractedText.toString().replaceAll("\\r?\\n", "</br>").replaceAll("\\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return "";
    }
    public String extractXLSXContent(InputStream inputStream) {
        StringBuilder extractedText = new StringBuilder();
        try{
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            // 遍历每个工作表
            for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
                XSSFSheet sheet = workbook.getSheetAt(sheetIndex);
                extractedText.append(sheet.getSheetName() + "\n");
                // 遍历每一行
                for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                    XSSFRow row = sheet.getRow(rowIndex);

                    if (row != null) {
                        // 遍历每个单元格
                        for (int cellIndex = 0; cellIndex < row.getLastCellNum(); cellIndex++) {
                            XSSFCell cell = row.getCell(cellIndex);
                            if (cell != null) {
                                // 获取单元格内容
                                switch (cell.getCellType()) {
                                    case STRING:
                                        extractedText.append(cell.getStringCellValue() + "\t");
                                        break;
                                    case NUMERIC:
                                        extractedText.append(cell.getNumericCellValue() + "\t");
                                        break;
                                    case BOOLEAN:
                                        extractedText.append(cell.getBooleanCellValue() + "\t");
                                        break;
                                    case FORMULA:
                                        extractedText.append(cell.getCellFormula() + "\t");
                                        break;
                                    default:
                                        extractedText.append(" \t");
                                        break;
                                }
                            }
                        }
                        extractedText.append("\n");
                    }
                }
                extractedText.append("\n");
            }
            //
            return extractedText.toString().replaceAll("\\r?\\n", "</br>").replaceAll("\\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return "";
    }

    public String extractXLSContent(InputStream inputStream) {
        StringBuilder extractedText = new StringBuilder();
        try{
            HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
            for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
                HSSFSheet sheet = workbook.getSheetAt(sheetIndex);
                extractedText.append((sheet.getSheetName() + "\n"));
                // 遍历每一行
                for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                    HSSFRow row = sheet.getRow(rowIndex);
                    if (row != null) {
                        // 遍历每个单元格
                        for (int cellIndex = 0; cellIndex < row.getLastCellNum(); cellIndex++) {
                            HSSFCell cell = row.getCell(cellIndex);
                            if (cell != null) {
                                // 获取单元格内容
                                switch (cell.getCellType()) {
                                    case STRING:
                                        extractedText.append((cell.getStringCellValue() + "\t"));
                                        break;
                                    case NUMERIC:
                                        extractedText.append(cell.getNumericCellValue() + "\t");
                                        break;
                                    case BOOLEAN:
                                        extractedText.append(cell.getBooleanCellValue() + "\t");
                                        break;
                                    case FORMULA:
                                        extractedText.append(cell.getCellFormula() + "\t");
                                        break;
                                    default:
                                        extractedText.append(" \t");
                                        break;
                                }
                            }
                        }
                        extractedText.append("\n");
                    }
                }
                extractedText.append("\n");
            }
            return extractedText.toString().replaceAll("\\r?\\n", "</br>").replaceAll("\\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return "";
    }

    private String extractPDFContent(InputStream inputStream) throws IOException {
        StringBuilder extractedText = new StringBuilder();

        //ocr
        try (PDDocument document = PDDocument.load(inputStream)) {
            PDFTextStripper pdfStripper = new PDFTextStripper();
            String textContent = pdfStripper.getText(document);
            extractedText.append(textContent).append("\n");
            // 关闭 PDF 文档
            document.close();
            return extractedText.toString().replaceAll("\\r?\\n", "</br>").replaceAll("\\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
        } catch (Exception e) {
            throw new IOException(e);
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }


    public String extractTxtContent(InputStream inputStream) {
        StringBuilder content = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) {
            String line;
            while ((line = br.readLine()) != null) {
                content.append(line).append("\n");  // 每行内容添加换行符
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return content.toString();
    }

    // Method for extracting .doc content
    private String extractDocContent(InputStream inputStream) throws IOException {
        try {
            StringBuilder extractedText = new StringBuilder();
            HWPFDocument doc = new HWPFDocument(inputStream);
            extractedText.append(doc.getDocumentText()).append("\n");
            return extractedText.toString().replaceAll("\\r?\\n", "</br>").replaceAll("\\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    // Method for extracting .docx content (text and images)
    private String extractDocxContent(InputStream inputStream) throws IOException {
        try {
            StringBuilder extractedText = new StringBuilder();
            XWPFDocument docx = new XWPFDocument(inputStream);
            for (XWPFParagraph paragraph : docx.getParagraphs()) {
                extractedText.append(paragraph.getText());
                extractedText.append("</br>");
            }
            for (XWPFTable table : docx.getTables()) {
                for (XWPFTableRow row : table.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
//                        extractedText.append(cell.getText()).append("\t");
                        extractedText.append(cell.getText()).append("&nbsp;&nbsp;&nbsp;&nbsp;");
                    }
                    extractedText.append("</br>");
                }
            }
            return extractedText.toString().replaceAll("\\r?\\n", "</br>").replaceAll("\\t", "&nbsp;&nbsp;&nbsp;&nbsp;");

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }





}
