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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
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.prosperity.domain.BizCommonProsperityAchievement;
import com.ruoyi.web.modules.prosperity.domain.BizCommonProsperityProject;
import com.ruoyi.web.modules.prosperity.mapper.BizCommonProsperityAchievementMapper;
import com.ruoyi.web.modules.prosperity.mapper.BizCommonProsperityProjectMapper;
import com.ruoyi.web.modules.prosperity.mapper.BizCommonProsperityProjectOpImageMapper;
import com.ruoyi.web.modules.screen.domain.vo.CommonProsperityProjectTypeDetailVo;
import com.ruoyi.web.modules.screen.domain.vo.CommonProsperityScreenDashboardVo;

/**
 * DP-GTFY-UT-014、015
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("CommonProsperityScreenServiceImpl")
class CommonProsperityScreenServiceImplTest
{

    @Mock
    private BizCommonProsperityAchievementMapper achievementMapper;

    @Mock
    private BizCommonProsperityProjectMapper projectMapper;

    @Mock
    private BizCommonProsperityProjectOpImageMapper opImageMapper;

    @InjectMocks
    private CommonProsperityScreenServiceImpl service;

    @Test
    @DisplayName("DP-GTFY-UT-014 仅项目无成果")
    void ut014_projectsOnly()
    {
        when(achievementMapper.selectByStatYear("2026")).thenReturn(Collections.emptyList());
        BizCommonProsperityProject p = new BizCommonProsperityProject();
        p.setId(1L);
        p.setProjectType(1);
        p.setPublishStatus(1);
        when(projectMapper.selectPublishedForScreen(2026)).thenReturn(Collections.singletonList(p));
        when(achievementMapper.selectDistinctStatYears()).thenReturn(Collections.emptyList());
        when(projectMapper.selectDistinctStatYearsFromPublished()).thenReturn(Collections.singletonList("2026"));

        CommonProsperityScreenDashboardVo vo = service.loadDashboard("2026");
        assertFalse(vo.getAchievement().getHasData());
        assertNull(vo.getAchievement().getSummary());
        assertTrue(vo.getHasProjectData());
        assertEquals(3, vo.getProjectTypeStats().size());
    }

    @Test
    @DisplayName("DP-GTFY-UT-015 仅成果无项目")
    void ut015_achievementOnly()
    {
        when(achievementMapper.selectByStatYear("2026"))
                .thenReturn(Collections.singletonList(sampleAchievementRow()));
        when(projectMapper.selectPublishedForScreen(2026)).thenReturn(Collections.emptyList());
        when(achievementMapper.selectDistinctStatYears()).thenReturn(Collections.singletonList("2026"));
        when(projectMapper.selectDistinctStatYearsFromPublished()).thenReturn(Collections.emptyList());

        CommonProsperityScreenDashboardVo vo = service.loadDashboard("2026");
        assertTrue(vo.getAchievement().getHasData());
        assertFalse(vo.getHasProjectData());
        assertEquals(0, vo.getProjectTypeStats().get(0).getCount().intValue());
    }

    @Test
    @DisplayName("按所选年查询成果台账")
    void loadsAchievementsByStatYear()
    {
        when(achievementMapper.selectByStatYear("2026")).thenReturn(Collections.emptyList());
        when(projectMapper.selectPublishedForScreen(2026)).thenReturn(Collections.emptyList());
        when(achievementMapper.selectDistinctStatYears()).thenReturn(Collections.emptyList());
        when(projectMapper.selectDistinctStatYearsFromPublished()).thenReturn(Collections.emptyList());

        service.loadDashboard("2026");
        verify(achievementMapper).selectByStatYear("2026");
        verify(projectMapper).selectPublishedForScreen(eq(2026));
    }

    @Test
    @DisplayName("总览取所选年最大填报月，按月序列为该年 1～最大月")
    void summaryUsesMaxMonthOfSelectedYear()
    {
        BizCommonProsperityAchievement mar = sampleAchievementRowForYear(2025, 3);
        mar.setCollectiveEconomyIncome(new BigDecimal("10"));
        BizCommonProsperityAchievement aug = sampleAchievementRowForYear(2025, 8);
        aug.setCollectiveEconomyIncome(new BigDecimal("88"));
        aug.setEmploymentDrivenCount(50);
        when(achievementMapper.selectByStatYear("2025")).thenReturn(Arrays.asList(mar, aug));
        when(projectMapper.selectPublishedForScreen(2025)).thenReturn(Collections.emptyList());
        when(achievementMapper.selectDistinctStatYears()).thenReturn(Collections.singletonList("2025"));
        when(projectMapper.selectDistinctStatYearsFromPublished()).thenReturn(Collections.emptyList());

        CommonProsperityScreenDashboardVo vo = service.loadDashboard("2025");
        assertEquals(2025, vo.getStatYear().intValue());
        assertTrue(vo.getAchievement().getHasData());
        assertNotNull(vo.getAchievement().getSummary());
        assertEquals(0, new BigDecimal("88.00").compareTo(vo.getAchievement().getSummary().getCollectiveEconomyIncome()));
        assertEquals(50, vo.getAchievement().getSummary().getEmploymentDrivenCount().intValue());
        assertEquals(8, vo.getAchievement().getMonthly().size());
        assertEquals(2025, vo.getAchievement().getMonthly().get(0).getStatYear().intValue());
        assertEquals(0, new BigDecimal("10").compareTo(
                vo.getAchievement().getMonthly().get(2).getCollectiveEconomyIncome()));
        assertEquals(0, new BigDecimal("88").compareTo(
                vo.getAchievement().getMonthly().get(7).getCollectiveEconomyIncome()));
    }

    @Test
    @DisplayName("列表含运营图查询")
    void listLoadsOpImages()
    {
        BizCommonProsperityProject p = new BizCommonProsperityProject();
        p.setId(9L);
        p.setProjectType(2);
        p.setPublishStatus(1);
        p.setProjectName("测试");
        when(projectMapper.selectPublishedForScreen(2026)).thenReturn(Collections.singletonList(p));
        when(opImageMapper.selectByProjectIds(any())).thenReturn(Collections.emptyList());

        assertNotNull(service.listPublishedProjects("2026"));
        verify(opImageMapper).selectByProjectIds(Arrays.asList(9L));
    }

    @Test
    @DisplayName("分类明细：指定年份调用聚合查询")
    void listProjectTypeDetails_withYear()
    {
        CommonProsperityProjectTypeDetailVo row = new CommonProsperityProjectTypeDetailVo();
        row.setStatYear(2025);
        row.setTotalCount(5);
        row.setHeMeiVillageCount(2);
        row.setHabitatImproveCount(2);
        row.setOtherProjectCount(1);
        when(projectMapper.selectPublishedTypeDetailsByYear(2025)).thenReturn(Collections.singletonList(row));

        List<CommonProsperityProjectTypeDetailVo> list = service.listProjectTypeDetails(2025);
        assertEquals(1, list.size());
        assertEquals(2025, list.get(0).getStatYear().intValue());
        assertEquals(5, list.get(0).getTotalCount().intValue());
        assertEquals(2, list.get(0).getHeMeiVillageCount().intValue());
        verify(projectMapper).selectPublishedTypeDetailsByYear(2025);
    }

    @Test
    @DisplayName("分类明细：未传年份不过滤")
    void listProjectTypeDetails_noYearFilter()
    {
        when(projectMapper.selectPublishedTypeDetailsByYear(null)).thenReturn(Collections.emptyList());

        List<CommonProsperityProjectTypeDetailVo> list = service.listProjectTypeDetails(null);
        assertNotNull(list);
        assertTrue(list.isEmpty());
        verify(projectMapper).selectPublishedTypeDetailsByYear(null);
    }

    private static BizCommonProsperityAchievement sampleAchievementRow()
    {
        return sampleAchievementRowForYear(2026, 3);
    }

    private static BizCommonProsperityAchievement sampleAchievementRowForYear(int year, int month)
    {
        BizCommonProsperityAchievement r = new BizCommonProsperityAchievement();
        r.setStatPeriod(String.format("%d-%02d", year, month));
        r.setCollectiveEconomyIncome(new BigDecimal("10"));
        r.setEmploymentDrivenCount(1);
        r.setNewJobPositions(1);
        r.setEnvProjectCount(1);
        r.setNewGreenArea(new BigDecimal("1"));
        r.setCulturalHeritageCount(1);
        r.setEthnicIntegrationProjectCount(1);
        r.setEthnicUnityActivityCount(1);
        r.setDigitalPlatformUsageRate(new BigDecimal("0.1"));
        r.setRegionalPublicBrandCount(1);
        r.setBrandPremiumRate(new BigDecimal("0.1"));
        return r;
    }
}
