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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
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.common.exception.ServiceException;
import com.ruoyi.web.modules.industryservice.domain.BizYakAsset;
import com.ruoyi.web.modules.industryservice.domain.BizYakGrowthRecord;
import com.ruoyi.web.modules.industryservice.domain.vo.YakAssetDetailVo;
import com.ruoyi.web.modules.industryservice.domain.vo.YakAssetGrowthChartVo;
import com.ruoyi.web.modules.industryservice.mapper.BizYakAssetMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizYakBatchRelMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizYakFeedingRecordMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizYakPenRelMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizYakGrowthRecordMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizYakPhysioSeriesMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizYakReproductionRecordMapper;
import com.ruoyi.web.modules.industryservice.service.YakAssetSyncService;
import com.ruoyi.web.modules.industryservice.support.YakAssetRules;

@ExtendWith(MockitoExtension.class)
@DisplayName("BizYakAssetServiceImpl")
class BizYakAssetServiceImplTest
{
    @Mock
    private BizYakAssetMapper bizYakAssetMapper;

    @Mock
    private BizYakPhysioSeriesMapper physioSeriesMapper;

    @Mock
    private BizYakGrowthRecordMapper growthRecordMapper;

    @Mock
    private BizYakReproductionRecordMapper reproductionRecordMapper;

    @Mock
    private BizYakFeedingRecordMapper feedingRecordMapper;

    @Mock
    private BizYakPenRelMapper penRelMapper;

    @Mock
    private BizYakBatchRelMapper batchRelMapper;

    @Mock
    private YakAssetSyncService yakAssetSyncService;

    @InjectMocks
    private BizYakAssetServiceImpl service;

    @Test
    @DisplayName("ZCZX-MYNZDA-UT-013 详情组装")
    void ut013_detail()
    {
        BizYakAsset asset = sampleAsset(1L);
        when(bizYakAssetMapper.selectBizYakAssetById(1L)).thenReturn(asset);
        when(physioSeriesMapper.selectByYakAssetId(1L)).thenReturn(Collections.emptyList());
        when(growthRecordMapper.selectByYakAssetId(1L)).thenReturn(Collections.emptyList());
        when(reproductionRecordMapper.selectByYakAssetId(1L)).thenReturn(Collections.emptyList());
        when(feedingRecordMapper.selectByYakAssetId(1L)).thenReturn(Collections.emptyList());
        when(penRelMapper.selectByYakAssetId(1L)).thenReturn(Collections.emptyList());
        when(batchRelMapper.selectByYakAssetId(1L)).thenReturn(Collections.emptyList());
        YakAssetDetailVo vo = service.selectDetailById(1L);
        assertEquals("YAK20250001", vo.getAsset().getYakNo());
        verify(physioSeriesMapper).selectByYakAssetId(1L);
    }

    @Test
    @DisplayName("ZCZX-MYNZDA-UT-014 已删不可查")
    void ut014_notFound()
    {
        when(bizYakAssetMapper.selectBizYakAssetById(99L)).thenReturn(null);
        assertThrows(ServiceException.class, () -> service.selectDetailById(99L));
    }

    @Test
    @DisplayName("ZCZX-MYNZDA-UT-012 生长曲线分组")
    void ut012_growthChart()
    {
        BizYakAsset asset = sampleAsset(2L);
        when(bizYakAssetMapper.selectBizYakAssetById(2L)).thenReturn(asset);
        BizYakGrowthRecord actual = new BizYakGrowthRecord();
        actual.setDayAge(100);
        actual.setWeightKg(new BigDecimal("200"));
        actual.setDataKind(YakAssetRules.DATA_KIND_ACTUAL);
        BizYakGrowthRecord forecast = new BizYakGrowthRecord();
        forecast.setDayAge(120);
        forecast.setWeightKg(new BigDecimal("210"));
        forecast.setDataKind(YakAssetRules.DATA_KIND_FORECAST);
        when(growthRecordMapper.selectByYakAssetId(2L)).thenReturn(Arrays.asList(actual, forecast));
        YakAssetGrowthChartVo chart = service.selectGrowthChart(2L, "weight");
        assertEquals(1, chart.getActual().size());
        assertEquals(1, chart.getForecast().size());
    }

    @Test
    @DisplayName("ZCZX-MYNZDA-UT-015 byNo")
    void ut015_byNo()
    {
        BizYakAsset asset = sampleAsset(3L);
        when(bizYakAssetMapper.selectBizYakAssetByYakNo("YAK20250001")).thenReturn(asset);
        when(physioSeriesMapper.selectByYakAssetId(3L)).thenReturn(Collections.emptyList());
        when(growthRecordMapper.selectByYakAssetId(3L)).thenReturn(Collections.emptyList());
        when(reproductionRecordMapper.selectByYakAssetId(3L)).thenReturn(Collections.emptyList());
        when(feedingRecordMapper.selectByYakAssetId(3L)).thenReturn(Collections.emptyList());
        when(penRelMapper.selectByYakAssetId(3L)).thenReturn(Collections.emptyList());
        when(batchRelMapper.selectByYakAssetId(3L)).thenReturn(Collections.emptyList());
        YakAssetDetailVo vo = service.selectDetailByYakNo("YAK20250001");
        assertEquals(3L, vo.getAsset().getId());
    }

    @Test
    @DisplayName("列表非法状态")
    void listInvalidStatus()
    {
        BizYakAsset query = new BizYakAsset();
        query.setAssetStatus(99);
        assertThrows(ServiceException.class, () -> service.selectBizYakAssetList(query));
    }

    @Test
    @DisplayName("ZCZX-MYNZDA-UT-011 生理曲线")
    void ut011_physioChart()
    {
        BizYakAsset asset = sampleAsset(4L);
        when(bizYakAssetMapper.selectBizYakAssetById(4L)).thenReturn(asset);
        when(physioSeriesMapper.selectChartByYakAssetId(4L, 30)).thenReturn(Collections.emptyList());
        List<?> chart = service.selectPhysioChart(4L, null);
        assertEquals(0, chart.size());
        verify(physioSeriesMapper).selectChartByYakAssetId(eq(4L), eq(30));
    }

    private static BizYakAsset sampleAsset(Long id)
    {
        BizYakAsset a = new BizYakAsset();
        a.setId(id);
        a.setYakNo("YAK20250001");
        a.setAssetStatus(2);
        return a;
    }
}
