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.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.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.circulation.mapper.BizQuarantineStationMapper;
import com.ruoyi.web.modules.epidemic.EpidemicReportTestSamples;
import com.ruoyi.web.modules.epidemic.domain.BizLabDetection;
import com.ruoyi.web.modules.epidemic.domain.BizRiskFactorWeight;
import com.ruoyi.web.modules.epidemic.mapper.BizEpidemicReportMapper;
import com.ruoyi.web.modules.epidemic.mapper.BizLabDetectionMapper;
import com.ruoyi.web.modules.epidemic.mapper.BizRiskFactorWeightMapper;
import com.ruoyi.web.modules.screen.domain.vo.EpidemicRiskScreenDashboardVo;

/**
 * DP-DYFX 看板编排
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("EpidemicRiskScreenServiceImpl")
class EpidemicRiskScreenServiceImplTest
{

    @Mock
    private BizLabDetectionMapper labDetectionMapper;

    @Mock
    private BizEpidemicReportMapper epidemicReportMapper;

    @Mock
    private BizQuarantineStationMapper quarantineStationMapper;

    @Mock
    private BizRiskFactorWeightMapper riskFactorWeightMapper;

    @InjectMocks
    private EpidemicRiskScreenServiceImpl service;

    @Test
    @DisplayName("无检测无疫情")
    void emptyDashboard()
    {
        when(labDetectionMapper.selectByTestYear(2026)).thenReturn(Collections.emptyList());
        when(labDetectionMapper.selectByTestDateBetween(any(), any())).thenReturn(Collections.emptyList());
        when(epidemicReportMapper.selectByReportYear(2026)).thenReturn(Collections.emptyList());
        when(epidemicReportMapper.selectRelievedByReleaseYear(2026)).thenReturn(Collections.emptyList());
        when(epidemicReportMapper.selectActiveControlByReportYear(2026)).thenReturn(Collections.emptyList());
        when(quarantineStationMapper.countForScreenByOperateStatus(1)).thenReturn(0);
        when(quarantineStationMapper.countForScreenDisabled()).thenReturn(0);
        when(riskFactorWeightMapper.selectBizRiskFactorWeightById(1L)).thenReturn(null);
        when(labDetectionMapper.selectDistinctTestYears()).thenReturn(Collections.emptyList());
        when(epidemicReportMapper.selectDistinctReportYears()).thenReturn(Collections.emptyList());

        EpidemicRiskScreenDashboardVo vo = service.loadDashboard("2026");
        assertFalse(vo.isHasLabData());
        assertNull(vo.getLabDetection());
        assertFalse(vo.isHasEpidemicData());
        assertFalse(vo.isHasRelievedData());
        assertFalse(vo.getRiskFactorWeights().isHasRiskFactorConfig());
    }

    @Test
    @DisplayName("仅有检测")
    void labOnly()
    {
        BizLabDetection d = new BizLabDetection();
        d.setTestDate(EpidemicReportTestSamples.date(2026, java.util.Calendar.MARCH, 1));
        d.setSampleSource(1);
        d.setTestQuantity(10);
        d.setPositiveCount(1);
        when(labDetectionMapper.selectByTestYear(2026)).thenReturn(Collections.singletonList(d));
        when(labDetectionMapper.selectByTestDateBetween(any(), any())).thenReturn(Collections.singletonList(d));
        when(epidemicReportMapper.selectByReportYear(2026)).thenReturn(Collections.emptyList());
        when(epidemicReportMapper.selectRelievedByReleaseYear(2026)).thenReturn(Collections.emptyList());
        when(epidemicReportMapper.selectActiveControlByReportYear(2026)).thenReturn(Collections.emptyList());
        stubQuarantineAndYears();

        EpidemicRiskScreenDashboardVo vo = service.loadDashboard("2026");
        assertTrue(vo.isHasLabData());
        assertEquals(10, vo.getLabDetection().getTestQuantityTotal());
        assertFalse(vo.isHasEpidemicData());
    }

    @Test
    @DisplayName("列表按上报年查询")
    void listReports()
    {
        when(epidemicReportMapper.selectByReportYear(2026))
                .thenReturn(Collections.singletonList(EpidemicReportTestSamples.sampleOpen()));
        assertEquals(1, service.listReportsByReportYear("2026").size());
        verify(epidemicReportMapper).selectByReportYear(eq(2026));
    }

    @Test
    @DisplayName("风险因子配置")
    void riskFactorConfig()
    {
        when(labDetectionMapper.selectByTestYear(2026)).thenReturn(Collections.emptyList());
        when(labDetectionMapper.selectByTestDateBetween(any(), any())).thenReturn(Collections.emptyList());
        when(epidemicReportMapper.selectByReportYear(2026)).thenReturn(Collections.emptyList());
        when(epidemicReportMapper.selectRelievedByReleaseYear(2026)).thenReturn(Collections.emptyList());
        when(epidemicReportMapper.selectActiveControlByReportYear(2026)).thenReturn(Collections.emptyList());
        stubQuarantineAndYears();
        BizRiskFactorWeight w = new BizRiskFactorWeight();
        w.setId(1L);
        w.setWeightBreedingDensity(new BigDecimal("0.2000"));
        w.setWeightTrafficMobility(new BigDecimal("0.2000"));
        w.setWeightQuarantineIntensity(new BigDecimal("0.2000"));
        w.setWeightMeteorologicalSuitability(new BigDecimal("0.2000"));
        w.setWeightPastDiseaseLevel(new BigDecimal("0.2000"));
        when(riskFactorWeightMapper.selectBizRiskFactorWeightById(1L)).thenReturn(w);

        EpidemicRiskScreenDashboardVo vo = service.loadDashboard("2026");
        assertTrue(vo.getRiskFactorWeights().isHasRiskFactorConfig());
        assertEquals(5, vo.getRiskFactorWeights().getItems().size());
    }

    private void stubQuarantineAndYears()
    {
        when(quarantineStationMapper.countForScreenByOperateStatus(1)).thenReturn(2);
        when(quarantineStationMapper.countForScreenDisabled()).thenReturn(1);
        when(riskFactorWeightMapper.selectBizRiskFactorWeightById(1L)).thenReturn(null);
        when(labDetectionMapper.selectDistinctTestYears()).thenReturn(Collections.singletonList("2026"));
        when(epidemicReportMapper.selectDistinctReportYears()).thenReturn(Collections.emptyList());
    }
}
