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.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

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 com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.industryservice.domain.BizYakOutboundReport;
import com.ruoyi.web.modules.industryservice.mapper.BizYakOutboundReportMapper;
import com.ruoyi.web.modules.industryservice.support.TownDeptSupport;
import com.ruoyi.web.modules.industryservice.support.YakHerdInventoryYearSupport;

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
@DisplayName("BizYakOutboundReportServiceImpl")
class BizYakOutboundReportServiceImplTest
{
    @Mock
    private BizYakOutboundReportMapper mapper;

    @Mock
    private TownDeptSupport townDeptSupport;

    @InjectMocks
    private BizYakOutboundReportServiceImpl service;

    @Test
    @DisplayName("ZCZX-MYCNCL-UT-003 缺村")
    void ut003_missingVillage()
    {
        BizYakOutboundReport row = sampleRow();
        row.setVillageDeptId(null);
        assertThrows(ServiceException.class, () -> service.insertBizYakOutboundReport(row));
    }

    @Test
    @DisplayName("ZCZX-MYCNCL-UT-004 负数拒绝")
    void ut004_negative()
    {
        BizYakOutboundReport row = sampleRow();
        row.setYakOutboundCount(-1);
        mockVillage();
        assertThrows(ServiceException.class, () -> service.insertBizYakOutboundReport(row));
    }

    @Test
    @DisplayName("ZCZX-MYCNCL-UT-005 同年同村重复")
    void ut005_duplicate()
    {
        mockVillage();
        when(mapper.countByYearMonthAndVillageExcludeId(2026, 5, 201L, null)).thenReturn(1);
        assertThrows(ServiceException.class, () -> service.insertBizYakOutboundReport(sampleRow()));
        verify(mapper, never()).insertBizYakOutboundReport(any());
    }

    @Test
    @DisplayName("ZCZX-MYCNCL-UT-006 新增成功")
    void ut006_insertSuccess()
    {
        mockVillage();
        when(mapper.countByYearMonthAndVillageExcludeId(2026, 5, 201L, null)).thenReturn(0);
        when(mapper.insertBizYakOutboundReport(any())).thenReturn(1);
        assertEquals(1, service.insertBizYakOutboundReport(sampleRow()));
    }

    @Test
    @DisplayName("ZCZX-MYCNCL-UT-015 修改不存在")
    void ut015_updateMissing()
    {
        when(mapper.selectBizYakOutboundReportById(99L)).thenReturn(null);
        BizYakOutboundReport row = sampleRow();
        row.setId(99L);
        mockVillage();
        assertThrows(ServiceException.class, () -> service.updateBizYakOutboundReport(row));
    }

    @Test
    @DisplayName("ZCZX-MYCNCL-UT-016 物理删除")
    void ut016_delete()
    {
        when(mapper.deleteBizYakOutboundReportByIds(any())).thenReturn(1);
        assertEquals(1, service.deleteBizYakOutboundReportByIds(new Long[] { 1L }, "tester"));
        verify(mapper).deleteBizYakOutboundReportByIds(any());
    }

    @Test
    @DisplayName("ZCZX-MYCNCL-UT-001 年份选项 6 个")
    void ut001_yearOptions()
    {
        assertEquals(6, YakHerdInventoryYearSupport.resolveYearOptions(2026).size());
    }

    private void mockVillage()
    {
        SysDept village = new SysDept();
        village.setDeptId(201L);
        village.setDeptName("荣嘎村");
        village.setParentId(101L);
        when(townDeptSupport.requireReportVillage(201L)).thenReturn(village);
        SysDept town = new SysDept();
        town.setDeptId(101L);
        town.setDeptName("雅安镇");
        when(townDeptSupport.requireReportTown(101L)).thenReturn(town);
    }

    private static BizYakOutboundReport sampleRow()
    {
        BizYakOutboundReport row = new BizYakOutboundReport();
        row.setStatYear(2026);
        row.setStatMonth(5);
        row.setVillageDeptId(201L);
        row.setYakOutboundCount(100);
        return row;
    }
}
