package com.yaoyicloud.factory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;

import com.amazonaws.services.s3.model.S3Object;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.deepoove.poi.data.DocxRenderData;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import com.yaoyicloud.easier.common.file.core.FileProperties;
import com.yaoyicloud.easier.common.file.core.FileTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.BodyElementType;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import org.w3c.dom.Node;

/**
 * 抽象渲染器
 *
 */

@Slf4j
public abstract class CSOAbstractRender extends AbstractRender {
    private final FileTemplate ossTemplate;
    private final FileProperties properties;

    /*
     * 子模版路径
     */
    private String subTemplatePath;

    public CSOAbstractRender(String cwd, FileTemplate ossTemplate, FileProperties properties) {
        super(cwd);
        this.ossTemplate = ossTemplate;
        this.properties = properties;
    }

    public final String createCSODocument(String info, InputStream inputStream, String relationId, Integer counter,
        String moduleType) throws IOException {
        // 获取数据
        Map<String, Object> originalMap = this.renderDocx(info, relationId, counter);
        boolean sensitiveFlag = (Boolean) originalMap.get("sensitiveFlag"); // 处理数据脱敏
        Map<String, Object> sensitiveMap = this.sensitiveData(originalMap, sensitiveFlag);
        ConfigureBuilder builder = this.builder(relationId);
        String docxResultPath = this.csoCompile(sensitiveMap, inputStream, builder, relationId, moduleType);
        log.info("文档导出成功，文档路径为: {}", docxResultPath);
        return docxResultPath;

    }

    @SuppressWarnings({"checkstyle:ParameterNumber", "checkstyle:NestedIfDepth"})
    public String csoCompile(Map<String, Object> dataMap, InputStream inputStream,
        ConfigureBuilder builder, String relationId, String moduleType)
        throws IOException {

        if (moduleType.equals("CSO_PROMOTION_DETAILS") || moduleType.equals("CSO_ATTACHMENT_XINHUA")) {
            Configure config = builder.build();
            XWPFTemplate subTemplate = null;
            try {
                if (StringUtils.isEmpty(subTemplatePath)) {
                    // 调用getSubTemplatePath()触发初始化
                    subTemplatePath = getSubTemplatePath();
                }
                subTemplate = XWPFTemplate.compile(subTemplatePath, config).render(dataMap);
                try (ByteArrayOutputStream nestOutput = new ByteArrayOutputStream()) {
                    subTemplate.write(nestOutput);
                    try (ByteArrayInputStream nestInput = new ByteArrayInputStream(nestOutput.toByteArray())) {
                        DocxRenderData docxRenderData = new DocxRenderData(nestInput);
                        dataMap.put("nestfile", docxRenderData);
                    }
                }
            } finally {
                if (subTemplate != null) {
                    subTemplate.close();
                }
            }
        }
        String sourcePath = super.documentCompile(dataMap, inputStream, builder, relationId, moduleType);
        File sourceFile = new File(sourcePath);
        try (NiceXWPFDocument xwpfDocument = new NiceXWPFDocument(new FileInputStream(sourceFile))) {
            // 3.1 删除空表格
            List<XWPFTable> allTables = xwpfDocument.getAllTables();
            for (XWPFTable table : allTables) {
                if (table.getRows().size() <= 1) {
                    Node domNode = table.getCTTbl().getDomNode();
                    Node parentNode = domNode.getParentNode();
                    parentNode.removeChild(domNode);
                }
            }

            // 3.2 删除空标题行
            List<IBodyElement> bodyElements = xwpfDocument.getXWPFDocument().getBodyElements();
            for (int i = bodyElements.size() - 1; i >= 0; i--) {
                IBodyElement ele = bodyElements.get(i);
                if (ele.getElementType() == BodyElementType.PARAGRAPH) {
                    XWPFParagraph paragraph = (XWPFParagraph) ele;
                    if (paragraph.getText().contains("EMPTY")) {
                        xwpfDocument.removeBodyElement(i);
                        if (i - 1 >= 0) {
                            IBodyElement aboveEle = bodyElements.get(i - 1);
                            if (aboveEle.getElementType() == BodyElementType.PARAGRAPH) {
                                XWPFParagraph abovePara = (XWPFParagraph) aboveEle;
                                if (abovePara.getText().trim().isEmpty()) {
                                    xwpfDocument.removeBodyElement(i - 1);
                                }
                            }
                        }
                    }
                }
            }

            try (FileOutputStream fos = new FileOutputStream(sourceFile)) {
                xwpfDocument.write(fos); // 覆盖写入原文件
            }
            this.docxResultPath = sourcePath;
        }

        return this.docxResultPath;
    }

    protected DynamicTableRenderPolicy getDynamicTableRenderPolicy(Map<String, Object> data) {
        boolean sensitiveFlag = (Boolean) data.get("sensitiveFlag");
        Map<Integer, String> userNameMap = (Map<Integer, String>) data.get("userNameMap");
        return tableDynamicPolicy(sensitiveFlag, userNameMap);
    }

    protected String getSubTemplatePath() {
        // 如果已经获取过模板路径，直接返回缓存的路径
        if (subTemplatePath != null && new File(subTemplatePath).exists()) {
            return subTemplatePath;
        }

        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            // 从OSS获取对象
            S3Object s3Object = ossTemplate.getObject(properties.getBucketName(), "subtemplate.docx");
            inputStream = s3Object.getObjectContent();

            // 创建临时文件
            File tempFile = Files.createTempFile("subtemplate-", ".docx").toFile();
            // 标记临时文件在JVM退出时删除
            tempFile.deleteOnExit();

            // 将OSS文件内容写入临时文件
            outputStream = new FileOutputStream(tempFile);
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            // 保存临时文件路径
            subTemplatePath = tempFile.getAbsolutePath();
            return subTemplatePath;

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                }
            }
        }
    }

}
