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.argThat;
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.math.BigDecimal;
import java.sql.Date;
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.common.exception.ServiceException;
import com.ruoyi.web.modules.industryservice.domain.BizGrassland;
import com.ruoyi.web.modules.industryservice.domain.BizGrasslandUsageRecord;
import com.ruoyi.web.modules.industryservice.domain.BizPasture;
import com.ruoyi.web.modules.industryservice.mapper.BizGrasslandMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizGrasslandUsageRecordMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizPastureMapper;
import com.ruoyi.web.modules.industryservice.support.GrasslandRules;
import com.ruoyi.web.modules.industryservice.support.GrasslandUsageRules;
import com.ruoyi.web.modules.industrypolicy.support.PastureRules;

@ExtendWith(MockitoExtension.class)
@DisplayName("BizGrasslandUsageRecordServiceImpl")
class BizGrasslandUsageRecordServiceImplTest
{
    @Mock
    private BizGrasslandUsageRecordMapper usageMapper;

    @Mock
    private BizGrasslandMapper grasslandMapper;

    @Mock
    private BizPastureMapper pastureMapper;

    @InjectMocks
    private BizGrasslandUsageRecordServiceImpl service;

    @Test
    @DisplayName("ZCZX-CCSYJL-UT-010 新增落库")
    void ut010_insert()
    {
        stubActiveMasterData();
        when(usageMapper.insertBizGrasslandUsageRecord(any())).thenReturn(1);
        BizGrasslandUsageRecord row = sampleRow();
        assertEquals(1, service.insertBizGrasslandUsageRecord(row));
        verify(usageMapper).insertBizGrasslandUsageRecord(argThat(r ->
                GrasslandUsageRules.DEL_FLAG_NORMAL.equals(r.getDelFlag()) && r.getActualUseDays() == 3));
    }

    @Test
    @DisplayName("ZCZX-CCSYJL-UT-011 忽略客户端天数")
    void ut011_ignoreClientDays()
    {
        stubActiveMasterData();
        when(usageMapper.insertBizGrasslandUsageRecord(any())).thenReturn(1);
        BizGrasslandUsageRecord row = sampleRow();
        row.setActualUseDays(999);
        service.insertBizGrasslandUsageRecord(row);
        verify(usageMapper).insertBizGrasslandUsageRecord(argThat(r -> r.getActualUseDays() == 3));
    }

    @Test
    @DisplayName("ZCZX-CCSYJL-UT-012 修改全字段")
    void ut012_update()
    {
        stubActiveMasterData();
        BizGrasslandUsageRecord db = sampleRow();
        db.setId(5L);
        when(usageMapper.selectBizGrasslandUsageRecordById(5L)).thenReturn(db);
        when(usageMapper.updateBizGrasslandUsageRecord(any())).thenReturn(1);
        BizGrasslandUsageRecord in = sampleRow();
        in.setId(5L);
        in.setUsageAreaMu(new BigDecimal("80"));
        in.setGrazingHeadCount(200);
        assertEquals(1, service.updateBizGrasslandUsageRecord(in));
        verify(usageMapper).updateBizGrasslandUsageRecord(any());
    }

    @Test
    @DisplayName("ZCZX-CCSYJL-UT-013 修改不存在")
    void ut013_updateMissing()
    {
        when(usageMapper.selectBizGrasslandUsageRecordById(99L)).thenReturn(null);
        BizGrasslandUsageRecord in = sampleRow();
        in.setId(99L);
        assertThrows(ServiceException.class, () -> service.updateBizGrasslandUsageRecord(in));
        verify(usageMapper, never()).updateBizGrasslandUsageRecord(any());
    }

    @Test
    @DisplayName("ZCZX-CCSYJL-UT-009 主数据已删除")
    void ut009_deletedGrassland()
    {
        BizGrassland grassland = new BizGrassland();
        grassland.setId(1L);
        grassland.setDelFlag(GrasslandRules.DEL_FLAG_DELETED);
        grassland.setAreaMu(new BigDecimal("100"));
        when(grasslandMapper.selectBizGrasslandById(1L)).thenReturn(grassland);
        assertThrows(ServiceException.class, () -> service.insertBizGrasslandUsageRecord(sampleRow()));
        verify(usageMapper, never()).insertBizGrasslandUsageRecord(any());
    }

    @Test
    @DisplayName("ZCZX-CCSYJL-UT-014 逻辑删除")
    void ut014_logicDelete()
    {
        when(usageMapper.logicDeleteBizGrasslandUsageRecordByIds(any(), eq("tester"))).thenReturn(1);
        assertEquals(1, service.deleteBizGrasslandUsageRecordByIds(new Long[] { 8L }, "tester"));
        verify(usageMapper).logicDeleteBizGrasslandUsageRecordByIds(any(), eq("tester"));
    }

    @Test
    @DisplayName("ZCZX-CCSYJL-UT-015 列表日期非法")
    void ut015_listBadDateRange()
    {
        BizGrasslandUsageRecord query = new BizGrasslandUsageRecord();
        query.setStartDate("2025-12-01");
        query.setEndDate("2025-01-01");
        assertThrows(ServiceException.class, () -> service.selectBizGrasslandUsageRecordList(query));
        verify(usageMapper, never()).selectBizGrasslandUsageRecordList(any());
    }

    @Test
    @DisplayName("列表查询合法日期")
    void listOk()
    {
        when(usageMapper.selectBizGrasslandUsageRecordList(any())).thenReturn(Collections.emptyList());
        BizGrasslandUsageRecord query = new BizGrasslandUsageRecord();
        query.setStartDate("2025-01-01");
        query.setEndDate("2025-06-30");
        assertEquals(0, service.selectBizGrasslandUsageRecordList(query).size());
    }

    private void stubActiveMasterData()
    {
        BizGrassland grassland = new BizGrassland();
        grassland.setId(1L);
        grassland.setDelFlag(GrasslandRules.DEL_FLAG_NORMAL);
        grassland.setAreaMu(new BigDecimal("100"));
        when(grasslandMapper.selectBizGrasslandById(1L)).thenReturn(grassland);

        BizPasture pasture = new BizPasture();
        pasture.setId(2L);
        pasture.setDelFlag(PastureRules.DEL_FLAG_NORMAL);
        when(pastureMapper.selectBizPastureById(2L)).thenReturn(pasture);
    }

    private static BizGrasslandUsageRecord sampleRow()
    {
        BizGrasslandUsageRecord r = new BizGrasslandUsageRecord();
        r.setGrasslandId(1L);
        r.setPastureId(2L);
        r.setUsageAreaMu(new BigDecimal("50"));
        r.setUseStartDate(Date.valueOf("2025-06-01"));
        r.setUseEndDate(Date.valueOf("2025-06-03"));
        r.setGrazingHeadCount(100);
        r.setGrazingMethod(GrasslandUsageRules.GRAZING_ROTATION);
        return r;
    }
}
