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

import cn.novalon.gym.manage.sys.core.domain.SysMenu;
import cn.novalon.gym.manage.sys.core.service.ISysMenuService;
import cn.novalon.gym.manage.sys.dto.request.MenuCreateRequest;
import cn.novalon.gym.manage.sys.dto.request.MenuUpdateRequest;
import cn.novalon.gym.manage.sys.core.command.CreateMenuCommand;
import cn.novalon.gym.manage.sys.core.command.UpdateMenuCommand;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import cn.novalon.gym.manage.sys.audit.OperationLog;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

/**
 * 系统菜单处理器
 * 
 * @author 张翔
 * @date 2026-03-14
 */
@Component
@Tag(name = "菜单管理", description = "系统菜单相关操作")
public class MenuHandler {

    private final ISysMenuService menuService;

    public MenuHandler(ISysMenuService menuService) {
        this.menuService = menuService;
    }

    @Operation(summary = "获取所有菜单", description = "获取系统中所有菜单列表")
    public Mono<ServerResponse> getAllMenus(ServerRequest request) {
        return ServerResponse.ok()
                .body(menuService.findAll(), SysMenu.class);
    }

    @Operation(summary = "根据ID获取菜单", description = "根据菜单ID获取菜单详细信息")
    public Mono<ServerResponse> getMenuById(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return menuService.findById(id)
                .flatMap(menu -> ServerResponse.ok().bodyValue(menu))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @Operation(summary = "获取菜单树", description = "获取系统菜单树结构")
    public Mono<ServerResponse> getMenuTree(ServerRequest request) {
        return ServerResponse.ok()
                .body(menuService.buildMenuTree(menuService.findAll()), SysMenu.class);
    }

    @Operation(summary = "根据父菜单获取子菜单", description = "根据父菜单ID获取子菜单列表")
    public Mono<ServerResponse> getMenusByParent(ServerRequest request) {
        Long parentId = request.queryParam("parentId")
                .map(Long::valueOf)
                .orElse(0L);
        return ServerResponse.ok()
                .body(menuService.findByParentId(parentId), SysMenu.class);
    }

    @Operation(summary = "根据类型获取菜单", description = "根据菜单类型获取菜单列表")
    public Mono<ServerResponse> getMenusByType(ServerRequest request) {
        String menuType = request.queryParam("menuType").orElse(null);
        return ServerResponse.ok()
                .body(menuService.findAll().filter(menu -> menuType == null || menuType.equals(menu.getMenuType())), SysMenu.class);
    }

    @Operation(summary = "创建菜单", description = "创建新菜单")
    @OperationLog(operation = "创建菜单", module = "菜单管理")
    public Mono<ServerResponse> createMenu(ServerRequest request) {
        return request.bodyToMono(MenuCreateRequest.class)
                .map(req -> CreateMenuCommand.of(
                        req.getParentId(),
                        req.getMenuName(),
                        req.getMenuType(),
                        req.getOrderNum(),
                        req.getComponent(),
                        req.getPerms(),
                        req.getStatus()
                ))
                .flatMap(menuService::createMenu)
                .flatMap(menu -> ServerResponse.status(HttpStatus.CREATED).bodyValue(menu));
    }

    @Operation(summary = "更新菜单", description = "更新菜单信息")
    @OperationLog(operation = "更新菜单", module = "菜单管理")
    public Mono<ServerResponse> updateMenu(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return request.bodyToMono(MenuUpdateRequest.class)
                .map(req -> UpdateMenuCommand.of(
                        id,
                        req.getParentId(),
                        req.getMenuName(),
                        req.getMenuType(),
                        req.getOrderNum(),
                        req.getComponent(),
                        req.getPerms(),
                        req.getStatus()
                ))
                .flatMap(menuService::updateMenu)
                .flatMap(menu -> ServerResponse.ok().bodyValue(menu))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @Operation(summary = "删除菜单", description = "删除指定菜单")
    @OperationLog(operation = "删除菜单", module = "菜单管理")
    public Mono<ServerResponse> deleteMenu(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return menuService.deleteMenu(id)
                .then(ServerResponse.noContent().build());
    }
}