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.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.SalesOrderItemRepository;
import com.ecep.contract.ds.contract.service.SaleOrdersService;
import com.ecep.contract.ds.contract.service.SalesOrderItemService;
import com.ecep.contract.ds.customer.model.SalesOrder;
import com.ecep.contract.ds.customer.model.SalesOrderItem;
import com.ecep.contract.vo.SalesOrderItemVo;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

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

    @Mock
    private SalesOrderItemRepository repository;

    @Mock
    private SaleOrdersService saleOrdersService;

    @InjectMocks
    private SalesOrderItemService service;

    private ObjectMapper objectMapper;
    private SalesOrderItem mockOrderItem;
    private SalesOrder mockSalesOrder;
    private SalesOrderItemVo expectedVo;

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

        // 创建模拟销售订单
        mockSalesOrder = new SalesOrder();
        mockSalesOrder.setId(1);
        mockSalesOrder.setCode("SO-TEST002");
        // 移除不存在的setName和setCreateDate方法

        // 创建模拟订单项
        mockOrderItem = new SalesOrderItem();
        mockOrderItem.setId(1);
        mockOrderItem.setName("测试订单项");
        mockOrderItem.setCode("SOI-TEST001");
        mockOrderItem.setOrder(mockSalesOrder);
        mockOrderItem.setQuantity(5);
        mockOrderItem.setPrice(100.0); // 使用setPrice而不是setUnitPrice

        // 创建预期的VO对象
        expectedVo = new SalesOrderItemVo();
        expectedVo.setId(1);
        expectedVo.setName("测试订单项");
        expectedVo.setCode("SOI-TEST001");
        expectedVo.setOrderId(1);
        expectedVo.setQuantity(5);
        expectedVo.setPrice(100.0); // 在VO中也使用price
    }

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

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

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

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

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

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

        // 验证结果
        assertNull(result);

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

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

        // 执行方法
        SalesOrderItem result = service.save(mockOrderItem);

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

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

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

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

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

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

        // 执行方法 - 使用空的JsonNode而不是null，避免空指针异常
        JsonNode emptyParamsNode = objectMapper.createObjectNode();
        Page<SalesOrderItemVo> result = service.findAll(emptyParamsNode, pageable);

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

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

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

        // 创建空的JsonNode对象
        JsonNode emptyParamsNode = null;

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

        // 执行方法 - 修改为正确的方法调用
        Page<SalesOrderItemVo> result = service.findAll(emptyParamsNode, pageRequest);

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

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

    /**
     * 测试order关联查询，验证关联实体处理功能
     */
    @Test
    public void testFindByOrderId() throws Exception {
        // 准备测试数据
        List<SalesOrderItem> orderItems = Arrays.asList(mockOrderItem);
        PageRequest pageRequest = PageRequest.of(0, 10);
        Page<SalesOrderItem> pageResult = new PageImpl<>(orderItems, pageRequest, orderItems.size());

        // 创建带orderId参数的JSON
        String paramsJson = String.format("{\"order\": %d}", mockSalesOrder.getId());
        JsonNode paramsNode = objectMapper.readTree(paramsJson);

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

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

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

        // 验证所有结果都属于指定的订单
        for (SalesOrderItemVo vo : result.getContent()) {
            assertEquals(mockSalesOrder.getId(), vo.getOrderId());
        }

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