package com.ruoyi.web.modules.industryservice.support;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.ByteArrayInputStream;
import java.util.Arrays;
import java.util.Collections;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import com.ruoyi.web.modules.industryservice.domain.BizYakOutboundReport;
import com.ruoyi.web.modules.industryservice.support.YakOutboundReportExcelParser.ParsedRow;

@DisplayName("YakOutboundReportExcelExporter")
class YakOutboundReportExcelExporterTest
{
    private final YakOutboundReportExcelExporter exporter = new YakOutboundReportExcelExporter();

    @Test
    @DisplayName("按年月导出村数据并写合计")
    void exportByYearMonth() throws Exception
    {
        BizYakOutboundReport report = new BizYakOutboundReport();
        report.setTownDeptId(101L);
        report.setTownName("雅安镇");
        report.setVillageDeptId(201L);
        report.setVillageName("雅安镇荣嘎村");
        report.setFarmerHouseholdCount(120);
        report.setFarmerPopulationCount(822);
        report.setYakOutboundCount(5670);
        report.setSelfConsumptionCattleCount(1677);

        byte[] bytes = exporter.export(2026, 7, Collections.singletonList(report), "admin");
        assertNotNull(bytes);
        assertTrue(bytes.length > 1000);

        try (ByteArrayInputStream in = new ByteArrayInputStream(bytes))
        {
            java.util.List<ParsedRow> rows = YakOutboundReportExcelParser.parse(in);
            assertEquals(1, rows.size());
            assertEquals("雅安镇荣嘎村", rows.get(0).getVillageName());
            assertEquals(5670, rows.get(0).getYakOutboundCount());
        }
    }

    @Test
    @DisplayName("合计行对户数按列求和")
    void exportTotalRowSums() throws Exception
    {
        BizYakOutboundReport a = sample("雅安镇", "雅安镇荣嘎村", 120, 5670);
        BizYakOutboundReport b = sample("雅安镇", "雅安镇公随村", 150, 3432);
        byte[] bytes = exporter.export(2026, 7, Arrays.asList(a, b), "admin");
        try (org.apache.poi.ss.usermodel.Workbook wb = org.apache.poi.ss.usermodel.WorkbookFactory.create(
                new ByteArrayInputStream(bytes)))
        {
            org.apache.poi.ss.usermodel.Sheet sheet = YakOutboundReportExcelParser.resolveSheet(wb);
            int header = YakOutboundReportExcelParser.detectHeaderRow(sheet);
            org.apache.poi.ss.usermodel.Row total = sheet.getRow(header + 1 + 2);
            assertEquals("合计", YakOutboundReportExcelParser.cellString(total, 0));
            assertEquals(270, YakOutboundReportExcelParser.cellInteger(total,
                    YakOutboundReportExcelParser.COL_FARMER_HOUSEHOLD).intValue());
            assertEquals(9102, YakOutboundReportExcelParser.cellInteger(total,
                    YakOutboundReportExcelParser.COL_YAK_OUTBOUND).intValue());
        }
    }

    @Test
    @DisplayName("导出填表时间默认为系统当月，且标题统计月与填表月可不同")
    void exportFillerDateDefaultsToCurrentMonth() throws Exception
    {
        java.time.LocalDate today = java.time.LocalDate.now();
        String expectedFill = today.getYear() + "年" + today.getMonthValue() + "月";
        int exportMonth = today.getMonthValue() == 1 ? 12 : today.getMonthValue() - 1;
        int exportYear = today.getMonthValue() == 1 ? today.getYear() - 1 : today.getYear();
        byte[] bytes = exporter.export(exportYear, exportMonth,
                Collections.singletonList(sample("雅安镇", "雅安镇荣嘎村", 10, 100)), "测试用户");
        try (org.apache.poi.ss.usermodel.Workbook wb = org.apache.poi.ss.usermodel.WorkbookFactory.create(
                new ByteArrayInputStream(bytes)))
        {
            org.apache.poi.ss.usermodel.Sheet sheet = YakOutboundReportExcelParser.resolveSheet(wb);
            org.apache.poi.ss.usermodel.Row fillerRow = sheet.getRow(1);
            assertNotNull(fillerRow);
            String fillerText = YakOutboundReportExcelParser.cellString(fillerRow, 0);
            assertNotNull(fillerText);
            assertTrue(fillerText.contains("测试用户"), fillerText);
            assertTrue(fillerText.contains(expectedFill), "填表时间应为当月: " + fillerText);
            assertTrue(!fillerText.contains("X月"), fillerText);
            String title = YakOutboundReportExcelParser.cellString(sheet.getRow(0), 0);
            assertTrue(title.contains(exportYear + "年"), title);
            assertTrue(title.contains("（" + exportMonth + "月）"), title);
        }
    }

    @Test
    @DisplayName("数据行不应继承模板合计行的合并单元格")
    void exportDataRowsHaveNoMergedTownVillage() throws Exception
    {
        java.util.List<BizYakOutboundReport> list = new java.util.ArrayList<>();
        for (int i = 0; i < 4; i++)
        {
            list.add(sample("雅安镇", "测试村" + i, 10 + i, 100 + i));
        }
        byte[] bytes = exporter.export(2026, 5, list, "admin");
        try (org.apache.poi.ss.usermodel.Workbook wb = org.apache.poi.ss.usermodel.WorkbookFactory.create(
                new ByteArrayInputStream(bytes)))
        {
            org.apache.poi.ss.usermodel.Sheet sheet = YakOutboundReportExcelParser.resolveSheet(wb);
            int header = YakOutboundReportExcelParser.detectHeaderRow(sheet);
            int dataStart = header + 1;
            int totalIdx = dataStart + list.size();
            for (int r = dataStart; r < totalIdx; r++)
            {
                org.apache.poi.ss.usermodel.Row row = sheet.getRow(r);
                assertNotNull(row);
                assertEquals("雅安镇", YakOutboundReportExcelParser.cellString(row, YakOutboundReportExcelParser.COL_TOWN));
                assertTrue(YakOutboundReportExcelParser.cellString(row, YakOutboundReportExcelParser.COL_VILLAGE_NAME)
                        .startsWith("测试村"));
                for (int i = 0; i < sheet.getNumMergedRegions(); i++)
                {
                    org.apache.poi.ss.util.CellRangeAddress region = sheet.getMergedRegion(i);
                    assertFalse(region.getFirstRow() <= r && region.getLastRow() >= r
                                    && region.getFirstColumn() <= YakOutboundReportExcelParser.COL_TOWN
                                    && region.getLastColumn() >= YakOutboundReportExcelParser.COL_TOWN,
                            "数据行 " + r + " 不应合并乡镇/村列");
                }
            }
            boolean totalMerged = false;
            for (int i = 0; i < sheet.getNumMergedRegions(); i++)
            {
                org.apache.poi.ss.util.CellRangeAddress region = sheet.getMergedRegion(i);
                if (region.getFirstRow() == totalIdx && region.getLastRow() == totalIdx
                        && region.getFirstColumn() == 0
                        && region.getLastColumn() == YakOutboundReportExcelParser.COL_VILLAGE_NAME)
                {
                    totalMerged = true;
                }
            }
            assertTrue(totalMerged, "仅合计行应合并序号~村三列");
        }
    }

    @Test
    @DisplayName("第3数据行及合计行复用模板数据行边框样式")
    void exportThirdDataRowAndTotalKeepBorders() throws Exception
    {
        java.util.List<BizYakOutboundReport> list = new java.util.ArrayList<>();
        for (int i = 0; i < 3; i++)
        {
            list.add(sample("雅安镇", "测试村" + i, 10 + i, 100 + i));
        }
        byte[] bytes = exporter.export(2026, 6, list, "admin");
        try (org.apache.poi.ss.usermodel.Workbook wb = org.apache.poi.ss.usermodel.WorkbookFactory.create(
                new ByteArrayInputStream(bytes)))
        {
            org.apache.poi.ss.usermodel.Sheet sheet = YakOutboundReportExcelParser.resolveSheet(wb);
            int header = YakOutboundReportExcelParser.detectHeaderRow(sheet);
            int dataStart = header + 1;
            org.apache.poi.ss.usermodel.Row first = sheet.getRow(dataStart);
            org.apache.poi.ss.usermodel.Row third = sheet.getRow(dataStart + 2);
            org.apache.poi.ss.usermodel.Row total = sheet.getRow(dataStart + list.size());
            assertNotNull(first);
            assertNotNull(third);
            assertNotNull(total);
            org.apache.poi.ss.usermodel.BorderStyle expected =
                    first.getCell(0).getCellStyle().getBorderBottom();
            assertNotEquals(org.apache.poi.ss.usermodel.BorderStyle.NONE, expected);
            for (int col = 0; col <= 2; col++)
            {
                assertEquals(expected, third.getCell(col).getCellStyle().getBorderBottom(),
                        "第3数据行列 " + col + " 应有边框");
            }
            for (int col = 0; col <= YakOutboundReportExcelParser.COL_LAST; col++)
            {
                org.apache.poi.ss.usermodel.Cell cell = total.getCell(col);
                assertNotNull(cell, "合计行列 " + col + " 应存在");
                assertNotEquals(org.apache.poi.ss.usermodel.BorderStyle.NONE,
                        cell.getCellStyle().getBorderBottom(),
                        "合计行列 " + col + " 应有下边框");
            }
        }
    }

    private static BizYakOutboundReport sample(String town, String village, int households, int yak)
    {
        BizYakOutboundReport report = new BizYakOutboundReport();
        report.setTownName(town);
        report.setVillageDeptId((long) village.hashCode());
        report.setVillageName(village);
        report.setFarmerHouseholdCount(households);
        report.setYakOutboundCount(yak);
        return report;
    }
}
