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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;

import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.web.modules.industryservice.domain.BizYakHerdInventory;
import com.ruoyi.web.modules.industryservice.support.YakHerdInventoryExcelParser.ParsedRow;

@ExtendWith(MockitoExtension.class)
@DisplayName("YakHerdInventoryValidation")
class YakHerdInventoryValidationTest
{
    @Mock
    private ISysDeptService deptService;

    @InjectMocks
    private TownDeptSupport townDeptSupport;

    @Test
    @DisplayName("所属村上级不是填报乡镇时拒绝")
    void villageParentNotReportTown()
    {
        SysDept town = town(101L, "巴青乡", 13);
        when(deptService.selectDeptList(org.mockito.ArgumentMatchers.any())).thenReturn(Collections.singletonList(town));
        SysDept village = town(201L, "某村", 1);
        village.setParentId(999L);
        when(deptService.selectDeptById(201L)).thenReturn(village);

        BizYakHerdInventory row = new BizYakHerdInventory();
        row.setStatYear(2026);
        row.setStatMonth(5);
        row.setVillageDeptId(201L);
        assertThrows(ServiceException.class, () -> YakHerdInventoryValidation.validateRowForSave(row, townDeptSupport));
    }

    @Test
    @DisplayName("保存时按村反填乡镇")
    void fillTownFromVillage()
    {
        SysDept town = town(101L, "巴青乡", 13);
        when(deptService.selectDeptList(org.mockito.ArgumentMatchers.any())).thenReturn(Collections.singletonList(town));
        SysDept village = town(201L, "某村", 1);
        village.setParentId(101L);
        when(deptService.selectDeptById(201L)).thenReturn(village);

        BizYakHerdInventory row = new BizYakHerdInventory();
        row.setStatYear(2026);
        row.setStatMonth(5);
        row.setVillageDeptId(201L);
        row.setBreedingBullCount(1);
        YakHerdInventoryValidation.validateRowForSave(row, townDeptSupport);
        assertEquals(101L, row.getTownDeptId());
        assertEquals("巴青乡", row.getTownName());
        assertEquals("某村", row.getVillageName());
        assertEquals(1, row.getBullTotal());
    }

    @Test
    @DisplayName("产奶羊存栏数须小于羊总存栏数")
    void milkingSheepLessThanSheepTotal()
    {
        BizYakHerdInventory row = new BizYakHerdInventory();
        row.setSheepTotal(10);
        row.setMilkingSheepCount(10);
        assertThrows(ServiceException.class,
                () -> YakHerdInventoryValidation.validateMilkingSheepLessThanSheepTotal(row));

        row.setMilkingSheepCount(11);
        assertThrows(ServiceException.class,
                () -> YakHerdInventoryValidation.validateMilkingSheepLessThanSheepTotal(row));

        row.setMilkingSheepCount(9);
        YakHerdInventoryValidation.validateMilkingSheepLessThanSheepTotal(row);

        row.setMilkingSheepCount(null);
        YakHerdInventoryValidation.validateMilkingSheepLessThanSheepTotal(row);
    }

    @Test
    @DisplayName("派生合计计算")
    void recalculateDerived()
    {
        BizYakHerdInventory row = new BizYakHerdInventory();
        row.setBreedingBullCount(10);
        row.setBullCastratedCount(20);
        row.setCowYoungCount(5);
        row.setCowAdultCount(15);
        row.setMilkingCowCount(3);
        row.setFertileCowCount(7);
        row.setSheepTotal(40);
        row.setInsuredYakCount(2);
        YakHerdInventoryValidation.recalculateDerived(row);
        assertEquals(30, row.getBullTotal());
        assertEquals(20, row.getCowTotal());
        assertEquals(10, row.getDairyTotal());
        assertEquals(52, row.getYakTotal());
        assertEquals(102, row.getGrandTotal());
        assertEquals(92, row.getYakSheepTotal());
    }

    @Test
    @DisplayName("Excel 合计不一致警告")
    void excelTotalWarn()
    {
        ParsedRow parsed = new ParsedRow();
        parsed.setExcelBullTotal(99);
        BizYakHerdInventory row = new BizYakHerdInventory();
        row.setBreedingBullCount(10);
        row.setBullCastratedCount(20);
        YakHerdInventoryValidation.recalculateDerived(row);
        List<String> warns = YakHerdInventoryValidation.buildExcelTotalWarns(parsed, row);
        assertTrue(warns.stream().anyMatch(w -> w.contains("公牛合计")));
    }

    private static SysDept town(Long id, String name, int orderNum)
    {
        SysDept dept = new SysDept();
        dept.setDeptId(id);
        dept.setDeptName(name);
        dept.setParentId(YakHerdInventoryRules.TOWN_PARENT_ID);
        dept.setOrderNum(orderNum);
        dept.setDelFlag("0");
        dept.setStatus("0");
        return dept;
    }
}
