package com.hotwj.platform.securityManagement.trainingOutline.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.hotwj.platform.common.utils.PdfWatermarkUtil;
import com.hotwj.platform.reportStatistics.integration.GotenbergClient;
import com.hotwj.platform.reportStatistics.template.VelocityTemplateRenderer;
import com.hotwj.platform.securityManagement.trainingOutline.domain.bo.HotTrainingOutlineBo;
import com.hotwj.platform.securityManagement.trainingOutline.domain.vo.HotTrainingOutlineVo;
import com.hotwj.platform.securityManagement.trainingOutline.service.IHotTrainingOutlinePrintService;
import com.hotwj.platform.securityManagement.trainingOutline.service.IHotTrainingOutlineService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.VelocityContext;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.file.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Service
@RequiredArgsConstructor
public class HotTrainingOutlinePrintServiceImpl implements IHotTrainingOutlinePrintService {

    private static final long LEVEL_ANNUAL = 1L;
    private static final long LEVEL_MONTHLY = 2L;

    private final IHotTrainingOutlineService trainingOutlineService;
    private final VelocityTemplateRenderer velocityTemplateRenderer;
    private final GotenbergClient gotenbergClient;

    @Value("${dromara.app.name:HOT交通安全管理清单平台}")
    private String appName;

    @Override
    public void exportPdf(HotTrainingOutlineBo bo, HttpServletResponse response) {
        List<HotTrainingOutlineVo> outlineList = resolveAnnualOutlines(bo);
        if (CollUtil.isEmpty(outlineList)) {
            throw new ServiceException("未查询到培训大纲数据");
        }

        List<Map<String, Object>> printDataList = new ArrayList<>();
        for (HotTrainingOutlineVo outline : outlineList) {
            Map<String, Object> outlineData = new HashMap<>();
            outlineData.put("outlineYear", outline.getOutlineName());
            List<Map<String, Object>> flatRows = new ArrayList<>();
            List<HotTrainingOutlineVo> monthVos = trainingOutlineService.queryChildrenByParentId(outline.getId());
            if (CollUtil.isNotEmpty(monthVos)) {
                for (HotTrainingOutlineVo month : monthVos) {
                    List<HotTrainingOutlineVo> weekVos = trainingOutlineService.queryChildrenByParentId(month.getId());
                    if (CollUtil.isNotEmpty(weekVos)) {
                        for (int i = 0; i < weekVos.size(); i++) {
                            HotTrainingOutlineVo week = weekVos.get(i);
                            Map<String, Object> row = new HashMap<>();
                            row.put("planMonth", month.getOutlineName());
                            row.put("topic", defaultString(month.getTrainingTypeLabel(), month.getTrainingType()));
                            row.put("courseName", week.getOutlineName());
                            row.put("durationMinute", "");
                            row.put("courseDesc", week.getOutlineFile());
                            row.put("monthRowSpan", i == 0 ? weekVos.size() : 0);
                            flatRows.add(row);
                        }
                    } else {
                        Map<String, Object> row = new HashMap<>();
                        row.put("planMonth", month.getOutlineName());
                        row.put("topic", defaultString(month.getTrainingTypeLabel(), month.getTrainingType()));
                        row.put("courseName", "");
                        row.put("durationMinute", "");
                        row.put("courseDesc", month.getOutlineFile());
                        row.put("monthRowSpan", 1);
                        flatRows.add(row);
                    }
                }
            }
            outlineData.put("rows", flatRows);
            printDataList.add(outlineData);
        }

        VelocityContext context = new VelocityContext();
        context.put("printTime", DateUtil.now());
        context.put("list", printDataList);
        context.put("appName", appName);

        String bodyHtml = velocityTemplateRenderer.render("templates/securityManage/trainingOutline.html.vm", context);

        VelocityContext layoutContext = new VelocityContext();
        layoutContext.put("title", "年度培训计划大纲");
        List<String> bodies = new ArrayList<>();
        bodies.add(bodyHtml);
        layoutContext.put("bodies", bodies);

        String finalHtml = velocityTemplateRenderer.render("templates/layout/printLayout.html.vm", layoutContext);

        try {
            byte[] pdfBytes = convertAndWatermark(finalHtml);
            response.setContentType("application/pdf");
            String fileName = "年度培训计划大纲.pdf";
            FileUtils.setAttachmentResponseHeader(response, fileName);
            response.getOutputStream().write(pdfBytes);
        } catch (Exception e) {
            log.error("Export PDF failed", e);
            throw new ServiceException("导出PDF失败");
        }
    }

    private byte[] convertAndWatermark(String htmlContent) throws Exception {
        File temp = Files.createTempFile("training-outline-print-", ".html").toFile();
        try {
            try (FileWriter fw = new FileWriter(temp, StandardCharsets.UTF_8)) {
                fw.write(htmlContent);
            }
            String footer = """
                    <div style="font-size:10px;color:#000;width:100%;padding:0 1cm;">
                        <span style="float:left;color:#888;">平台信息依实为准，信息使用自判</span>
                        <span style="float:right;">第 <span class='pageNumber'></span> / <span class='totalPages'></span> 页</span>
                    </div>
                    """;
            byte[] pdf = gotenbergClient.convertHtmlToPdf(temp, footer);
            return PdfWatermarkUtil.addWatermark(pdf, appName);
        } finally {
            if (temp.exists()) {
                if (!temp.delete()) {
                    log.warn("Failed to delete temp file: {}", temp.getAbsolutePath());
                }
            }
        }
    }

    private List<HotTrainingOutlineVo> resolveAnnualOutlines(HotTrainingOutlineBo bo) {
        if (bo != null && bo.getId() != null) {
            HotTrainingOutlineVo current = trainingOutlineService.queryById(bo.getId());
            if (current == null) {
                throw new ServiceException("培训大纲不存在");
            }
            HotTrainingOutlineVo annual = resolveAnnualOutline(current);
            return annual == null ? List.of() : List.of(annual);
        }
        HotTrainingOutlineBo queryBo = bo == null ? new HotTrainingOutlineBo() : bo;
        queryBo.setOutlineLevel(LEVEL_ANNUAL);
        return trainingOutlineService.queryAnnualList(queryBo);
    }

    private HotTrainingOutlineVo resolveAnnualOutline(HotTrainingOutlineVo current) {
        if (current == null) {
            return null;
        }
        if (Objects.equals(current.getOutlineLevel(), LEVEL_ANNUAL)) {
            return current;
        }
        if (Objects.equals(current.getOutlineLevel(), LEVEL_MONTHLY)) {
            return trainingOutlineService.queryById(current.getParentId());
        }
        HotTrainingOutlineVo parent = trainingOutlineService.queryById(current.getParentId());
        if (parent == null) {
            return null;
        }
        return trainingOutlineService.queryById(parent.getParentId());
    }

    private String defaultString(String preferred, String fallback) {
        return preferred != null && !preferred.isBlank() ? preferred : (fallback == null ? "" : fallback);
    }
}
