package com.ruoyi.web.modules.prosperity.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.Arrays;
import java.util.Calendar;
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.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.prosperity.domain.BizCommonProsperityProject;
import com.ruoyi.web.modules.prosperity.domain.BizCommonProsperityProjectOpImage;
import com.ruoyi.web.modules.prosperity.mapper.BizCommonProsperityProjectMapper;
import com.ruoyi.web.modules.prosperity.mapper.BizCommonProsperityProjectOpImageMapper;

/**
 * GTFY-XM-UT-014～022
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("BizCommonProsperityProjectServiceImpl")
class BizCommonProsperityProjectServiceImplTest
{

    @Mock
    private BizCommonProsperityProjectMapper projectMapper;

    @Mock
    private BizCommonProsperityProjectOpImageMapper opImageMapper;

    @InjectMocks
    private BizCommonProsperityProjectServiceImpl service;

    @Test
    @DisplayName("GTFY-XM-UT-014 新增初始未发布")
    void ut014_insert()
    {
        when(projectMapper.insertBizCommonProsperityProject(any())).thenAnswer(inv -> {
            BizCommonProsperityProject r = inv.getArgument(0);
            r.setId(1L);
            return 1;
        });
        assertEquals(1, service.insertBizCommonProsperityProject(sampleRow()));
        verify(projectMapper).insertBizCommonProsperityProject(argThat(r ->
                r.getPublishStatus() == 0 && r.getPublishTime() == null));
        verify(opImageMapper).insertBatch(any());
    }

    @Test
    @DisplayName("GTFY-XM-UT-015 已发布禁止修改")
    void ut015_updatePublished()
    {
        BizCommonProsperityProject db = sampleRow();
        db.setId(9L);
        db.setPublishStatus(1);
        when(projectMapper.selectBizCommonProsperityProjectById(9L)).thenReturn(db);
        BizCommonProsperityProject in = sampleRow();
        in.setId(9L);
        in.setProjectName("新名称");
        ServiceException ex = assertThrows(ServiceException.class, () -> service.updateBizCommonProsperityProject(in));
        org.junit.jupiter.api.Assertions.assertTrue(ex.getMessage().contains("下架"));
        verify(projectMapper, never()).updateBizCommonProsperityProject(any());
    }

    @Test
    @DisplayName("GTFY-XM-UT-016 发布成功")
    void ut016_publish()
    {
        BizCommonProsperityProject db = sampleRow();
        db.setId(3L);
        db.setPublishStatus(0);
        when(projectMapper.selectBizCommonProsperityProjectById(3L)).thenReturn(db);
        when(opImageMapper.selectByProjectId(3L)).thenReturn(Collections.singletonList(sampleImage(1)));
        when(projectMapper.updateBizCommonProsperityProject(any())).thenReturn(1);
        assertEquals(1, service.publish(3L));
        verify(projectMapper).updateBizCommonProsperityProject(argThat(r ->
                r.getPublishStatus() == 1 && r.getPublishTime() != null));
    }

    @Test
    @DisplayName("GTFY-XM-UT-017 发布缺运营图拒绝")
    void ut017_publishNoImages()
    {
        BizCommonProsperityProject db = sampleRow();
        db.setId(6L);
        db.setPublishStatus(0);
        when(projectMapper.selectBizCommonProsperityProjectById(6L)).thenReturn(db);
        when(opImageMapper.selectByProjectId(6L)).thenReturn(Collections.emptyList());
        assertThrows(ServiceException.class, () -> service.publish(6L));
        verify(projectMapper, never()).updateBizCommonProsperityProject(any());
    }

    @Test
    @DisplayName("GTFY-XM-UT-018 下架成功回流")
    void ut018_offline()
    {
        BizCommonProsperityProject db = sampleRow();
        db.setId(4L);
        db.setPublishStatus(1);
        when(projectMapper.selectBizCommonProsperityProjectById(4L)).thenReturn(db);
        when(projectMapper.updateBizCommonProsperityProject(any())).thenReturn(1);
        assertEquals(1, service.offline(4L));
        verify(projectMapper).updateBizCommonProsperityProject(argThat(r ->
                r.getPublishStatus() == 0 && r.getOfflineTime() != null));
        verify(opImageMapper, never()).deleteByProjectId(any());
    }

    @Test
    @DisplayName("GTFY-XM-UT-019 未发布禁止下架")
    void ut019_offlineDraft()
    {
        BizCommonProsperityProject db = sampleRow();
        db.setId(5L);
        db.setPublishStatus(0);
        when(projectMapper.selectBizCommonProsperityProjectById(5L)).thenReturn(db);
        assertThrows(ServiceException.class, () -> service.offline(5L));
    }

    @Test
    @DisplayName("GTFY-XM-UT-020 删除未发布联动子表")
    void ut020_delete()
    {
        BizCommonProsperityProject db = sampleRow();
        db.setId(21L);
        db.setPublishStatus(0);
        when(projectMapper.selectBizCommonProsperityProjectById(21L)).thenReturn(db);
        when(opImageMapper.selectByProjectId(21L)).thenReturn(Arrays.asList(sampleImage(1), sampleImage(2)));
        when(projectMapper.deleteBizCommonProsperityProjectByIds(any())).thenReturn(1);
        assertEquals(1, service.deleteBizCommonProsperityProjectByIds(new Long[] { 21L }));
        verify(opImageMapper).deleteByProjectIds(any());
    }

    @Test
    @DisplayName("GTFY-XM-UT-021 替换运营图删旧子表")
    void ut021_updateReplaceImages()
    {
        BizCommonProsperityProject db = sampleRow();
        db.setId(10L);
        db.setPublishStatus(0);
        when(projectMapper.selectBizCommonProsperityProjectById(10L)).thenReturn(db);
        when(opImageMapper.selectByProjectId(10L)).thenReturn(Collections.singletonList(sampleImage(1)));
        when(projectMapper.updateBizCommonProsperityProject(any())).thenReturn(1);
        BizCommonProsperityProject in = sampleRow();
        in.setId(10L);
        BizCommonProsperityProjectOpImage newImg = sampleImage(2);
        newImg.setFilePath(Constants.RESOURCE_PREFIX + "/upload/new2.jpg");
        in.setOperationImages(Collections.singletonList(newImg));
        assertEquals(1, service.updateBizCommonProsperityProject(in));
        verify(opImageMapper).deleteByProjectId(10L);
        verify(opImageMapper).insertBatch(any());
    }

    @Test
    @DisplayName("GTFY-XM-UT-022 下架不删子表")
    void ut022_offlineKeepsImages()
    {
        BizCommonProsperityProject db = sampleRow();
        db.setId(7L);
        db.setPublishStatus(1);
        when(projectMapper.selectBizCommonProsperityProjectById(7L)).thenReturn(db);
        when(projectMapper.updateBizCommonProsperityProject(any())).thenReturn(1);
        service.offline(7L);
        verify(opImageMapper, never()).deleteByProjectId(any());
        verify(opImageMapper, never()).deleteByProjectIds(any());
    }

    private static BizCommonProsperityProject sampleRow()
    {
        BizCommonProsperityProject r = new BizCommonProsperityProject();
        r.setProjectName("共富项目");
        r.setProjectType(1);
        r.setIntroduction("简介");
        r.setProjectContent("内容");
        r.setImplYear(Calendar.getInstance().get(Calendar.YEAR));
        r.setOperationImages(Collections.singletonList(sampleImage(1)));
        return r;
    }

    private static BizCommonProsperityProjectOpImage sampleImage(int sortOrder)
    {
        BizCommonProsperityProjectOpImage img = new BizCommonProsperityProjectOpImage();
        img.setFileUrl("http://img");
        img.setFilePath(Constants.RESOURCE_PREFIX + "/upload/img" + sortOrder + ".jpg");
        img.setSortOrder(sortOrder);
        return img;
    }
}
