package com.ruoyi.web.modules.diagnosis.service;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
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.diagnosis.domain.dto.ConsultAskerIpCountDto;
import com.ruoyi.web.modules.diagnosis.mapper.BizConsultMessageMapper;
import com.ruoyi.web.modules.diagnosis.support.AiConsultDiseaseWarningProperties;
import com.ruoyi.web.modules.diagnosis.support.AiConsultDiseaseWarningRules;
import com.ruoyi.web.modules.diagnosis.support.ConsultAskerIpRegionResolver;
import com.ruoyi.web.modules.industryservice.domain.BizYakDiseaseWarning;
import com.ruoyi.web.modules.industryservice.mapper.BizYakDiseaseWarningMapper;

@ExtendWith(MockitoExtension.class)
@DisplayName("AiConsultDiseaseWarningService")
class AiConsultDiseaseWarningServiceTest
{
    @Mock
    private AiConsultDiseaseWarningProperties properties;

    @Mock
    private BizConsultMessageMapper consultMessageMapper;

    @Mock
    private BizYakDiseaseWarningMapper warningMapper;

    @Mock
    private ConsultAskerIpRegionResolver ipRegionResolver;

    @InjectMocks
    private AiConsultDiseaseWarningService service;

    @Test
    @DisplayName("未启用")
    void disabled()
    {
        when(properties.isEnabled()).thenReturn(false);
        assertEquals(0, service.scanAndPersistWarnings());
        verify(consultMessageMapper, never()).selectAiYakDiseaseAskerIpCounts(eq(2), any(), any(), any());
    }

    @Test
    @DisplayName("达阈值新增预警")
    void insertWarning()
    {
        when(properties.isEnabled()).thenReturn(true);
        when(properties.getThreshold()).thenReturn(3);
        ConsultAskerIpCountDto row = new ConsultAskerIpCountDto();
        row.setAskerIp("1.2.3.4");
        row.setMessageCount(3L);
        when(consultMessageMapper.selectAiYakDiseaseAskerIpCounts(eq(2),
                eq(AiConsultDiseaseWarningRules.AI_CATEGORY), any(Date.class),
                any(Date.class))).thenReturn(Collections.singletonList(row));
        when(ipRegionResolver.resolveDistrictLabel("1.2.3.4")).thenReturn("巴青区");
        when(warningMapper.selectMonthlyWarningByPastureName(eq("巴青区"),
                eq(AiConsultDiseaseWarningRules.WARNING_TYPE_AI_CONSULT), any(Date.class), any(Date.class)))
                .thenReturn(null);
        assertEquals(1, service.scanAndPersistWarnings());
        verify(warningMapper).insertBizYakDiseaseWarning(org.mockito.ArgumentMatchers.argThat(
                w -> w != null && w.getYakNo() == null));
    }

    @Test
    @DisplayName("达阈值更新已有预警")
    void updateWarning()
    {
        when(properties.isEnabled()).thenReturn(true);
        when(properties.getThreshold()).thenReturn(3);
        ConsultAskerIpCountDto row = new ConsultAskerIpCountDto();
        row.setAskerIp("1.2.3.4");
        row.setMessageCount(5L);
        when(consultMessageMapper.selectAiYakDiseaseAskerIpCounts(eq(2),
                eq(AiConsultDiseaseWarningRules.AI_CATEGORY), any(Date.class),
                any(Date.class))).thenReturn(Collections.singletonList(row));
        when(ipRegionResolver.resolveDistrictLabel("1.2.3.4")).thenReturn("巴青区");
        BizYakDiseaseWarning existing = new BizYakDiseaseWarning();
        existing.setId(9L);
        when(warningMapper.selectMonthlyWarningByPastureName(eq("巴青区"),
                eq(AiConsultDiseaseWarningRules.WARNING_TYPE_AI_CONSULT), any(Date.class), any(Date.class)))
                .thenReturn(existing);
        assertEquals(1, service.scanAndPersistWarnings());
        verify(warningMapper).updateAlertContent(any());
        verify(warningMapper, never()).insertBizYakDiseaseWarning(any());
    }

    @Test
    @DisplayName("未达阈值不写入")
    void belowThreshold()
    {
        when(properties.isEnabled()).thenReturn(true);
        when(properties.getThreshold()).thenReturn(3);
        ConsultAskerIpCountDto row = new ConsultAskerIpCountDto();
        row.setAskerIp("1.2.3.4");
        row.setMessageCount(2L);
        when(consultMessageMapper.selectAiYakDiseaseAskerIpCounts(eq(2),
                eq(AiConsultDiseaseWarningRules.AI_CATEGORY), any(Date.class),
                any(Date.class))).thenReturn(Collections.singletonList(row));
        assertEquals(0, service.scanAndPersistWarnings());
        verify(warningMapper, never()).insertBizYakDiseaseWarning(any());
    }

    @Test
    @DisplayName("同地区多 IP 累计")
    void aggregateRegion()
    {
        when(properties.isEnabled()).thenReturn(true);
        when(properties.getThreshold()).thenReturn(3);
        ConsultAskerIpCountDto a = new ConsultAskerIpCountDto();
        a.setAskerIp("1.1.1.1");
        a.setMessageCount(3L);
        ConsultAskerIpCountDto b = new ConsultAskerIpCountDto();
        b.setAskerIp("2.2.2.2");
        b.setMessageCount(4L);
        when(consultMessageMapper.selectAiYakDiseaseAskerIpCounts(eq(2),
                eq(AiConsultDiseaseWarningRules.AI_CATEGORY), any(Date.class),
                any(Date.class))).thenReturn(Arrays.asList(a, b));
        when(ipRegionResolver.resolveDistrictLabel("1.1.1.1")).thenReturn("巴青区");
        when(ipRegionResolver.resolveDistrictLabel("2.2.2.2")).thenReturn("巴青区");
        when(warningMapper.selectMonthlyWarningByPastureName(eq("巴青区"),
                eq(AiConsultDiseaseWarningRules.WARNING_TYPE_AI_CONSULT), any(Date.class), any(Date.class)))
                .thenReturn(null);
        assertEquals(1, service.scanAndPersistWarnings());
        verify(warningMapper).insertBizYakDiseaseWarning(org.mockito.ArgumentMatchers.argThat(
                w -> w != null && "7".equals(w.getMeasuredValue())));
    }
}
