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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
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.web.modules.industryservice.domain.BizLivestockProductOutput;
import com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport;
import com.ruoyi.web.modules.industryservice.domain.BizVaccinationData;
import com.ruoyi.web.modules.industryservice.mapper.BizLivestockProductOutputMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizThreeAssetsProblemReportMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizVaccinationDataMapper;
import com.ruoyi.web.modules.screen.domain.dto.HomeScreenStatPeriodDto;
import com.ruoyi.web.modules.screen.domain.dto.LivestockResourceProductOutputSumDto;
import com.ruoyi.web.modules.screen.domain.dto.LivestockResourceTechPersonnelDto;
import com.ruoyi.web.modules.screen.domain.dto.LivestockResourceThreeAssetsSumDto;
import com.ruoyi.web.modules.screen.domain.dto.LivestockResourceVaccinationSumDto;
import com.ruoyi.web.modules.screen.domain.vo.LivestockResourceDashboardVo;
import com.ruoyi.web.modules.screen.domain.vo.LivestockResourceProductOutputListItemVo;
import com.ruoyi.web.modules.screen.domain.vo.LivestockResourceThreeAssetsProblemListItemVo;
import com.ruoyi.web.modules.screen.domain.vo.LivestockResourceVaccinationListItemVo;
import com.ruoyi.web.modules.screen.domain.vo.LivestockResourceVetCountListItemVo;
import com.ruoyi.web.modules.screen.mapper.HomeScreenStatsMapper;
import com.ruoyi.web.modules.screen.mapper.LivestockResourceScreenMapper;

@ExtendWith(MockitoExtension.class)
@DisplayName("LivestockResourceScreenServiceImpl")
class LivestockResourceScreenServiceImplTest
{
    @Mock
    private LivestockResourceScreenMapper livestockResourceScreenMapper;

    @Mock
    private HomeScreenStatsMapper homeScreenStatsMapper;

    @Mock
    private BizThreeAssetsProblemReportMapper bizThreeAssetsProblemReportMapper;

    @Mock
    private BizLivestockProductOutputMapper bizLivestockProductOutputMapper;

    @Mock
    private BizVaccinationDataMapper bizVaccinationDataMapper;

    @InjectMocks
    private LivestockResourceScreenServiceImpl service;

    @Test
    @DisplayName("DP-XM-UT-007 加载看板结构与核心总览 8 项")
    void loadDashboardStructure()
    {
        LivestockResourceThreeAssetsSumDto assets = new LivestockResourceThreeAssetsSumDto();
        assets.setOperatingFixedAssets(new BigDecimal("100.50"));
        assets.setNonOperatingFixedAssets(new BigDecimal("200.25"));
        assets.setFixedAssets(new BigDecimal("300.75"));
        when(livestockResourceScreenMapper.sumRuralThreeAssetsFixed()).thenReturn(assets);

        HomeScreenStatPeriodDto productPeriod = new HomeScreenStatPeriodDto();
        productPeriod.setStatYear(2026);
        productPeriod.setStatMonth(5);
        when(livestockResourceScreenMapper.selectLatestLivestockProductOutputStatPeriodByYear(anyInt()))
                .thenReturn(productPeriod);
        LivestockResourceProductOutputSumDto output = new LivestockResourceProductOutputSumDto();
        output.setMeatOutput(new BigDecimal("1.2"));
        output.setMilkOutput(new BigDecimal("3.4"));
        when(livestockResourceScreenMapper.sumLivestockProductOutputByStatYearMonth(eq(2026), eq(5)))
                .thenReturn(output);
        when(livestockResourceScreenMapper.sumLivestockProductOutputMonthlyUpTo(eq(2026), eq(5)))
                .thenReturn(Collections.emptyList());
        when(livestockResourceScreenMapper.countThreeAssetsProblemByLevel(any(), any()))
                .thenReturn(Collections.emptyList());

        HomeScreenStatPeriodDto vaccPeriod = new HomeScreenStatPeriodDto();
        vaccPeriod.setStatYear(2026);
        vaccPeriod.setStatMonth(6);
        when(livestockResourceScreenMapper.selectLatestVaccinationStatPeriodByYear(anyInt())).thenReturn(vaccPeriod);
        LivestockResourceVaccinationSumDto vacc = new LivestockResourceVaccinationSumDto();
        vacc.setShouldVaccinateCount(200L);
        vacc.setActualVaccinateCount(180L);
        when(livestockResourceScreenMapper.sumVaccinationByStatYearMonth(eq(2026), eq(6))).thenReturn(vacc);

        when(livestockResourceScreenMapper.countVetMedicalResource()).thenReturn(15L);
        when(livestockResourceScreenMapper.countMedicalOrgResource()).thenReturn(7L);
        when(livestockResourceScreenMapper.countTechExpertResource()).thenReturn(9L);
        LivestockResourceTechPersonnelDto tech = new LivestockResourceTechPersonnelDto();
        tech.setEnvoyTotalCount(30L);
        tech.setEnvoyMaleCount(20L);
        tech.setEnvoyFemaleCount(10L);
        tech.setEnvoyPartyMemberCount(12L);
        tech.setAgriTotalCount(40L);
        tech.setAgriClerkCount(5L);
        tech.setAgriJuniorCount(8L);
        tech.setAgriIntermediateCount(10L);
        tech.setAgriAssociateSeniorCount(7L);
        tech.setAgriManagementCount(10L);
        when(livestockResourceScreenMapper.selectTechServicePersonnelTotals()).thenReturn(tech);

        when(homeScreenStatsMapper.selectAppointmentMonthlyByYear(anyInt()))
                .thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.countVideoCoursesPublishedInYear(any(), any())).thenReturn(2);
        when(homeScreenStatsMapper.countTrainingsPublishedInYear(any(), any())).thenReturn(3);
        when(homeScreenStatsMapper.selectTrainingTrendByTrainingYear(anyInt()))
                .thenReturn(Collections.emptyList());
        when(livestockResourceScreenMapper.selectDistinctSessionYears()).thenReturn(Arrays.asList(2026, 2025));

        int currentYear = java.time.LocalDate.now().getYear();
        LivestockResourceDashboardVo vo = service.loadDashboard(String.valueOf(currentYear));
        assertEquals(currentYear, vo.getStatYear());
        assertNotNull(vo.getStatDate());
        assertNotNull(vo.getOverview());
        assertEquals(new BigDecimal("100.50"), vo.getOverview().getOperatingFixedAssets());
        assertEquals(new BigDecimal("1.2000"), vo.getOverview().getMeatOutput());
        assertEquals(new BigDecimal("90.00"), vo.getOverview().getImmunityRate());
        assertEquals(15L, vo.getOverview().getVetCount());
        assertEquals(30L, vo.getOverview().getTechEnvoyCount());
        assertEquals(40L, vo.getOverview().getAgriUnitCount());
        assertNotNull(vo.getRuralThreeAssets());
        assertEquals(new BigDecimal("300.75"), vo.getRuralThreeAssets().getFixedAssets());
        assertNotNull(vo.getProblemReportShare());
        assertNotNull(vo.getProductOutputTrend());
        assertEquals(5, vo.getProductOutputTrend().getMaxMonth());
        assertEquals(5, vo.getProductOutputTrend().getMonthlySeries().size());
        assertNotNull(vo.getVaccinationOverview());
        assertEquals(new BigDecimal("90.00"), vo.getVaccinationOverview().getImmunityRate());
        assertNotNull(vo.getAppointment());
        assertEquals(15, vo.getAppointment().getAnnualVetCount());
        assertEquals(9, vo.getAppointment().getAnnualExpertCount());
        assertEquals(7, vo.getAppointment().getAnnualOrgCount());
        assertNotNull(vo.getTechEnvoyStructure());
        assertEquals(30L, vo.getTechEnvoyStructure().getTotalCount());
        assertNotNull(vo.getAgriUnitStructure());
        assertEquals(5, vo.getAgriUnitStructure().getRankItems().size());
        assertNotNull(vo.getAgriClassroom());
        assertEquals(2, vo.getAgriClassroom().getVideoCourseCount());
        assertNotNull(vo.getTrainingTrend());
    }

    @Test
    @DisplayName("DP-XM-UT-008 历史年无产量/接种填报时对应为 0")
    void historicalYearZeros()
    {
        when(livestockResourceScreenMapper.sumRuralThreeAssetsFixed()).thenReturn(null);
        when(livestockResourceScreenMapper.selectLatestLivestockProductOutputStatPeriodByYear(2020))
                .thenReturn(null);
        when(livestockResourceScreenMapper.selectLatestVaccinationStatPeriodByYear(2020)).thenReturn(null);
        when(livestockResourceScreenMapper.countVetMedicalResource()).thenReturn(null);
        when(livestockResourceScreenMapper.countMedicalOrgResource()).thenReturn(null);
        when(livestockResourceScreenMapper.countTechExpertResource()).thenReturn(null);
        when(livestockResourceScreenMapper.selectTechServicePersonnelTotals()).thenReturn(null);
        when(livestockResourceScreenMapper.countThreeAssetsProblemByLevel(any(), any()))
                .thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.selectAppointmentMonthlyByYear(anyInt()))
                .thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.countVideoCoursesPublishedInYear(any(), any())).thenReturn(0);
        when(homeScreenStatsMapper.countTrainingsPublishedInYear(any(), any())).thenReturn(0);
        when(homeScreenStatsMapper.selectTrainingTrendByTrainingYear(anyInt()))
                .thenReturn(Collections.emptyList());
        when(livestockResourceScreenMapper.selectDistinctSessionYears()).thenReturn(Collections.singletonList(2020));

        LivestockResourceDashboardVo vo = service.loadDashboard("2020");
        assertEquals(new BigDecimal("0.0000"), vo.getOverview().getMeatOutput());
        assertEquals(new BigDecimal("0.00"), vo.getOverview().getImmunityRate());
        assertEquals(0L, vo.getOverview().getVetCount());
        assertEquals(0L, vo.getProblemReportShare().getTotalCount());
        assertEquals(null, vo.getProductOutputTrend().getMaxMonth());
        assertEquals(new BigDecimal("0.00"), vo.getVaccinationOverview().getImmunityRate());
        assertEquals("2020-12-31", vo.getStatDate());
    }

    @Test
    @DisplayName("三资问题上报明细按年过滤并组装字段")
    void listThreeAssetsProblemReports()
    {
        BizThreeAssetsProblemReport row = new BizThreeAssetsProblemReport();
        row.setTownName("巴青镇");
        row.setVillageName("某村");
        row.setProblemLevel("key");
        row.setProblemDetail("道路硬化问题");
        row.setHandleResult("已整改");
        when(bizThreeAssetsProblemReportMapper.selectBizThreeAssetsProblemReportList(any()))
                .thenAnswer(invocation -> {
                    BizThreeAssetsProblemReport q = invocation.getArgument(0);
                    assertNotNull(q.getBeginReportTime());
                    assertNotNull(q.getEndReportTime());
                    return Collections.singletonList(row);
                });

        java.util.List<LivestockResourceThreeAssetsProblemListItemVo> list =
                service.listThreeAssetsProblemReports(2026, 101L, 201L);
        assertEquals(1, list.size());
        assertEquals("巴青镇", list.get(0).getTownName());
        assertEquals("某村", list.get(0).getVillageName());
        assertEquals("key", list.get(0).getProblemLevel());
        assertEquals("重点", list.get(0).getProblemLevelName());
        assertEquals("道路硬化问题", list.get(0).getProblemDetail());
        assertEquals("已整改", list.get(0).getHandleResult());
    }

    @Test
    @DisplayName("三资问题上报明细未传年份不过滤上报时间窗")
    void listThreeAssetsProblemReports_noYearFilter()
    {
        when(bizThreeAssetsProblemReportMapper.selectBizThreeAssetsProblemReportList(any()))
                .thenAnswer(invocation -> {
                    BizThreeAssetsProblemReport q = invocation.getArgument(0);
                    assertNull(q.getBeginReportTime());
                    assertNull(q.getEndReportTime());
                    return Collections.emptyList();
                });
        assertEquals(0, service.listThreeAssetsProblemReports(null, null, null).size());
    }

    @Test
    @DisplayName("DP-XM-UT-009 产量明细分页")
    void listProductOutputs()
    {
        BizLivestockProductOutput row = new BizLivestockProductOutput();
        row.setStatYear(2026);
        row.setStatMonth(7);
        row.setTownName("巴青镇");
        row.setVillageName("某村");
        row.setMeatOutput(new BigDecimal("1.2"));
        row.setMilkOutput(new BigDecimal("3.4"));
        when(bizLivestockProductOutputMapper.selectBizLivestockProductOutputList(any()))
                .thenReturn(Collections.singletonList(row));

        java.util.List<LivestockResourceProductOutputListItemVo> list =
                service.listProductOutputs(2026, 7, 101L, 201L);
        assertEquals(1, list.size());
        assertEquals(2026, list.get(0).getStatYear());
        assertEquals(7, list.get(0).getStatMonth());
        assertEquals("巴青镇", list.get(0).getTownName());
        assertEquals("某村", list.get(0).getVillageName());
        assertEquals(new BigDecimal("1.2000"), list.get(0).getMeatOutput());
        assertEquals(new BigDecimal("3.4000"), list.get(0).getMilkOutput());
    }

    @Test
    @DisplayName("DP-XM-UT-010 疫苗接种明细分页")
    void listVaccinationData()
    {
        BizVaccinationData row = new BizVaccinationData();
        row.setStatYear(2026);
        row.setStatMonth(7);
        row.setTownName("巴青镇");
        row.setVillageName("某村");
        row.setShouldVaccinateCount(100);
        row.setActualVaccinateCount(80);
        row.setImmunityRate(new BigDecimal("80.00"));
        when(bizVaccinationDataMapper.selectBizVaccinationDataList(any()))
                .thenReturn(Collections.singletonList(row));

        java.util.List<LivestockResourceVaccinationListItemVo> list =
                service.listVaccinationData(2026, 7, 101L, 201L);
        assertEquals(1, list.size());
        assertEquals(2026, list.get(0).getStatYear());
        assertEquals(7, list.get(0).getStatMonth());
        assertEquals("巴青镇", list.get(0).getTownName());
        assertEquals("某村", list.get(0).getVillageName());
        assertEquals(100, list.get(0).getShouldVaccinateCount());
        assertEquals(80, list.get(0).getActualVaccinateCount());
        assertEquals(new BigDecimal("80.00"), list.get(0).getImmunityRate());
    }

    @Test
    @DisplayName("DP-XM-UT-011 兽医数量按乡镇汇总")
    void listVetCounts()
    {
        LivestockResourceVetCountListItemVo row = new LivestockResourceVetCountListItemVo();
        row.setTownName("巴青镇");
        row.setVetCount(15L);
        when(livestockResourceScreenMapper.selectVetCountByTown(eq(101L)))
                .thenReturn(Collections.singletonList(row));

        java.util.List<LivestockResourceVetCountListItemVo> list = service.listVetCounts(101L);
        assertEquals(1, list.size());
        assertEquals("巴青镇", list.get(0).getTownName());
        assertEquals(15L, list.get(0).getVetCount());
    }
}
