package com.ecep.contract.ds.sale.service;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;

import com.ecep.contract.ds.contract.repository.SalesOrderRepository;
import com.ecep.contract.ds.contract.service.SaleOrdersService;
import com.ecep.contract.ds.customer.model.SalesOrder;
import com.ecep.contract.vo.SalesOrderVo;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * SaleOrdersService的测试类，用于验证实体-VO转换机制和缓存策略
 */
public class SaleOrdersServiceTest {

    @Mock
    private SalesOrderRepository repository;

    @InjectMocks
    private SaleOrdersService service;

    private ObjectMapper objectMapper;
    private SalesOrder mockSalesOrder;
    private SalesOrderVo expectedVo;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this);
        objectMapper = new ObjectMapper();

        // 初始化测试数据
        mockSalesOrder = new SalesOrder();
        mockSalesOrder.setId(1);
        mockSalesOrder.setCode("SO-TEST001");
        mockSalesOrder.setMakerDate(LocalDate.now());
        mockSalesOrder.setVerifierDate(LocalDate.now().plusDays(7));

        expectedVo = new SalesOrderVo();
        expectedVo.setId(1);
        expectedVo.setCode("SO-TEST001");
        expectedVo.setMakerDate(mockSalesOrder.getMakerDate());
    }

    /**
     * 测试findById方法，验证实体-VO转换
     */
    @Test
    public void testFindById() {
        // 配置mock行为
        when(repository.findById(1)).thenReturn(Optional.of(mockSalesOrder));

        // 执行方法
        SalesOrderVo result = service.findById(1);

        // 验证结果
        assertNotNull(result);
        assertEquals(expectedVo.getId(), result.getId());
        assertEquals(expectedVo.getCode(), result.getCode());

        // 验证方法调用
        verify(repository, times(1)).findById(1);
    }

    /**
     * 测试findById方法，验证当实体不存在时返回null
     */
    @Test
    public void testFindById_EntityNotFound() {
        // 配置mock行为
        when(repository.findById(999)).thenReturn(Optional.empty());

        // 执行方法
        SalesOrderVo result = service.findById(999);

        // 验证结果
        assertNull(result);

        // 验证方法调用
        verify(repository, times(1)).findById(999);
    }

    /**
     * 测试save方法，验证保存逻辑
     */
    @Test
    public void testSave() {
        // 配置mock行为
        when(repository.save(any(SalesOrder.class))).thenReturn(mockSalesOrder);

        // 执行方法
        SalesOrder result = service.save(mockSalesOrder);

        // 验证结果
        assertNotNull(result);
        assertEquals(mockSalesOrder.getId(), result.getId());

        // 验证方法调用
        verify(repository, times(1)).save(mockSalesOrder);
    }

    /**
     * 测试delete方法，验证删除逻辑
     */
    @Test
    public void testDelete() {
        // 执行方法
        service.delete(mockSalesOrder);

        // 验证方法调用
        verify(repository, times(1)).delete(mockSalesOrder);
    }

    /**
     * 测试findAll方法，验证分页功能
     */
    @Test
    public void testFindAll() {
        // 准备测试数据
        List<SalesOrder> salesOrders = Arrays.asList(mockSalesOrder);
        Pageable pageable = PageRequest.of(0, 10);
        Page<SalesOrder> pageResult = new PageImpl<>(salesOrders, pageable, salesOrders.size());

        // 配置mock行为
        when(repository.findAll(pageable)).thenReturn(pageResult);

        // 执行方法 - 修改为正确的方法调用
        Page<SalesOrderVo> result = service.findAll((JsonNode) null, pageable);

        // 验证结果
        assertNotNull(result);
        assertEquals(1, result.getTotalElements());

        // 验证方法调用
        verify(repository, times(1)).findAll(pageable);
    }

    /**
     * 测试带参数的findAll方法，验证参数处理
     */
    @Test
    public void testFindAll_WithParams() throws Exception {
        // 准备测试数据
        List<SalesOrder> salesOrders = Arrays.asList(mockSalesOrder);
        Pageable pageable = PageRequest.of(0, 10);
        Page<SalesOrder> pageResult = new PageImpl<>(salesOrders, pageable, salesOrders.size());

        // 创建带搜索参数的JSON
        String paramsJson = "{\"searchText\": \"测试\"}";
        JsonNode paramsNode = objectMapper.readTree(paramsJson);

        // 配置mock行为
        when(repository.findAll(any(Specification.class), eq(pageable))).thenReturn(pageResult);

        // 执行方法
        Page<SalesOrderVo> result = service.findAll(paramsNode, pageable);

        // 验证结果
        assertNotNull(result);
        assertEquals(1, result.getTotalElements());

        // 验证方法调用
        verify(repository, times(1)).findAll(any(Specification.class), eq(pageable));
    }
}