using ClosedXML.Excel;
using Jiaowu.Api.Domain.Academic;
using Jiaowu.Api.Infrastructure.Timetables;

namespace Jiaowu.Api.Tests;

public sealed class TimetableExcelExporterTests
{
    [Fact]
    public void Create_builds_week_grid_with_exam_and_flexible_course_section()
    {
        var timetable = new TimetableData(
            new TimetableTermDto(
                Guid.NewGuid(),
                "2026-2027 学年第一学期",
                "2026-2027",
                TermSeason.Autumn,
                new DateOnly(2026, 9, 1),
                new DateOnly(2027, 1, 15),
                true),
            new TimetableSubjectDto(
                Guid.NewGuid(),
                "CS2601",
                "计算机科学 2601 班",
                TimetableResourceType.Class,
                2026,
                Guid.NewGuid(),
                "计算机科学与技术",
                Guid.NewGuid(),
                "计算机学院",
                null,
                null,
                null),
            null,
            null,
            new TimetablePlanDto(
                Guid.NewGuid(),
                "正式课表",
                "V1",
                SchedulePlanStatus.Published,
                DateTime.UtcNow,
                DateTime.UtcNow),
            [
                new TimetableSlotDto(
                    1,
                    "第一节",
                    new TimeOnly(8, 0),
                    new TimeOnly(8, 45))
            ],
            [
                new TimetableEntryDto(
                    Guid.NewGuid(),
                    Guid.NewGuid(),
                    "TASK-01",
                    "高等数学 01",
                    "MATH101",
                    "高等数学",
                    ["张老师"],
                    ["计算机科学 2601 班"],
                    "101",
                    "第一教学楼",
                    "主校区",
                    1,
                    1,
                    2,
                    1,
                    16,
                    WeekPattern.All,
                    null)
            ],
            [
                new FlexibleCourseDto(
                    Guid.NewGuid(),
                    "TASK-02",
                    "劳动教育",
                    "LAB101",
                    "劳动教育",
                    1,
                    16,
                    1,
                    16,
                    1,
                    ["李老师"],
                    ["计算机科学 2601 班"],
                    null)
            ],
            [
                new TimetableEntryDto(
                    Guid.NewGuid(),
                    Guid.NewGuid(),
                    "TASK-EXAM",
                    "高等数学期末考试",
                    "MATH101",
                    "高等数学",
                    ["张老师", "监考：李老师"],
                    ["计算机科学 2601 班"],
                    "201",
                    "第二教学楼",
                    "主校区",
                    2,
                    1,
                    1,
                    1,
                    1,
                    WeekPattern.All,
                    null,
                    true,
                    "2026-2027 学年第一学期期末考试",
                    new DateOnly(2027, 1, 5),
                    DateTime.UtcNow)
            ])
        {
            ExperimentEntries =
            [
                new TimetableEntryDto(
                    Guid.NewGuid(),
                    Guid.NewGuid(),
                    "TASK-LAB",
                    "程序设计实验教学班",
                    "CSLAB101",
                    "程序设计实验",
                    ["陈老师"],
                    ["计算机科学 2601 班"],
                    "301",
                    "实验中心",
                    "主校区",
                    4,
                    1,
                    2,
                    2,
                    2,
                    WeekPattern.All,
                    null,
                    false,
                    null,
                    null,
                    DateTime.UtcNow,
                    true,
                    Guid.NewGuid(),
                    "LAB-01",
                    "基础控制实验",
                    new DateOnly(2026, 9, 10),
                    ExperimentArrangementMode.SelfScheduled)
            ]
        };

        var bytes = TimetableExcelExporter.Create(timetable);

        using var stream = new MemoryStream(bytes);
        using var workbook = new XLWorkbook(stream);
        var sheet = workbook.Worksheet("课表");
        Assert.Contains("计算机科学 2601 班", sheet.Cell("A1").GetString());
        Assert.Contains("已融入 1 场考试", sheet.Cell("A2").GetString());
        Assert.Contains("已融入 1 场实验", sheet.Cell("A2").GetString());
        Assert.Contains("高等数学", sheet.Cell(5, 2).GetString());
        Assert.Contains("【考试】高等数学", sheet.Cell(5, 3).GetString());
        Assert.Contains("【实验】基础控制实验", sheet.Cell(5, 5).GetString());
        Assert.Contains("自主预约", sheet.Cell(5, 5).GetString());
        Assert.Contains("2027-01-05", sheet.Cell(5, 3).GetString());
        Assert.True(sheet.Row(5).Height > 64,
            "包含多门课程、考试和实验的节次行必须按内容增高，不能截断文字。");
        Assert.Contains(sheet.MergedRanges,
            range => range.RangeAddress.ToString() == "B5:B6");
        Assert.Contains(
            sheet.CellsUsed(),
            cell => cell.GetString().Contains("非排时课程"));

        var batchBytes = TimetableExcelExporter.Create([timetable, timetable]);
        using var batchStream = new MemoryStream(batchBytes);
        using var batchWorkbook = new XLWorkbook(batchStream);
        Assert.Equal(2, batchWorkbook.Worksheets.Count);
        Assert.All(batchWorkbook.Worksheets, worksheet =>
            Assert.Contains("计算机科学 2601 班", worksheet.Cell("A1").GetString()));

        var pdf = TimetablePdfExporter.Create([timetable, timetable]);
        Assert.Equal("%PDF", System.Text.Encoding.ASCII.GetString(pdf, 0, 4));
        Assert.Contains(System.Text.Encoding.ASCII.GetBytes("%%EOF"), pdf);
        Assert.True(pdf.Length > 2_000, "课表 PDF 必须包含完整课程和非排时课程页面。");
    }
}
