package cn.novalon.manage.sys.handler.config;

import cn.novalon.manage.sys.core.domain.SysConfig;
import cn.novalon.manage.sys.core.service.ISysConfigService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.reactive.function.server.MockServerRequest;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;

import java.time.LocalDateTime;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class SysConfigHandlerTest {

    @Mock
    private ISysConfigService configService;

    private SysConfigHandler configHandler;
    private SysConfig testConfig;

    @BeforeEach
    void setUp() {
        configHandler = new SysConfigHandler(configService);
        
        testConfig = new SysConfig();
        testConfig.setId(1L);
        testConfig.setConfigName("系统名称");
        testConfig.setConfigKey("system.name");
        testConfig.setConfigValue("Novalon管理系统");
        testConfig.setConfigType("string");
        testConfig.setCreatedAt(LocalDateTime.now());
        testConfig.setUpdatedAt(LocalDateTime.now());
    }

    @Test
    void testGetAllConfigs() {
        when(configService.findAll()).thenReturn(Flux.just(testConfig));
        
        ServerRequest request = MockServerRequest.builder().build();
        Mono<ServerResponse> response = configHandler.getAllConfigs(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
        
        verify(configService).findAll();
    }

    @Test
    void testGetConfigById() {
        when(configService.findById(1L)).thenReturn(Mono.just(testConfig));
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "1")
                .build();
        Mono<ServerResponse> response = configHandler.getConfigById(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
        
        verify(configService).findById(1L);
    }

    @Test
    void testGetConfigById_NotFound() {
        when(configService.findById(999L)).thenReturn(Mono.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "999")
                .build();
        Mono<ServerResponse> response = configHandler.getConfigById(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(configService).findById(999L);
    }

    @Test
    void testGetConfigByKey() {
        when(configService.findByConfigKey("system.name")).thenReturn(Mono.just(testConfig));
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("configKey", "system.name")
                .build();
        Mono<ServerResponse> response = configHandler.getConfigByKey(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
        
        verify(configService).findByConfigKey("system.name");
    }

    @Test
    void testGetConfigByKey_NotFound() {
        when(configService.findByConfigKey("unknown.key")).thenReturn(Mono.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("configKey", "unknown.key")
                .build();
        Mono<ServerResponse> response = configHandler.getConfigByKey(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(configService).findByConfigKey("unknown.key");
    }

    @Test
    void testCreateConfig() {
        SysConfig newConfig = new SysConfig();
        newConfig.setConfigName("新配置");
        newConfig.setConfigKey("new.config");
        newConfig.setConfigValue("value");
        newConfig.setConfigType("string");
        
        when(configService.save(any())).thenReturn(Mono.just(testConfig));
        
        ServerRequest request = MockServerRequest.builder()
                .body(Mono.just(newConfig));
        Mono<ServerResponse> response = configHandler.createConfig(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.CREATED)
                .verifyComplete();
        
        verify(configService).save(any());
    }

    @Test
    void testUpdateConfig() {
        SysConfig updateConfig = new SysConfig();
        updateConfig.setConfigName("更新配置");
        updateConfig.setConfigValue("updated_value");
        updateConfig.setConfigType("string");
        
        when(configService.findById(1L)).thenReturn(Mono.just(testConfig));
        when(configService.save(any())).thenReturn(Mono.just(testConfig));
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "1")
                .body(Mono.just(updateConfig));
        Mono<ServerResponse> response = configHandler.updateConfig(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
        
        verify(configService).findById(1L);
        verify(configService).save(any());
    }

    @Test
    void testUpdateConfig_NotFound() {
        SysConfig updateConfig = new SysConfig();
        updateConfig.setConfigName("更新配置");
        
        when(configService.findById(999L)).thenReturn(Mono.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "999")
                .body(Mono.just(updateConfig));
        Mono<ServerResponse> response = configHandler.updateConfig(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(configService).findById(999L);
    }

    @Test
    void testDeleteConfig() {
        when(configService.deleteById(1L)).thenReturn(Mono.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "1")
                .build();
        Mono<ServerResponse> response = configHandler.deleteConfig(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NO_CONTENT)
                .verifyComplete();
        
        verify(configService).deleteById(1L);
    }
}