package com.ruoyi.web.modules.industryservice.service.impl;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.InputStream;
import org.junit.jupiter.api.BeforeEach;
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 org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.mock.web.MockMultipartFile;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.industryservice.domain.BizYakHerdInventory;
import com.ruoyi.web.modules.industryservice.domain.vo.YakHerdInventoryImportResultVo;
import com.ruoyi.web.modules.industryservice.mapper.BizYakHerdInventoryMapper;
import com.ruoyi.web.modules.industryservice.support.TownDeptSupport;
import com.ruoyi.web.modules.industryservice.support.YakHerdInventoryRules;

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
@DisplayName("牦牛存栏导入 upsert")
class BizYakHerdInventoryImportUpsertTest
{
    @Mock
    private BizYakHerdInventoryMapper mapper;

    @Mock
    private TownDeptSupport townDeptSupport;

    @InjectMocks
    private BizYakHerdInventoryServiceImpl service;

    @BeforeEach
    void stubTowns()
    {
        String[] names = {
            "拉西镇", "雅安镇", "杂色镇", "巴青乡", "江绵乡",
            "岗切乡", "本塔乡", "贡日乡", "玛如乡", "阿秀乡"
        };
        String[] villages = {
            "拉西村", "雅安村", "杂色村", "巴青村", "江绵村",
            "岗切村", "本塔村", "贡日村", "玛如村", "阿秀村"
        };
        for (int i = 0; i < names.length; i++)
        {
            SysDept town = new SysDept();
            town.setDeptId(100L + i);
            town.setDeptName(names[i]);
            town.setParentId(YakHerdInventoryRules.TOWN_PARENT_ID);
            town.setOrderNum(13 + i);
            town.setDelFlag("0");
            town.setStatus("0");

            SysDept village = new SysDept();
            village.setDeptId(200L + i);
            village.setDeptName(villages[i]);
            village.setParentId(town.getDeptId());
            village.setOrderNum(1);
            village.setDelFlag("0");
            village.setStatus("0");

            when(townDeptSupport.resolveTownByName(eq(names[i]))).thenReturn(town);
            when(townDeptSupport.resolveVillageByTownAndName(eq(town.getDeptId()), eq(villages[i]))).thenReturn(village);
            when(townDeptSupport.requireReportTown(eq(town.getDeptId()))).thenReturn(town);
            when(townDeptSupport.requireReportVillage(eq(village.getDeptId()))).thenReturn(village);
        }
        when(mapper.selectByYearMonthAndVillage(anyInt(), anyInt(), anyLong())).thenReturn(null);
    }

    @Test
    @DisplayName("首次导入：全部插入")
    void importInsertAll() throws Exception
    {
        when(mapper.insertBizYakHerdInventory(any())).thenReturn(1);
        try (InputStream in = getClass().getResourceAsStream("/excel/yak_herd_inventory_2026.xlsx"))
        {
            MockMultipartFile file = new MockMultipartFile("file", "牦牛存栏数据.xlsx",
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", in);
            YakHerdInventoryImportResultVo result = service.importData(file, 2026, 5, "tester");
            assertEquals(10, result.getInsertCount());
            assertEquals(0, result.getUpdateCount());
            assertEquals(0, result.getFailCount());
            verify(mapper, never()).deleteByYearMonth(anyInt(), anyInt());
            verify(mapper, times(10)).insertBizYakHerdInventory(any());
            verify(mapper, never()).updateBizYakHerdInventory(any());
        }
    }

    @Test
    @DisplayName("重复导入：已存在村更新、不删同月其他")
    void importUpsertExisting() throws Exception
    {
        BizYakHerdInventory existing = new BizYakHerdInventory();
        existing.setId(99L);
        when(mapper.selectByYearMonthAndVillage(eq(2026), eq(5), eq(200L))).thenReturn(existing);
        when(mapper.insertBizYakHerdInventory(any())).thenReturn(1);
        when(mapper.updateBizYakHerdInventory(any())).thenReturn(1);
        try (InputStream in = getClass().getResourceAsStream("/excel/yak_herd_inventory_2026.xlsx"))
        {
            MockMultipartFile file = new MockMultipartFile("file", "牦牛存栏数据.xlsx",
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", in);
            YakHerdInventoryImportResultVo result = service.importData(file, 2026, 5, "tester");
            assertEquals(9, result.getInsertCount());
            assertEquals(1, result.getUpdateCount());
            verify(mapper, never()).deleteByYearMonth(anyInt(), anyInt());
            verify(mapper, times(1)).updateBizYakHerdInventory(any());
            verify(mapper, times(9)).insertBizYakHerdInventory(any());
        }
    }

    @Test
    @DisplayName("存在未识别乡镇时整批失败不落库")
    void importAbortOnUnknownTown() throws Exception
    {
        when(townDeptSupport.resolveTownByName(eq("拉西镇"))).thenReturn(null);
        try (InputStream in = getClass().getResourceAsStream("/excel/yak_herd_inventory_2026.xlsx"))
        {
            MockMultipartFile file = new MockMultipartFile("file", "牦牛存栏数据.xlsx",
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", in);
            assertThrows(ServiceException.class, () -> service.importData(file, 2026, 5, "tester"));
            verify(mapper, never()).deleteByYearMonth(anyInt(), anyInt());
            verify(mapper, never()).insertBizYakHerdInventory(any());
            verify(mapper, never()).updateBizYakHerdInventory(any());
        }
    }
}
