package com.ruoyi.web.modules.industrypolicy.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.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.math.BigDecimal;
import java.util.Calendar;
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.common.exception.ServiceException;
import com.ruoyi.web.modules.industrypolicy.domain.BizSubsidyProject;
import com.ruoyi.web.modules.industrypolicy.mapper.BizSubsidyProjectMapper;
import com.ruoyi.web.modules.industrypolicy.support.SubsidyProjectRules;
import com.ruoyi.web.modules.industrypolicy.support.SubsidyProjectStatusResolver;

@ExtendWith(MockitoExtension.class)
@DisplayName("BizSubsidyProjectServiceImpl")
class BizSubsidyProjectServiceImplTest
{
    @Mock
    private BizSubsidyProjectMapper mapper;

    @InjectMocks
    private BizSubsidyProjectServiceImpl service;

    @Test
    @DisplayName("ZCZX-BTXM-UT-012 保存后推算进行中")
    void ut012_insertAutoInProgress()
    {
        when(mapper.insertBizSubsidyProject(any())).thenAnswer(inv -> {
            BizSubsidyProject r = inv.getArgument(0);
            r.setId(1L);
            return 1;
        });
        BizSubsidyProject row = inProgressRow();
        row.setExecStatus(SubsidyProjectRules.EXEC_NOT_STARTED);
        assertEquals(1, service.insertBizSubsidyProject(row));
        verify(mapper).insertBizSubsidyProject(argThat(r ->
                r.getExecStatus() == SubsidyProjectRules.EXEC_IN_PROGRESS
                        && r.getManualCompleteFlag() == SubsidyProjectRules.MANUAL_FLAG_AUTO));
    }

    @Test
    @DisplayName("ZCZX-BTXM-UT-013 手工完成写 flag")
    void ut013_manualComplete()
    {
        when(mapper.insertBizSubsidyProject(any())).thenReturn(1);
        BizSubsidyProject row = inProgressRow();
        row.setExecStatus(SubsidyProjectRules.EXEC_COMPLETED);
        row.setActualEndDate(daysFromNow(0));
        assertEquals(1, service.insertBizSubsidyProject(row));
        verify(mapper).insertBizSubsidyProject(argThat(r ->
                r.getManualCompleteFlag() == SubsidyProjectRules.MANUAL_FLAG_LOCKED
                        && r.getActualEndDate() != null));
    }

    @Test
    @DisplayName("ZCZX-BTXM-UT-014 列表查询刷新状态")
    void ut014_listRefresh()
    {
        BizSubsidyProject row = inProgressRow();
        row.setId(10L);
        row.setExecStatus(SubsidyProjectRules.EXEC_NOT_STARTED);
        row.setManualCompleteFlag(SubsidyProjectRules.MANUAL_FLAG_AUTO);
        when(mapper.selectBizSubsidyProjectList(any())).thenReturn(Collections.singletonList(row));
        when(mapper.updateBizSubsidyProjectExecStatus(any())).thenReturn(1);
        service.selectBizSubsidyProjectList(new BizSubsidyProject());
        verify(mapper).updateBizSubsidyProjectExecStatus(argThat(r ->
                r.getExecStatus() == SubsidyProjectRules.EXEC_IN_PROGRESS));
    }

    @Test
    @DisplayName("ZCZX-BTXM-UT-015 删除清封面")
    void ut015_delete()
    {
        BizSubsidyProject db = inProgressRow();
        db.setId(5L);
        db.setPublishStatus(0);
        db.setCoverFilePath("/profile/upload/cover.jpg");
        when(mapper.selectBizSubsidyProjectById(5L)).thenReturn(db);
        when(mapper.deleteBizSubsidyProjectByIds(any())).thenReturn(1);
        assertEquals(1, service.deleteBizSubsidyProjectByIds(new Long[] { 5L }));
    }

    @Test
    @DisplayName("已发布禁止修改")
    void updatePublished()
    {
        BizSubsidyProject db = inProgressRow();
        db.setId(9L);
        db.setPublishStatus(1);
        when(mapper.selectBizSubsidyProjectById(9L)).thenReturn(db);
        BizSubsidyProject in = inProgressRow();
        in.setId(9L);
        assertThrows(ServiceException.class, () -> service.updateBizSubsidyProject(in));
        verify(mapper, never()).updateBizSubsidyProject(any());
    }

    @Test
    @DisplayName("发布成功")
    void publish()
    {
        BizSubsidyProject db = inProgressRow();
        db.setId(3L);
        db.setPublishStatus(0);
        when(mapper.selectBizSubsidyProjectById(3L)).thenReturn(db);
        when(mapper.updateBizSubsidyProject(any())).thenReturn(1);
        assertEquals(1, service.publish(3L));
        verify(mapper).updateBizSubsidyProject(argThat(r -> r.getPublishStatus() == 1 && r.getPublishTime() != null));
    }

    private static BizSubsidyProject inProgressRow()
    {
        BizSubsidyProject r = new BizSubsidyProject();
        r.setProjectName("示范项目");
        r.setInvestmentAmount(new BigDecimal("10000"));
        r.setProjectStartDate(daysFromNow(-1));
        r.setPlannedEndDate(daysFromNow(10));
        r.setExecStatus(SubsidyProjectRules.EXEC_IN_PROGRESS);
        return r;
    }

    private static Date daysFromNow(int delta)
    {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, delta);
        return SubsidyProjectStatusResolver.truncateToDay(cal.getTime());
    }
}
