package com.ruoyi.web.modules.innovation.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.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.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.innovation.TechProjectGuideTestSamples;
import com.ruoyi.web.modules.innovation.domain.BizTechProjectGuide;
import com.ruoyi.web.modules.innovation.mapper.BizTechProjectGuideMapper;
import com.ruoyi.web.modules.innovation.support.TechProjectGuideTypeValidator;

/**
 * KJXM-UT-009～015
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("BizTechProjectGuideServiceImpl")
class BizTechProjectGuideServiceImplTest
{

    @Mock
    private BizTechProjectGuideMapper techProjectGuideMapper;

    @Mock
    private TechProjectGuideTypeValidator techProjectGuideTypeValidator;

    @InjectMocks
    private BizTechProjectGuideServiceImpl service;

    @Test
    @DisplayName("KJXM-UT-009 已发布禁止修改")
    void ut009_updatePublished()
    {
        BizTechProjectGuide db = TechProjectGuideTestSamples.sampleDraft();
        db.setId(1L);
        db.setPublishStatus(1);
        when(techProjectGuideMapper.selectBizTechProjectGuideById(1L)).thenReturn(db);
        BizTechProjectGuide in = TechProjectGuideTestSamples.sampleDraft();
        in.setId(1L);
        in.setProjectIntro("新简介");
        assertThrows(ServiceException.class, () -> service.updateBizTechProjectGuide(in));
        verify(techProjectGuideMapper, never()).updateBizTechProjectGuide(any());
    }

    @Test
    @DisplayName("KJXM-UT-010 已发布禁止删除")
    void ut010_deletePublished()
    {
        BizTechProjectGuide db = TechProjectGuideTestSamples.sampleDraft();
        db.setId(2L);
        db.setPublishStatus(1);
        when(techProjectGuideMapper.selectBizTechProjectGuideById(2L)).thenReturn(db);
        assertThrows(ServiceException.class, () -> service.deleteBizTechProjectGuideByIds(new Long[] { 2L }));
        verify(techProjectGuideMapper, never()).deleteBizTechProjectGuideByIds(any());
    }

    @Test
    @DisplayName("KJXM-UT-011 未发布禁止下架")
    void ut011_offlineDraft()
    {
        BizTechProjectGuide db = TechProjectGuideTestSamples.sampleDraft();
        db.setId(3L);
        db.setPublishStatus(0);
        when(techProjectGuideMapper.selectBizTechProjectGuideById(3L)).thenReturn(db);
        assertThrows(ServiceException.class, () -> service.offline(3L));
    }

    @Test
    @DisplayName("KJXM-UT-012 发布写状态与时间")
    void ut012_publish()
    {
        BizTechProjectGuide db = TechProjectGuideTestSamples.sampleDraft();
        db.setId(4L);
        db.setPublishStatus(0);
        when(techProjectGuideMapper.selectBizTechProjectGuideById(4L)).thenReturn(db);
        when(techProjectGuideMapper.updateBizTechProjectGuide(any())).thenReturn(1);
        assertEquals(1, service.publish(4L));
        verify(techProjectGuideMapper).updateBizTechProjectGuide(argThat(r ->
                r.getPublishStatus() == 1 && r.getPublishTime() != null));
    }

    @Test
    @DisplayName("KJXM-UT-013 下架保留发布日期")
    void ut013_offlineKeepsPublishTime()
    {
        BizTechProjectGuide db = TechProjectGuideTestSamples.sampleDraft();
        db.setId(5L);
        db.setPublishStatus(1);
        Date publishTime = new Date();
        db.setPublishTime(publishTime);
        when(techProjectGuideMapper.selectBizTechProjectGuideById(5L)).thenReturn(db);
        when(techProjectGuideMapper.updateBizTechProjectGuide(any())).thenReturn(1);
        assertEquals(1, service.offline(5L));
        verify(techProjectGuideMapper).updateBizTechProjectGuide(argThat(r ->
                r.getPublishStatus() == 0
                        && r.getPublishTime() == publishTime
                        && r.getOfflineTime() != null));
    }

    @Test
    @DisplayName("KJXM-UT-014 新增 saveAndPublish")
    void ut014_insertSaveAndPublish()
    {
        when(techProjectGuideMapper.insertBizTechProjectGuide(any())).thenAnswer(inv -> {
            BizTechProjectGuide r = inv.getArgument(0);
            r.setId(10L);
            return 1;
        });
        when(techProjectGuideMapper.selectBizTechProjectGuideById(10L)).thenAnswer(inv -> {
            BizTechProjectGuide r = TechProjectGuideTestSamples.sampleDraft();
            r.setId(10L);
            r.setPublishStatus(0);
            return r;
        });
        when(techProjectGuideMapper.updateBizTechProjectGuide(any())).thenReturn(1);
        BizTechProjectGuide row = TechProjectGuideTestSamples.sampleDraft();
        row.setSaveAndPublish(true);
        assertEquals(1, service.insertBizTechProjectGuide(row));
        verify(techProjectGuideMapper).updateBizTechProjectGuide(argThat(r -> r.getPublishStatus() == 1));
    }

    @Test
    @DisplayName("KJXM-UT-015 替换附件路径触发更新")
    void ut015_updateReplaceAttachment()
    {
        BizTechProjectGuide db = TechProjectGuideTestSamples.sampleWithAttachment();
        db.setId(6L);
        db.setPublishStatus(0);
        when(techProjectGuideMapper.selectBizTechProjectGuideById(6L)).thenReturn(db);
        when(techProjectGuideMapper.updateBizTechProjectGuide(any())).thenReturn(1);
        BizTechProjectGuide in = TechProjectGuideTestSamples.sampleWithAttachment();
        in.setId(6L);
        in.setAttachmentFilePath(Constants.RESOURCE_PREFIX + "/upload/new.pdf");
        in.setAttachmentFileName("new.pdf");
        assertEquals(1, service.updateBizTechProjectGuide(in));
        verify(techProjectGuideMapper).updateBizTechProjectGuide(any());
    }

    @Test
    @DisplayName("新增仅保存未发布")
    void insertDraft()
    {
        when(techProjectGuideMapper.insertBizTechProjectGuide(any())).thenReturn(1);
        assertEquals(1, service.insertBizTechProjectGuide(TechProjectGuideTestSamples.sampleDraft()));
        verify(techProjectGuideMapper).insertBizTechProjectGuide(argThat(r ->
                r.getPublishStatus() == 0 && r.getPublishTime() == null));
        verify(techProjectGuideMapper, never()).updateBizTechProjectGuide(any());
    }
}
