package com.storlead.framework.common.util;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.Map;

/**
 * @program: storlead-saas-platform
 * @description:
 * @author: chenkq
 * @create: 2026-05-18 17:50
 */
public class WordUtils {

    private static final Logger log = LoggerFactory.getLogger(WordUtils.class);
    private static WordUtils service = null;

    public WordUtils() {
        super();
    }

    public static WordUtils getInstance() {
        if(service == null) {
            service = new WordUtils();
        }
        return service;
    }

    /**
     * 导出至word
     * @param ftl ftl模板地址
     * @param fileName 文件名
     * @param dataMap 导出数据
     * @param response response
     */
    public void exportDocFile(String ftl, String fileName, Map<String, Object> dataMap, HttpServletResponse response){
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("UTF-8");

        OutputStreamWriter oWriter = null;
        Writer out = null;
        try {
            ClassPathResource resource = new ClassPathResource(ftl);
            File file = File.createTempFile("StatementTemp",".ftl");
            FileUtils.copyURLToFile(resource.getURL(), file);
            String templateFile = file.getAbsolutePath();
            templateFile = pathReplace(templateFile);
            if(null == templateFile){
                log.error("导出失败，模板不存在");
                return;
            }
            String ftlPath = templateFile.substring(0, templateFile.lastIndexOf("/"));
            log.info("模板路径：{}", ftlPath);
            // FTL文件所存在的位置--绝对路径
            configuration.setDirectoryForTemplateLoading(new File(ftlPath));
            //configuration.setClassForTemplateLoading(this.getClass(), ftlPath);
            String ftlFile = templateFile.substring(templateFile.lastIndexOf("/")+1);
            log.info("模板临时文件名称：{}", ftlFile);
            // 模板文件名
            Template template = configuration.getTemplate(ftlFile);

            response.reset();
            response.setContentType("application/msword; charset=utf-8");
            String filename = fileName + ".doc";
            response.setHeader("Content-Disposition", "attachment; filename="+ urlEncode(filename));
            oWriter = new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8);
            out = new BufferedWriter(oWriter);
            template.process(dataMap, out);
        } catch (Exception e) {
            log.error("导出word失败：", e);
        } finally {
            try {
                if(null != out){
                    out.close();
                }
                if(null != oWriter){
                    oWriter.close();
                }
            } catch (IOException e) {
                log.error("Writer or OutputStreamWriter close failed:{}", e.getMessage());
            }
        }
    }



    /**
     * 导出至word
     * @param ftl ftl模板地址
     * @param fileName 文件名
     * @param dataMap 导出数据
     * @param response response
     */
    public ResponseEntity<FileSystemResource> repExportDocFile(String ftl, String fileName, Map<String, Object> dataMap) {
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("UTF-8");

        try {
            // 1. 获取模板文件
            ClassPathResource resource = new ClassPathResource(ftl);
            File tempTemplate = File.createTempFile("StatementTemp", ".ftl");
            FileUtils.copyURLToFile(resource.getURL(), tempTemplate);

            String templatePath = pathReplace(tempTemplate.getAbsolutePath());
            if (templatePath == null) {
                log.error("导出失败，模板不存在");
                return ResponseEntity.notFound().build();
            }

            String ftlDir = templatePath.substring(0, templatePath.lastIndexOf("/"));
            configuration.setDirectoryForTemplateLoading(new File(ftlDir));
            String ftlFileName = templatePath.substring(templatePath.lastIndexOf("/") + 1);
            Template template = configuration.getTemplate(ftlFileName);

            // 2. 生成 Word 临时文件
            File tempWordFile = File.createTempFile("Export-", ".doc");
            try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempWordFile), StandardCharsets.UTF_8))) {
                template.process(dataMap, out);
            }

            // 3. 返回 Word 文件
            FileSystemResource resourceBody = new FileSystemResource(tempWordFile);
            String downloadFileName = fileName + ".doc";

//            response.setContentType("application/msword; charset=utf-8");
//            String filename = fileName + ".doc";
//            response.setHeader("Content-Disposition", "attachment; filename="+ urlEncode(filename));

            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + urlEncode(downloadFileName))
//                    .header("application/octet-stream", "attachment; filename=" + urlEncode(downloadFileName))
                    .contentType(MediaType.parseMediaType("application/msword"))
                    .contentLength(resourceBody.contentLength())
                    .body(resourceBody);

        } catch (Exception e) {
            log.error("导出word失败：", e);
            return ResponseEntity.status(500).build();
        }
    }

    public String exportDocToUrl(String ftl, String fileName, Map<String, Object> dataMap) {
        try {
            // 生成 Word 文件
            Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
            configuration.setDefaultEncoding("UTF-8");

            ClassPathResource resource = new ClassPathResource(ftl);
            File tempTemplate = File.createTempFile("Template-", ".ftl");
            FileUtils.copyURLToFile(resource.getURL(), tempTemplate);

            String templatePath = pathReplace(tempTemplate.getAbsolutePath());
            String ftlDir = templatePath.substring(0, templatePath.lastIndexOf("/"));
            configuration.setDirectoryForTemplateLoading(new File(ftlDir));
            String ftlFileName = templatePath.substring(templatePath.lastIndexOf("/") + 1);

            Template template = configuration.getTemplate(ftlFileName);

            // 1. 导出目录（容器内路径）
            File exportDir = new File("/app/tempfiles");
            if (!exportDir.exists()) {
                exportDir.mkdirs();
            }

            File targetFile = new File(exportDir, fileName + ".doc");

            try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile), StandardCharsets.UTF_8))) {
                template.process(dataMap, out);
            }

            // 2. 拼接 URL（这里假设映射后访问路径是 /export/）
            return "/static/file/" + fileName + ".doc";

        } catch (Exception e) {
            log.error("生成word失败：", e);
            return null;
        }
    }


    public void exportDocFileTest(String ftl, String fileName, Map<String, Object> dataMap, HttpServletResponse response){
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("UTF-8");

        try {
            // 直接从类路径加载FTL资源
            ClassPathResource resource = new ClassPathResource(ftl);
            URL templateUrl = resource.getURL();

            // 注意：这里需要确保Freemarker可以直接从URL加载模板，或者您需要将其内容复制到字符串或ByteArrayInputStream
            // 但对于大多数情况，如果模板在类路径中，您可以直接使用setClassLoaderForTemplateLoading
            configuration.setClassForTemplateLoading(this.getClass().getClassLoader().getClass(), "");

            // 获取模板
            Template template = configuration.getTemplate(ftl);

            // 设置响应头
            response.reset();
            response.setContentType("application/octet-stream; charset=utf-8");
            String encodedFileName = java.net.URLEncoder.encode(fileName + ".doc", StandardCharsets.UTF_8.toString());
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");

            // 使用BufferedWriter写入响应
            try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8))) {
                template.process(dataMap, writer);
                writer.flush(); // 确保所有数据都被写入响应
            }

        } catch (IOException | TemplateException e) {
            // 处理异常，例如记录日志或返回错误响应
            // 注意：在实际应用中，您可能想要将异常信息返回给客户端或进行其他错误处理
            System.err.println("导出word失败：" + e.getMessage());
        }
    }

    /**
     * 创建doc文件
     * @param ftl src/main/resources/ftl/xxx.ftl
     * @param dataMap 导出数据
     * @param exportPath  eg: /tmp/test/test123.doc
     * @param loadType  设置路径加载方式。1-绝对路径，2-项目相对路径
     * @return {@link File}
     * @ver v1.0.0
     */
    public File createDocFile(String ftl, Map<String, Object> dataMap, String exportPath, int loadType) {
        File file = new File(ftl);
        String templateFile = file.getAbsolutePath();
        Template t = null;
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("UTF-8");
        try {
            templateFile = pathReplace(templateFile);
            if(null == templateFile){
                log.error("模板不存在！");
                return null;
            }
            String ftlPath = templateFile.substring(0, templateFile.lastIndexOf("/"));
            if(loadType == 1) {
                // FTL文件所存在的位置
                configuration.setDirectoryForTemplateLoading(new File(ftlPath));
            }else {
                //以类加载的方式查找模版文件路径
                configuration.setClassForTemplateLoading(this.getClass(), ftlPath);
            }

            String ftlFile = templateFile.substring(templateFile.lastIndexOf("/")+1);
            // 模板文件名
            t = configuration.getTemplate(ftlFile);

            File outFile = new File(exportPath);
            Writer out =  new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(outFile.toPath())));
            t.process(dataMap, out);
        } catch (Exception e) {
            log.error("导出word文档出错：{}", e.getMessage());
        }
        return null;
    }

    /**
     *  把路径的\替换成/
     * @param path 路径
     * @return {@link String}
     * @ver v1.0.0
     */
    private static String pathReplace(String path) {
        if(!ObjectUtils.isEmpty(path)) {
            path = path.replace("\\",  "/");
//                path = path.replace("\"", "/");
        }
        return path;
    }

    /**
     * 图片转base64
     * @param imgStr 图片 http 地址
     * @return {@link String}
     * @ver v1.0.0
     */
    public static String getImgStrToBase64(String imgStr) {
        if(StringUtils.isEmpty(imgStr)){
            return "";
        }
        log.info("imgStr:===>{}",imgStr);
        InputStream inputStream = null;
        ByteArrayOutputStream outputStream = null;
        byte[] buffer = null;
        try {
            //判断网络链接图片文件/本地目录图片文件
            if (imgStr.startsWith("http://") || imgStr.startsWith("https://")) {
                // 创建URL
                URL url = new URL(imgStr);
                // 创建链接
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);
                inputStream = conn.getInputStream();
                outputStream = new ByteArrayOutputStream();
                // 将内容读取内存中
                buffer = new byte[1024];
                int len = -1;
                while ((len = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }
                buffer = outputStream.toByteArray();
            } else {
                inputStream = Files.newInputStream(Paths.get(imgStr));
                int count = 0;
                while (count == 0) {
                    count = inputStream.available();
                }
                buffer = new byte[count];
                inputStream.read(buffer);
            }
            // 对字节数组Base64编码
            return new String(Base64.getDecoder().decode(buffer));
        }catch (Exception e) {
            log.error("图片转换失败：{}", e.getMessage());
            return "";
        } finally {
            if (inputStream != null) {
                try {
                    // 关闭inputStream流
                    inputStream.close();
                } catch (IOException e) {
                    log.error("InputStream 关闭失败：{}", e.getMessage());
                }
            }
            if (outputStream != null) {
                try {
                    // 关闭outputStream流
                    outputStream.close();
                } catch (IOException e) {
                    log.error("ByteArrayOutputStream 关闭失败：{}", e.getMessage());
                }
            }
        }
    }


    /**
     * URL 编码, Encode默认为UTF-8.
     */
    public static String urlEncode(String part) {
        try {
            return URLEncoder.encode(part, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("编码失败：{}", e.getMessage());
            return "";
        }
    }
}
