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.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import com.ruoyi.web.modules.industryservice.domain.BizLivestockProductOutput;
import com.ruoyi.web.modules.industryservice.support.LivestockProductOutputExcelParser.ParsedRow;

@DisplayName("LivestockProductOutput Excel")
class LivestockProductOutputExcelTest
{
    private final LivestockProductOutputExcelExporter exporter = new LivestockProductOutputExcelExporter();

    @Test
    @DisplayName("解析样例跳过空行")
    void parseSample() throws Exception
    {
        try (InputStream in = getClass().getResourceAsStream("/excel/livestock_product_output_sample.xlsx"))
        {
            List<ParsedRow> rows = LivestockProductOutputExcelParser.parse(in);
            assertEquals(2, rows.size());
            assertEquals("雅安镇", rows.get(0).getTownName());
            assertEquals("雅安镇荣嘎村", rows.get(0).getVillageName());
            assertEquals(0, new BigDecimal("1.25").compareTo(rows.get(0).getMeatOutput()));
            assertEquals(0, new BigDecimal("3.5").compareTo(rows.get(0).getMilkOutput()));
        }
    }

    @Test
    @DisplayName("导出含合计行并对肉奶求和")
    void exportHasTotalRow() throws Exception
    {
        BizLivestockProductOutput a = sample("雅安镇", "雅安镇荣嘎村", "1.25", "3.50");
        BizLivestockProductOutput b = sample("雅安镇", "雅安镇公随村", "0.80", "2.10");
        byte[] bytes = exporter.export(2026, 7, Arrays.asList(a, b), "admin");
        assertNotNull(bytes);
        try (Workbook wb = WorkbookFactory.create(new ByteArrayInputStream(bytes)))
        {
            Sheet sheet = LivestockProductOutputExcelParser.resolveSheet(wb);
            int header = LivestockProductOutputExcelParser.detectHeaderRow(sheet);
            int dataStart = header + 1;
            Row total = sheet.getRow(dataStart + 2);
            assertNotNull(total);
            assertEquals("合计", LivestockProductOutputExcelParser.cellString(total, 0));
            assertEquals(0, new BigDecimal("2.05").compareTo(
                    LivestockProductOutputExcelParser.cellDecimal(total, LivestockProductOutputExcelParser.COL_MEAT)));
            assertEquals(0, new BigDecimal("5.60").compareTo(
                    LivestockProductOutputExcelParser.cellDecimal(total, LivestockProductOutputExcelParser.COL_MILK)));
            assertTrue(sheet.getLastRowNum() == dataStart + 2);
        }
    }

    @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, Arrays.asList(sample("雅安镇", "雅安镇荣嘎村", "1", "2")),
                "测试用户");
        try (Workbook wb = WorkbookFactory.create(new ByteArrayInputStream(bytes)))
        {
            Sheet sheet = LivestockProductOutputExcelParser.resolveSheet(wb);
            Row fillerRow = sheet.getRow(1);
            assertNotNull(fillerRow);
            String fillerText = LivestockProductOutputExcelParser.cellString(fillerRow, 0);
            assertNotNull(fillerText);
            assertTrue(fillerText.contains("测试用户"), fillerText);
            assertTrue(fillerText.contains(expectedFill), "填表时间应为当月: " + fillerText);
            assertTrue(!fillerText.contains("X月"), fillerText);
            Row titleRow = sheet.getRow(0);
            String title = LivestockProductOutputExcelParser.cellString(titleRow, 0);
            assertTrue(title.contains(exportYear + "年"), title);
            assertTrue(title.contains("（" + exportMonth + "月）"), title);
        }
    }

    @Test
    @DisplayName("数据行不应继承模板合计行的合并单元格")
    void exportDataRowsHaveNoMergedTownVillage() throws Exception
    {
        java.util.List<BizLivestockProductOutput> list = new java.util.ArrayList<>();
        for (int i = 0; i < 4; i++)
        {
            list.add(sample("雅安镇", "测试村" + i, "1.0", "2.0"));
        }
        byte[] bytes = exporter.export(2026, 5, list, "admin");
        try (Workbook wb = WorkbookFactory.create(new ByteArrayInputStream(bytes)))
        {
            Sheet sheet = LivestockProductOutputExcelParser.resolveSheet(wb);
            int header = LivestockProductOutputExcelParser.detectHeaderRow(sheet);
            int dataStart = header + 1;
            int totalIdx = dataStart + list.size();
            for (int r = dataStart; r < totalIdx; r++)
            {
                Row row = sheet.getRow(r);
                assertNotNull(row);
                assertEquals("雅安镇", LivestockProductOutputExcelParser.cellString(row, LivestockProductOutputExcelParser.COL_TOWN));
                assertTrue(LivestockProductOutputExcelParser.cellString(row, LivestockProductOutputExcelParser.COL_VILLAGE)
                        .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() <= LivestockProductOutputExcelParser.COL_TOWN
                                    && region.getLastColumn() >= LivestockProductOutputExcelParser.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() == LivestockProductOutputExcelParser.COL_VILLAGE)
                {
                    totalMerged = true;
                }
            }
            assertTrue(totalMerged, "仅合计行应合并序号~村三列");
        }
    }

    private static BizLivestockProductOutput sample(String town, String village, String meat, String milk)
    {
        BizLivestockProductOutput row = new BizLivestockProductOutput();
        row.setTownName(town);
        row.setVillageDeptId((long) village.hashCode());
        row.setVillageName(village);
        row.setMeatOutput(new BigDecimal(meat));
        row.setMilkOutput(new BigDecimal(milk));
        return row;
    }
}
