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

import cn.novalon.manage.sys.core.domain.SysMenu;
import cn.novalon.manage.sys.core.service.ISysMenuService;
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.when;

@ExtendWith(MockitoExtension.class)
class MenuHandlerDataIntegrityTest {

    @Mock
    private ISysMenuService menuService;

    private MenuHandler menuHandler;

    @BeforeEach
    void setUp() {
        menuHandler = new MenuHandler(menuService);
    }

    @Test
    void testGetAllMenus_EmptyDatabase() {
        when(menuService.findAll()).thenReturn(Flux.empty());
        
        ServerRequest request = MockServerRequest.builder().build();
        Mono<ServerResponse> response = menuHandler.getAllMenus(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
    }

    @Test
    void testGetAllMenus_WithSystemManagementMenus() {
        SysMenu systemMenu = new SysMenu();
        systemMenu.setId(1L);
        systemMenu.setParentId(0L);
        systemMenu.setMenuName("系统管理");
        systemMenu.setMenuType("M");
        systemMenu.setOrderNum(1);
        systemMenu.setStatus(1);
        systemMenu.setCreatedAt(LocalDateTime.now());
        systemMenu.setUpdatedAt(LocalDateTime.now());
        
        SysMenu userMenu = new SysMenu();
        userMenu.setId(11L);
        userMenu.setParentId(1L);
        userMenu.setMenuName("用户管理");
        userMenu.setMenuType("C");
        userMenu.setOrderNum(1);
        userMenu.setComponent("system/user/index");
        userMenu.setPerms("system:user:list");
        userMenu.setStatus(1);
        userMenu.setCreatedAt(LocalDateTime.now());
        userMenu.setUpdatedAt(LocalDateTime.now());
        
        when(menuService.findAll()).thenReturn(Flux.just(systemMenu, userMenu));
        
        ServerRequest request = MockServerRequest.builder().build();
        Mono<ServerResponse> response = menuHandler.getAllMenus(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
    }

    @Test
    void testGetMenuTree_WithEmptyDatabase() {
        when(menuService.findAll()).thenReturn(Flux.empty());
        when(menuService.buildMenuTree(any())).thenReturn(Flux.empty());
        
        ServerRequest request = MockServerRequest.builder().build();
        Mono<ServerResponse> response = menuHandler.getMenuTree(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
    }

    @Test
    void testGetMenusByParent_WithNoChildren() {
        when(menuService.findByParentId(999L)).thenReturn(Flux.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .queryParam("parentId", "999")
                .build();
        Mono<ServerResponse> response = menuHandler.getMenusByParent(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
    }

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

    @Test
    void testGetMenusByType_NoMatchingMenus() {
        SysMenu menu = new SysMenu();
        menu.setId(1L);
        menu.setMenuName("系统管理");
        menu.setMenuType("M");
        
        when(menuService.findAll()).thenReturn(Flux.just(menu));
        
        ServerRequest request = MockServerRequest.builder()
                .queryParam("menuType", "F")
                .build();
        Mono<ServerResponse> response = menuHandler.getMenusByType(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
    }
}