package com.ylx.massage.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.ylx.common.exception.ServiceException;
import com.ylx.massage.domain.MaProject;
import com.ylx.massage.domain.dto.MaProjectUpdateEnableDTO;
import com.ylx.massage.mapper.MaProjectMapper;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.session.Configuration;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.test.util.ReflectionTestUtils;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class MaProjectServiceImplTest {

    @Test
    public void updateProjectEnableUpdatesEnabledStatusByMerchantAndProject() {
        initTableInfo();
        MaProjectMapper mapper = mock(MaProjectMapper.class);
        when(mapper.update(isNull(), any(Wrapper.class))).thenReturn(1);
        MaProjectServiceImpl service = new MaProjectServiceImpl();
        ReflectionTestUtils.setField(service, "maProjectMapper", mapper);
        MaProjectUpdateEnableDTO dto = buildDto(7, 20, 0);

        int rows = service.updateProjectEnable(dto);

        assertEquals(1, rows);
        ArgumentCaptor<Wrapper<MaProject>> wrapperCaptor = ArgumentCaptor.forClass(Wrapper.class);
        verify(mapper).update(isNull(), wrapperCaptor.capture());
        LambdaUpdateWrapper<MaProject> wrapper = (LambdaUpdateWrapper<MaProject>) wrapperCaptor.getValue();
        String sqlSegment = wrapper.getSqlSegment().toLowerCase();
        String sqlSet = wrapper.getSqlSet().toLowerCase();
        assertTrue(sqlSegment.contains("merchant"));
        assertTrue(sqlSegment.contains("project"));
        assertTrue(sqlSegment.contains("delete"));
        assertTrue(sqlSegment.contains("audit"));
        assertTrue(sqlSet.contains("project"));
        assertTrue(sqlSet.contains("enable"));
        assertTrue(sqlSet.contains("update"));
        assertTrue(wrapper.getParamNameValuePairs().containsValue(7));
        assertTrue(wrapper.getParamNameValuePairs().containsValue(20));
        assertTrue(wrapper.getParamNameValuePairs().containsValue(0));
        assertTrue(wrapper.getParamNameValuePairs().containsValue(1));
    }

    @Test
    public void updateProjectEnableRejectsInvalidEnableStatus() {
        MaProjectMapper mapper = mock(MaProjectMapper.class);
        MaProjectServiceImpl service = new MaProjectServiceImpl();
        ReflectionTestUtils.setField(service, "maProjectMapper", mapper);
        MaProjectUpdateEnableDTO dto = buildDto(7, 20, 2);

        ServiceException exception = assertThrows(ServiceException.class,
                () -> service.updateProjectEnable(dto));

        assertEquals("上下架状态参数不正确", exception.getMessage());
        verify(mapper, never()).update(any(MaProject.class), any(Wrapper.class));
    }

    @Test
    public void updateProjectEnableRejectsEmptyEnableStatus() {
        MaProjectMapper mapper = mock(MaProjectMapper.class);
        MaProjectServiceImpl service = new MaProjectServiceImpl();
        ReflectionTestUtils.setField(service, "maProjectMapper", mapper);
        MaProjectUpdateEnableDTO dto = buildDto(7, 20, null);

        ServiceException exception = assertThrows(ServiceException.class,
                () -> service.updateProjectEnable(dto));

        assertEquals("上下架状态不能为空", exception.getMessage());
        verify(mapper, never()).update(any(MaProject.class), any(Wrapper.class));
    }

    @Test
    public void updateProjectEnableRejectsMissingMerchantProject() {
        initTableInfo();
        MaProjectMapper mapper = mock(MaProjectMapper.class);
        when(mapper.update(isNull(), any(Wrapper.class))).thenReturn(0);
        MaProjectServiceImpl service = new MaProjectServiceImpl();
        ReflectionTestUtils.setField(service, "maProjectMapper", mapper);
        MaProjectUpdateEnableDTO dto = buildDto(7, 20, 1);

        ServiceException exception = assertThrows(ServiceException.class,
                () -> service.updateProjectEnable(dto));

        assertEquals("商户项目不存在或未审核通过", exception.getMessage());
    }

    private MaProjectUpdateEnableDTO buildDto(Integer merchantId, Integer projectId, Integer projectIsEnable) {
        MaProjectUpdateEnableDTO dto = new MaProjectUpdateEnableDTO();
        dto.setMerchantId(merchantId);
        dto.setProjectId(projectId);
        dto.setProjectIsEnable(projectIsEnable);
        return dto;
    }

    private void initTableInfo() {
        if (TableInfoHelper.getTableInfo(MaProject.class) == null) {
            MapperBuilderAssistant assistant = new MapperBuilderAssistant(new Configuration(), "");
            TableInfoHelper.initTableInfo(assistant, MaProject.class);
        }
    }
}
