package com.ningdatech.pmapi.common.util;

import cn.hutool.core.io.IoUtil;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.pmapi.common.model.FreemarkerBatchExportDTO;
import com.ningdatech.pmapi.meeting.entity.dto.ExpertFeeExportDTO;
import com.ningdatech.pmapi.meeting.entity.dto.ExpertInfoDTO;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.springframework.core.io.ByteArrayResource;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 * FreemarkerWordUtil
 * </p>
 *
 * @author WendyYang
 * @since 2023/7/24
 **/
@Slf4j
public class FreemarkerWordUtil {

    private static void setDownFileName(HttpServletResponse response, String fileName) {
        String fileNameEncoded;
        try {
            fileNameEncoded = URLEncoder.encode(fileName, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("文件名编码异常");
        }
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEncoded);
    }

    private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_31);

    static {
        CONFIGURATION.setDefaultEncoding("UTF-8");
        CONFIGURATION.setClassForTemplateLoading(FreemarkerWordUtil.class, "/template");
    }

    /**
     * 生成word文件
     *
     * @param dataMap      word中需要展示的动态数据，用map集合来保存
     * @param templateName word模板名称，例如：test.ftl
     * @param filePath     文件生成的目标路径，例如：D:/wordFile/
     * @param fileName     生成的文件名称，例如：test.doc
     */
    public static void create(Object dataMap, String templateName, String filePath, String fileName) {
        try {
            Template template = CONFIGURATION.getTemplate(templateName);
            //输出文件
            File outFile = new File(filePath + File.separator + fileName);
            //如果输出目标文件夹不存在，则创建
            if (!outFile.getParentFile().exists()) {
                boolean ignore = outFile.getParentFile().mkdirs();
            }
            //将模板和数据模型合并生成文件
            Writer out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(outFile.toPath()), StandardCharsets.UTF_8));
            //生成文件
            template.process(dataMap, out);
            IoUtil.flush(out);
            IoUtil.close(out);
        } catch (Exception e) {
            log.error("根据模版生成Word文件失败：", e);
            throw BizException.wrap("根据模版生成Word文件失败");
        }
    }

    public static void export(String fileName, Object data, HttpServletResponse response, String templateName) throws TemplateException, IOException {
        Template template = CONFIGURATION.getTemplate(templateName);
        response.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
        response.setContentType(ContentType.APPLICATION_JSON.getMimeType());
        setDownFileName(response, fileName);
        try (StringWriter out = new StringWriter();
             Writer writer = new BufferedWriter(out, 4096)) {
            template.process(data, writer);
            try (InputStream is = new ByteArrayResource(out.toString().getBytes(StandardCharsets.UTF_8)).getInputStream();
                 ServletOutputStream outputStream = response.getOutputStream()) {
                // 缓冲区
                byte[] buffer = new byte[1024];
                int bytesToRead;
                // 通过循环将读入的Word文件的内容输出到浏览器中
                while ((bytesToRead = is.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesToRead);
                }
            }
        }


    }

    public static void exportBatch(HttpServletResponse response, List<FreemarkerBatchExportDTO> fbeList, String fileName) throws IOException, TemplateException {
        response.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
        response.setContentType("application/zip");
        setDownFileName(response, fileName);
        try (ServletOutputStream os = response.getOutputStream();
             ZipOutputStream zos = new ZipOutputStream(os)) {
            for (FreemarkerBatchExportDTO param : fbeList) {
                Template template = CONFIGURATION.getTemplate(param.getTemplate());
                StringWriter out = new StringWriter();
                try (Writer writer = new BufferedWriter(out, 4096)) {
                    template.process(param.getData(), writer);
                }
                ZipEntry zipEntry = new ZipEntry(param.getFileName());
                zos.putNextEntry(zipEntry);
                zos.write(out.toString().getBytes(StandardCharsets.UTF_8));
                zos.closeEntry();
            }
        } finally {
            response.flushBuffer();
        }
    }

    public static void main(String[] args) {
        ExpertFeeExportDTO dto = new ExpertFeeExportDTO();
        dto.setMeetingAddress("杭州市滨江区海创还能到我当时防守打法十大发放");
        dto.setMeetingTime("2023-01-01 12:20");
        dto.setProjectName("阿萨法舒服舒服舒服舒服送达方");
        dto.setExperts(new ArrayList<>());
        for (int i = 0; i < 10; i++) {
            ExpertInfoDTO expert = new ExpertInfoDTO();
            expert.setNo(i);
            expert.setBank("中国建设银行");
            expert.setMobile("17819392616");
            expert.setBankNo("6111111172121324354");
            expert.setCompany("宁达科技有限公司");
            expert.setFee(BigDecimal.valueOf(500));
            expert.setName("张三丰");
            expert.setSex("男");
            expert.setIdcard("1212121211212121");
            dto.getExperts().add(expert);
        }
        create(dto, "meeting/专家费.ftl", "/Users/wendy/Desktop/", "专家费.doc");
    }


}
