package com.zsc.edu.gateway.service.iot;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zsc.edu.gateway.domain.iot.ProductBuilder;
import com.zsc.edu.gateway.exception.ConstraintException;
import com.zsc.edu.gateway.modules.iot.product.dto.ProductDto;
import com.zsc.edu.gateway.modules.iot.product.entity.Product;
import com.zsc.edu.gateway.modules.iot.product.repo.ProductRepository;
import com.zsc.edu.gateway.modules.iot.product.service.ProductService;
import com.zsc.edu.gateway.modules.iot.tsl.dto.ParamDto;
import com.zsc.edu.gateway.modules.iot.tsl.entity.DataType;
import com.zsc.edu.gateway.modules.iot.tsl.entity.Param;
import com.zsc.edu.gateway.modules.iot.tsl.repo.ParamRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
public class ProductServiceTest {
    @Autowired
    private ProductService service;
    @Autowired
    private ProductRepository repo;
    @Autowired
    private ParamRepository paramRepository;

    private Product product1;
    private Product product2;

    @BeforeEach
    void setUp() {
        product1 = ProductBuilder.bProduct().name("PRODUCT_NAME_1").productType("测试1").link(Product.LinkType.TCP).build();
        repo.insert(product1);
        product2 = ProductBuilder.bProduct().name("PRODUCT_NAME_2").productType("测试2").link(Product.LinkType.TCP).build();
        repo.insert(product2);
    }

    @AfterEach
    void tearDown() {
        repo.delete(new LambdaQueryWrapper<Product>()
                .in(Product::getName, "PRODUCT_NAME_1", "PRODUCT_NAME_2", "PRODUCT_NAME_3", "PRODUCT_UPDATE"));
        paramRepository.delete(new LambdaQueryWrapper<Param>()
                .in(Param::getName, "联合测试"));
    }

    @Test
    void list() {
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
        assertEquals(2, service.list(queryWrapper.like(Product::getName, "PRODUCT")).size());
        assertEquals(1, service.list(queryWrapper.eq(Product::getName, product1.getName())).size());
//        assertEquals(2, service.list().size());
    }

    @Test
    void createProduct() {
        ProductDto dto = new ProductDto("PRODUCT_NAME_3", "测试3", "测试3", Product.LinkType.TCP, createParam(), "备注1");
        Product product = service.create(dto);
        assertNotNull(product);
        List<Product> Products = service.list(new LambdaQueryWrapper<Product>().like(Product::getName, "PRODUCT"));
        assertEquals(3, Products.size());
        // 不能创建其他已存在的同名同代码部门
        ProductDto dto2 = new ProductDto(product2.getName(), "测试1", "测试1", Product.LinkType.TCP, null, "备注1");
        assertThrows(ConstraintException.class, () -> service.create(dto2));
    }

    @Test
    void updateProduct() {
        ProductDto dto = new ProductDto();
        dto.setName("PRODUCT_UPDATE");
        dto.setProductType("测试更新");
        dto.setModel("测试更新");
        dto.setLink(Product.LinkType.TCP);
        dto.setParams(null);
        dto.setParams(createParam());
        service.update(dto, product2.getId());
        Product updatedProduct = repo.selectOne(new LambdaQueryWrapper<Product>().eq(Product::getName, dto.getName()));
        assertNotNull(updatedProduct);
        assertEquals("PRODUCT_UPDATE", updatedProduct.getName());
        assertEquals(product2.getId(), updatedProduct.getId());
    }

    public List<ParamDto> createParam() {
        ParamDto paramDto = new ParamDto();
        paramDto.setName("联合测试");
        paramDto.setType(Param.Type.OUTPUT);
        paramDto.setDataType(DataType.DATE);
        List<ParamDto> params = new ArrayList<>();
        params.add(paramDto);
        return params;
    }
}
