package com.ruoyi.ccdi.project.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.project.domain.CcdiProject;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectEmployeeCreditNegativeQueryDTO;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectEmployeeCreditNegativeExcel;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeCreditNegativeItemVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeCreditNegativePageVO;
import com.ruoyi.ccdi.project.mapper.CcdiBankTagResultMapper;
import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper;
import com.ruoyi.ccdi.project.mapper.CcdiProjectOverviewEmployeeResultMapper;
import com.ruoyi.ccdi.project.mapper.CcdiProjectOverviewMapper;
import com.ruoyi.common.exception.ServiceException;
import java.math.BigDecimal;
import java.util.List;
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 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.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class CcdiProjectOverviewServiceEmployeeCreditNegativeTest {

    @InjectMocks
    private CcdiProjectOverviewServiceImpl service;

    @Mock
    private CcdiProjectOverviewMapper overviewMapper;

    @Mock
    private CcdiProjectMapper projectMapper;

    @Mock
    private CcdiProjectOverviewEmployeeResultMapper overviewEmployeeResultMapper;

    @Mock
    private CcdiBankTagResultMapper bankTagResultMapper;

    @Mock
    private CcdiProjectOverviewEmployeeResultBuilder overviewEmployeeResultBuilder;

    @Test
    void shouldReturnEmployeeCreditNegativePage() {
        CcdiProject project = new CcdiProject();
        project.setProjectId(40L);
        when(projectMapper.selectById(40L)).thenReturn(project);

        CcdiProjectEmployeeCreditNegativeItemVO item = new CcdiProjectEmployeeCreditNegativeItemVO();
        item.setPersonName("李四");
        item.setPersonId("330000000000000001");
        item.setQueryDate("2026-03-20");
        item.setCivilCnt(1);
        item.setCivilLmt(new BigDecimal("10000.00"));

        Page<CcdiProjectEmployeeCreditNegativeItemVO> page = new Page<>(1, 5);
        page.setRecords(List.of(item));
        page.setTotal(1L);
        when(overviewMapper.selectEmployeeCreditNegativePage(any(Page.class), any(CcdiProjectEmployeeCreditNegativeQueryDTO.class)))
            .thenReturn(page);

        CcdiProjectEmployeeCreditNegativeQueryDTO queryDTO = new CcdiProjectEmployeeCreditNegativeQueryDTO();
        queryDTO.setProjectId(40L);
        queryDTO.setPageNum(1);
        queryDTO.setPageSize(5);

        CcdiProjectEmployeeCreditNegativePageVO result = service.getEmployeeCreditNegative(queryDTO);

        assertEquals(1, result.getRows().size());
        assertEquals(1L, result.getTotal());
        assertEquals("李四", result.getRows().getFirst().getPersonName());
        verify(overviewMapper).selectEmployeeCreditNegativePage(
            any(Page.class),
            argThat(query -> query.getProjectId().equals(40L))
        );
    }

    @Test
    void shouldThrowWhenEmployeeCreditNegativeProjectDoesNotExist() {
        when(projectMapper.selectById(99L)).thenReturn(null);

        CcdiProjectEmployeeCreditNegativeQueryDTO queryDTO = new CcdiProjectEmployeeCreditNegativeQueryDTO();
        queryDTO.setProjectId(99L);

        assertThrows(ServiceException.class, () -> service.getEmployeeCreditNegative(queryDTO));
    }

    @Test
    void shouldExportEmployeeCreditNegativeRows() {
        CcdiProject project = new CcdiProject();
        project.setProjectId(40L);
        when(projectMapper.selectById(40L)).thenReturn(project);

        CcdiProjectEmployeeCreditNegativeItemVO item = new CcdiProjectEmployeeCreditNegativeItemVO();
        item.setPersonName("李四");
        item.setPersonId("330000000000000001");
        item.setQueryDate("2026-03-20");
        item.setCivilCnt(1);
        item.setCivilLmt(new BigDecimal("10000.00"));
        when(overviewMapper.selectEmployeeCreditNegativeList(40L)).thenReturn(List.of(item));

        List<CcdiProjectEmployeeCreditNegativeExcel> rows = service.exportEmployeeCreditNegative(40L);

        assertEquals(1, rows.size());
        assertEquals("李四", rows.getFirst().getPersonName());
        assertEquals("330000000000000001", rows.getFirst().getPersonId());
        verify(overviewMapper).selectEmployeeCreditNegativeList(eq(40L));
    }

    @Test
    void shouldThrowWhenExportEmployeeCreditNegativeProjectDoesNotExist() {
        when(projectMapper.selectById(100L)).thenReturn(null);

        assertThrows(ServiceException.class, () -> service.exportEmployeeCreditNegative(100L));
    }
}
