package com.seeyon.apps.esign.utils;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Section;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STPageOrientation;

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

public class DocumentA4Checker {

    // A4标准磅值 宽595 高842，允许误差5pt
    private static final float A4_WIDTH = 595.0f;
    private static final float A4_HEIGHT = 842.0f;
    private static final float TOLERANCE = 5.0f;
    // twips 转 pt： /20
    private static final float TWIPS_TO_PT = 20.0f;

    public static boolean isFirstPageA4(File file) {
        if (file == null || !file.exists() || !file.isFile()) {
            return false;
        }

        String fileName = Optional.ofNullable(file.getName()).orElse("");
        String suffix = getFileSuffix(fileName).toLowerCase();

        try {
            switch (suffix) {
                case "pdf":
                    try (InputStream in = new FileInputStream(file)) {
                        return checkPdfFirstPageA4(in);
                    }
                case "doc":
                    // 先尝试 doc 解析，若文件实际为 OOXML 则回退到 docx
                    try (InputStream in = new FileInputStream(file)) {
                        return checkDocFirstPageA4(in);
                    } catch (IllegalArgumentException e) {
                        try (InputStream in = new FileInputStream(file)) {
                            return isDocxA4Portrait(in);
                        }
                    }
                case "docx":
                    try (InputStream in = new FileInputStream(file)) {
                        return isDocxA4Portrait(in);
                    }
                default:
                    return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 校验 PDF 第一页是否竖版 A4
     */
    private static boolean checkPdfFirstPageA4(InputStream in) throws IOException {
        try (PDDocument document = PDDocument.load(in)) {
            if (document.getNumberOfPages() == 0) return false;

            PDPage page = document.getPage(0);
            float w = page.getMediaBox().getWidth();
            float h = page.getMediaBox().getHeight();

            return Math.abs(w - A4_WIDTH) <= TOLERANCE
                    && Math.abs(h - A4_HEIGHT) <= TOLERANCE;
        }
    }

    /**
     * 校验 doc 第一页是否竖版 A4
     */
    private static boolean checkDocFirstPageA4(InputStream in) throws IOException {
        try (HWPFDocument doc = new HWPFDocument(in)) {
            Section section = doc.getRange().getSection(0);

            int widthTwips = section.getPageWidth();
            int heightTwips = section.getPageHeight();

            float widthPt = widthTwips / 20f;
            float heightPt = heightTwips / 20f;

            return Math.abs(widthPt - A4_WIDTH) <= TOLERANCE
                    && Math.abs(heightPt - A4_HEIGHT) <= TOLERANCE;
        }
    }

    /**
     * 校验 docx 第一页是否竖版 A4（POI 5.x 兼容版）
     */
    public static boolean isDocxA4Portrait(InputStream in) throws IOException {
        try (XWPFDocument docx = new XWPFDocument(in)) {
            CTSectPr sectPr = docx.getDocument().getBody().getSectPr();
            if (sectPr == null || sectPr.getPgSz() == null) {
                // 没有设置页面大小 → 默认认为是A4（Word默认行为）
                return true;
            }

            CTPageSz pgSz = sectPr.getPgSz();

            // 判断是否横向
            if (pgSz.getOrient() != null) {
                STPageOrientation.Enum orient = pgSz.getOrient();
                if (STPageOrientation.LANDSCAPE.equals(orient)) {
                    return false;
                }
            }

            // 兼容 BigInteger 和 BigDecimal 两种实现
            Number wTwips = (Number) pgSz.getW();
            Number hTwips = (Number) pgSz.getH();

            if (wTwips == null || hTwips == null) {
                return false;
            }

            float wPt = wTwips.floatValue() / TWIPS_TO_PT;
            float hPt = hTwips.floatValue() / TWIPS_TO_PT;

            return Math.abs(wPt - A4_WIDTH) <= TOLERANCE
                    && Math.abs(hPt - A4_HEIGHT) <= TOLERANCE;
        }
    }

    private static String getFileSuffix(String fileName) {
        int idx = fileName.lastIndexOf('.');
        return idx == -1 ? "" : fileName.substring(idx + 1);
    }
}