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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
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 java.util.concurrent.atomic.AtomicLong;
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.web.modules.industryservice.domain.BizYakOutboundReport;
import com.ruoyi.web.modules.industryservice.domain.vo.YakOutboundReportImportResultVo;
import com.ruoyi.web.modules.industryservice.mapper.BizYakOutboundReportMapper;
import com.ruoyi.web.modules.industryservice.support.TownDeptSupport;
import com.ruoyi.web.modules.industryservice.support.YakOutboundReportExcelExporter;

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

    @Mock
    private TownDeptSupport townDeptSupport;

    @Mock
    private YakOutboundReportExcelExporter yakOutboundReportExcelExporter;

    @InjectMocks
    private BizYakOutboundReportServiceImpl service;

    @Test
    @DisplayName("ZCZX-MYCNCL-UT-013 首次导入全部插入")
    void importInsertAll() throws Exception
    {
        mockTownAndVillage();
        when(mapper.selectByYearMonthAndVillage(anyInt(), anyInt(), anyLong())).thenReturn(null);
        when(mapper.insertBizYakOutboundReport(any())).thenReturn(1);

        try (InputStream in = getClass().getResourceAsStream("/excel/yak_outbound_report_2026.xlsx"))
        {
            MockMultipartFile file = new MockMultipartFile("file", "牦牛出栏.xlsx",
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", in);
            YakOutboundReportImportResultVo result = service.importData(file, 2026, 7, "tester");
            assertEquals(2, result.getInsertCount());
            assertEquals(0, result.getUpdateCount());
            assertEquals(0, result.getFailCount());
            verify(mapper, never()).deleteByYearMonth(any(), any());
            verify(mapper, times(2)).insertBizYakOutboundReport(any());
            verify(mapper, never()).updateBizYakOutboundReport(any());
        }
    }

    @Test
    @DisplayName("已存在村则更新、不删同月其他")
    void importUpsertExisting() throws Exception
    {
        mockTownAndVillage();
        BizYakOutboundReport existing = new BizYakOutboundReport();
        existing.setId(99L);
        when(mapper.selectByYearMonthAndVillage(anyInt(), anyInt(), anyLong())).thenAnswer(inv -> {
            Long villageId = inv.getArgument(2);
            if (villageId != null && villageId == 201L)
            {
                return existing;
            }
            return null;
        });
        when(mapper.insertBizYakOutboundReport(any())).thenReturn(1);
        when(mapper.updateBizYakOutboundReport(any())).thenReturn(1);

        try (InputStream in = getClass().getResourceAsStream("/excel/yak_outbound_report_2026.xlsx"))
        {
            MockMultipartFile file = new MockMultipartFile("file", "牦牛出栏.xlsx",
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", in);
            YakOutboundReportImportResultVo result = service.importData(file, 2026, 7, "tester");
            assertEquals(1, result.getInsertCount());
            assertEquals(1, result.getUpdateCount());
            verify(mapper, never()).deleteByYearMonth(any(), any());
            verify(mapper, times(1)).updateBizYakOutboundReport(any());
            verify(mapper, times(1)).insertBizYakOutboundReport(any());
        }
    }

    private void mockTownAndVillage()
    {
        AtomicLong townSeq = new AtomicLong(100);
        AtomicLong villageSeq = new AtomicLong(200);
        when(townDeptSupport.resolveTownByName(anyString())).thenAnswer(inv -> {
            SysDept d = new SysDept();
            d.setDeptId(townSeq.incrementAndGet());
            d.setDeptName(TownDeptSupport.normalizeTownName(inv.getArgument(0)));
            return d;
        });
        when(townDeptSupport.resolveVillageByTownAndName(anyLong(), anyString())).thenAnswer(inv -> {
            SysDept d = new SysDept();
            d.setDeptId(villageSeq.incrementAndGet());
            d.setDeptName(inv.getArgument(1));
            d.setParentId(inv.getArgument(0));
            return d;
        });
        when(townDeptSupport.requireReportVillage(anyLong())).thenAnswer(inv -> {
            SysDept d = new SysDept();
            d.setDeptId(inv.getArgument(0));
            d.setDeptName("村");
            d.setParentId(101L);
            return d;
        });
        when(townDeptSupport.requireReportTown(anyLong())).thenAnswer(inv -> {
            SysDept d = new SysDept();
            d.setDeptId(inv.getArgument(0));
            d.setDeptName("雅安镇");
            return d;
        });
    }
}
