package com.vetti.common.utils.readFile;

import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

public  class FileContentUtil {

    private FileContentUtil() {}

    /**
     * 读取不同类型文件的文本内容。
     *
     * @param is                 输入流（由调用方负责关闭）
     * @param fileExtension      文件扩展名（小写，例如：txt、pdf、docx、doc、html）
     * @return                   提取到的文本
     * @throws IOException       IO 相关异常
     */
    public static String readFileContent(InputStream is, String fileExtension) throws IOException {
        return readFileContent(is, fileExtension, null);
    }

    /**
     * 读取不同类型文件的文本内容，支持在 PDF 文本为空时进行 OCR。
     *
     * @param is                 输入流（由调用方负责关闭）
     * @param fileExtension      文件扩展名（小写，例如：txt、pdf、docx、doc、html）
     * @param tesseractDatapath  Tesseract 数据路径（可选；为空则不设置）
     * @return                   提取到的文本
     * @throws IOException       IO 相关异常
     */
    public static String readFileContent(InputStream is, String fileExtension, String tesseractDatapath) throws IOException {
        Objects.requireNonNull(is, "InputStream cannot be null");
        Objects.requireNonNull(fileExtension, "fileExtension cannot be null");

        switch (fileExtension) {
            case "txt": {
                byte[] bytes = toByteArray(is);
                return new String(bytes, StandardCharsets.UTF_8);
            }
            case "pdf": {
                try (PDDocument doc = PDDocument.load(is)) {
                    PDFTextStripper textStripper = new PDFTextStripper();
                    String str = textStripper.getText(doc);
//                    str = str.replace("\r", "").replace("\n", "");
                    if (StringUtils.isEmpty(str)) {
                        int pageCount = doc.getNumberOfPages();
                        if (pageCount > 0) {
                            PDFRenderer renderer = new PDFRenderer(doc);
                            ITesseract tesseract = new Tesseract();
                            if (tesseractDatapath != null) {
                                tesseract.setDatapath(tesseractDatapath);
                            }
                            tesseract.setLanguage("eng+chi_sim");
                            StringBuilder fullText = new StringBuilder();
                            for (int i = 0; i < pageCount; i++) {
                                BufferedImage image = renderer.renderImageWithDPI(i, 300, ImageType.BINARY);
                                try {
                                    String pageText = tesseract.doOCR(image);
                                    fullText.append(pageText).append("\n\n");
                                } catch (TesseractException e) {
                                    throw new RuntimeException(e);
                                }
                            }
                            str = fullText.toString();
                        }
                    }
                    return str;
                }
            }
            case "docx": {
                try (XWPFDocument xdoc = new XWPFDocument(is);
                     XWPFWordExtractor extractor = new XWPFWordExtractor(xdoc)) {
                    return extractor.getText();
                }
            }
            case "doc": {
                try (WordExtractor extractor = new WordExtractor(is)) {
                    return extractor.getText();
                }
            }
            case "html": {
                // 直接从 InputStream 解析 HTML，避免中间落地文件
                Document doc = Jsoup.parse(is, "UTF-8", "");
                return doc.body() != null ? doc.body().html() : "";
            }
            default:
                return "";
        }
    }

    private static byte[] toByteArray(InputStream is) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream(Math.max(32, is.available()));
        byte[] buf = new byte[8192];
        int len;
        while ((len = is.read(buf)) != -1) {
            bos.write(buf, 0, len);
        }
        return bos.toByteArray();
    }
}