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.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.when;

import java.math.BigDecimal;
import java.util.Arrays;
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.web.modules.industryservice.domain.dto.BreedingIndustryYakSnapshot;
import com.ruoyi.web.modules.industryservice.mapper.BreedingIndustryStatsMapper;
import com.ruoyi.web.modules.industryservice.support.BreedingIndustryRules;
import com.ruoyi.web.modules.screen.domain.vo.HomeScreenDashboardVo;
import com.ruoyi.web.modules.screen.mapper.HomeScreenStandardMapper;
import com.ruoyi.web.modules.screen.mapper.HomeScreenStatsMapper;

/**
 * DP-SY-UT-010 等编排测试
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("HomeScreenServiceImpl")
class HomeScreenServiceImplTest
{

    @Mock
    private BreedingIndustryStatsMapper breedingIndustryStatsMapper;

    @Mock
    private HomeScreenStatsMapper homeScreenStatsMapper;

    @Mock
    private HomeScreenStandardMapper homeScreenStandardMapper;

    @InjectMocks
    private HomeScreenServiceImpl service;

    @Test
    @DisplayName("DP-SY-UT-010 流通三项与年份无关")
    void ut010_tradeCountsStable()
    {
        stubBreedingEmpty();
        stubOtherBlocks();
        when(homeScreenStatsMapper.countSupplierForScreen()).thenReturn(3);
        when(homeScreenStatsMapper.countDistributorForScreen()).thenReturn(2);
        when(homeScreenStatsMapper.countTradeMarketForScreen()).thenReturn(1);

        HomeScreenDashboardVo y2025 = service.loadDashboard("2025");
        HomeScreenDashboardVo y2026 = service.loadDashboard("2026");

        assertEquals(3, y2025.getIndustryOverview().getSupplierCount());
        assertEquals(3, y2026.getIndustryOverview().getSupplierCount());
        assertEquals(2, y2025.getIndustryOverview().getDistributorCount());
        assertEquals(2, y2026.getIndustryOverview().getDistributorCount());
        assertEquals(1, y2025.getIndustryOverview().getTradeMarketCount());
        assertEquals(1, y2026.getIndustryOverview().getTradeMarketCount());
    }

    @Test
    @DisplayName("DP-SY-API-001 看板结构完整")
    void dashboardStructure()
    {
        stubBreedingWithOneYak();
        stubOtherBlocks();
        HomeScreenDashboardVo vo = service.loadDashboard("2026");
        assertEquals(2026, vo.getStatYear());
        assertNotNull(vo.getStatDate());
        assertNotNull(vo.getIndustryOverview());
        assertNotNull(vo.getInventoryChange());
        assertEquals(3, vo.getAgeStructure().size());
        assertEquals(12, vo.getOutboundMonthly().size());
        assertNotNull(vo.getGrassland());
        assertNotNull(vo.getAppointment());
        assertNotNull(vo.getSubsidy());
        assertNotNull(vo.getAgriClassroom());
        assertNotNull(vo.getTrainingTrend());
    }

    private void stubBreedingEmpty()
    {
        when(breedingIndustryStatsMapper.selectActivePastureIds()).thenReturn(Collections.singletonList(1L));
        when(breedingIndustryStatsMapper.countPastureInScope(anyList())).thenReturn(1);
        when(breedingIndustryStatsMapper.countGrassland()).thenReturn(0);
        when(breedingIndustryStatsMapper.sumGrasslandAreaMu()).thenReturn(BigDecimal.ZERO);
        when(breedingIndustryStatsMapper.selectYakSnapshotsInScope(anyList())).thenReturn(Collections.emptyList());
        when(breedingIndustryStatsMapper.countAnnualOutbound(anyList(), any(), any())).thenReturn(0);
        when(breedingIndustryStatsMapper.countAvailableGrassland()).thenReturn(0);
        when(breedingIndustryStatsMapper.countInUseGrassland(any())).thenReturn(0);
        when(breedingIndustryStatsMapper.selectDegradationGroupCounts()).thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.selectOutboundCountByMonth(anyList(), any(), any()))
                .thenReturn(Collections.emptyList());
    }

    private void stubBreedingWithOneYak()
    {
        when(breedingIndustryStatsMapper.selectActivePastureIds()).thenReturn(Collections.singletonList(1L));
        when(breedingIndustryStatsMapper.countPastureInScope(anyList())).thenReturn(1);
        when(breedingIndustryStatsMapper.countGrassland()).thenReturn(5);
        when(breedingIndustryStatsMapper.sumGrasslandAreaMu()).thenReturn(new BigDecimal("100"));
        BreedingIndustryYakSnapshot yak = new BreedingIndustryYakSnapshot();
        yak.setPastureId(1L);
        yak.setAssetStatus(BreedingIndustryRules.ASSET_STATUS_NORMAL);
        yak.setGender("公");
        yak.setAgeMonths(3);
        when(breedingIndustryStatsMapper.selectYakSnapshotsInScope(anyList()))
                .thenReturn(Collections.singletonList(yak));
        when(breedingIndustryStatsMapper.countAnnualOutbound(anyList(), any(), any())).thenReturn(2);
        when(breedingIndustryStatsMapper.countAvailableGrassland()).thenReturn(3);
        when(breedingIndustryStatsMapper.countInUseGrassland(any())).thenReturn(2);
        when(breedingIndustryStatsMapper.selectDegradationGroupCounts()).thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.selectOutboundCountByMonth(anyList(), any(), any()))
                .thenReturn(Collections.emptyList());
    }

    private void stubOtherBlocks()
    {
        when(homeScreenStatsMapper.countSupplierForScreen()).thenReturn(0);
        when(homeScreenStatsMapper.countDistributorForScreen()).thenReturn(0);
        when(homeScreenStatsMapper.countTradeMarketForScreen()).thenReturn(0);
        when(homeScreenStatsMapper.selectAppointmentAnnualByYear(any(Integer.class)))
                .thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.selectAppointmentMonthlyByYear(any(Integer.class)))
                .thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.sumSubsidyAmountByTypeForYear(any(), any()))
                .thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.countSubsidyGrantInYear(any(), any())).thenReturn(0);
        when(homeScreenStatsMapper.countVideoCoursesPublishedInYear(any(), any())).thenReturn(0);
        when(homeScreenStatsMapper.countTrainingsPublishedInYear(any(), any())).thenReturn(0);
        when(homeScreenStatsMapper.countPublishedTrainingsWithTrainingTimeInYear(any(Integer.class))).thenReturn(0);
        when(homeScreenStatsMapper.selectTrainingTrendByTrainingYear(any(Integer.class)))
                .thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.selectDistinctOutboundYears()).thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.selectDistinctAppointmentYears()).thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.selectDistinctSubsidyYears()).thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.selectDistinctStandardCreateYears()).thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.selectDistinctTechPublishYears()).thenReturn(Collections.emptyList());
        when(homeScreenStatsMapper.selectDistinctTrainingYears()).thenReturn(Collections.emptyList());
    }
}
