package cn.yunzhixue.ability.center.examsprint.application.report;

import cn.yunzhixue.ability.center.examsprint.contracts.report.AchievementExamSprintReportPayload;
import cn.yunzhixue.ability.center.examsprint.domain.report.AchievementReportContent;
import cn.yunzhixue.ability.center.examsprint.domain.report.ReportType;
import cn.yunzhixue.ability.center.examsprint.domain.report.UnmodeledReportContent;
import cn.yunzhixue.ability.center.examsprint.infrastructure.report.pdf.PlaywrightExamSprintReportPdfGenerator;
import cn.yunzhixue.ability.center.examsprint.infrastructure.report.rendering.achievement.ClasspathAchievementExamSprintReportRenderer;
import cn.yunzhixue.ability.center.examsprint.infrastructure.report.rendering.outlook.ClasspathOutlookExamSprintReportRenderer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.Instant;

import static org.assertj.core.api.Assertions.assertThat;

class ExamSprintReportWarmupResourceIntegrationTest {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private static final Instant GENERATED_AT = Instant.parse("2026-05-07T08:00:00Z");

    /** 覆盖运行时 warmup JSON 资源场景，当使用真实渲染器和 PDF 生成器时，两个报告都应产出非空 HTML 与 PDF。 */
    @Test
    void warmupResourcesRenderHtmlAndGeneratePdfForBothReports() throws Exception {
        try (PlaywrightExamSprintReportPdfGenerator pdfGenerator = new PlaywrightExamSprintReportPdfGenerator()) {

            JsonNode outlookPayload = readResource(ExamSprintReportWarmupRunner.OUTLOOK_WARMUP_RESOURCE);
            ClasspathOutlookExamSprintReportRenderer outlookRenderer = new ClasspathOutlookExamSprintReportRenderer(OBJECT_MAPPER);
            String outlookHtml = outlookRenderer.render(
                    new UnmodeledReportContent(ReportType.OUTLOOK, outlookPayload),
                    GENERATED_AT);
            byte[] outlookPdf = pdfGenerator.generate(outlookHtml);

            assertThat(outlookPayload.path("StudentName").asText()).isEqualTo("20260318测试");
            assertThat(outlookHtml)
                    .contains("高考英语临考词汇突击潜力展望报告")
                    .contains("模块一：个人学情分析")
                    .contains("模块二：科学备考建议");
            assertPdfBytes(outlookPdf);

            JsonNode achievementPayload = readResource(ExamSprintReportWarmupRunner.ACHIEVEMENT_WARMUP_RESOURCE);
            AchievementExamSprintReportPayload reportPayload = OBJECT_MAPPER.treeToValue(
                    achievementPayload,
                    AchievementExamSprintReportPayload.class);
            AchievementReportContent achievementContent = AchievementReportContentMapper.toDomainContent(reportPayload);
            ClasspathAchievementExamSprintReportRenderer achievementRenderer = new ClasspathAchievementExamSprintReportRenderer();
            String achievementHtml = achievementRenderer.render(achievementContent, GENERATED_AT);
            byte[] achievementPdf = pdfGenerator.generate(achievementHtml);

            assertThat(achievementContent.studentName()).isEqualTo("20260318测试");
            assertThat(achievementContent.reportTitle()).isEqualTo("初中英语临考突击学习成果报告");
            assertThat(achievementHtml)
                    .contains("初中英语临考突击学习成果报告")
                    .contains("模块一：词汇量对比")
                    .contains("模块二：试卷熟词量对比")
                    .contains("模块三：实考生词命中状况");
            assertPdfBytes(achievementPdf);
        }
    }

    private JsonNode readResource(String resourcePath) throws Exception {
        try (InputStream inputStream = new ClassPathResource(resourcePath).getInputStream()) {
            return OBJECT_MAPPER.readTree(inputStream);
        }
    }

    private void assertPdfBytes(byte[] pdfBytes) {
        assertThat(pdfBytes).isNotEmpty();
        assertThat(new String(pdfBytes, 0, 4, StandardCharsets.ISO_8859_1)).isEqualTo("%PDF");
    }
}
