package cn.novalon.gym.manage.gateway.loadbalancer;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

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

/**
 * CustomLoadBalancer单元测试
 * 
 * 文件定义：测试自定义负载均衡器的核心功能
 * 涉及业务：轮询、随机、加权轮询、最少连接策略
 * 
 * @author 张翔
 * @date 2026-03-26
 */
class CustomLoadBalancerTest {

    private CustomLoadBalancer loadBalancer;
    private List<ServiceInstance> instances;

    @BeforeEach
    void setUp() {
        loadBalancer = new CustomLoadBalancer();

        instances = Arrays.asList(
                createInstance("host1", 8080),
                createInstance("host2", 8080),
                createInstance("host3", 8080)
        );
    }

    @Test
    void testSelectByRoundRobin() {
        ServiceInstance instance1 = loadBalancer.selectInstance(
                instances, 
                CustomLoadBalancer.LoadBalanceStrategy.ROUND_ROBIN);
        
        ServiceInstance instance2 = loadBalancer.selectInstance(
                instances, 
                CustomLoadBalancer.LoadBalanceStrategy.ROUND_ROBIN);

        assertNotNull(instance1);
        assertNotNull(instance2);
        assertNotSame(instance1, instance2);
    }

    @Test
    void testSelectByRandom() {
        ServiceInstance instance = loadBalancer.selectInstance(
                instances, 
                CustomLoadBalancer.LoadBalanceStrategy.RANDOM);

        assertNotNull(instance);
        assertTrue(instances.contains(instance));
    }

    @Test
    void testSelectByWeightedRoundRobin() {
        ServiceInstance instance = loadBalancer.selectInstance(
                instances, 
                CustomLoadBalancer.LoadBalanceStrategy.WEIGHTED_ROUND_ROBIN);

        assertNotNull(instance);
        assertTrue(instances.contains(instance));
    }

    @Test
    void testSelectByLeastConnections() {
        ServiceInstance instance = loadBalancer.selectInstance(
                instances, 
                CustomLoadBalancer.LoadBalanceStrategy.LEAST_CONNECTIONS);

        assertNotNull(instance);
        assertTrue(instances.contains(instance));
    }

    @Test
    void testSelectInstance_EmptyList() {
        ServiceInstance instance = loadBalancer.selectInstance(
                Collections.emptyList(), 
                CustomLoadBalancer.LoadBalanceStrategy.ROUND_ROBIN);

        assertNull(instance);
    }

    @Test
    void testSelectInstance_NullList() {
        ServiceInstance instance = loadBalancer.selectInstance(
                null, 
                CustomLoadBalancer.LoadBalanceStrategy.ROUND_ROBIN);

        assertNull(instance);
    }

    @Test
    void testSetWeight() {
        ServiceInstance instance = instances.get(0);
        
        loadBalancer.setWeight(instance, 5);

        assertNotNull(instance);
    }

    @Test
    void testIncrementConnection() {
        ServiceInstance instance = instances.get(0);
        
        loadBalancer.incrementConnection(instance);
        loadBalancer.incrementConnection(instance);

        assertNotNull(instance);
    }

    @Test
    void testDecrementConnection() {
        ServiceInstance instance = instances.get(0);
        
        loadBalancer.incrementConnection(instance);
        loadBalancer.incrementConnection(instance);
        loadBalancer.decrementConnection(instance);

        assertNotNull(instance);
    }

    private ServiceInstance createInstance(String host, int port) {
        return new DefaultServiceInstance(
                "service-" + host + "-" + port,
                "test-service",
                host,
                port,
                false
        );
    }
}
