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

import cn.novalon.manage.sys.core.domain.SysRole;
import cn.novalon.manage.sys.core.service.ISysRoleService;
import cn.novalon.manage.common.dto.PageRequest;
import cn.novalon.manage.sys.dto.request.RoleCreateRequest;
import cn.novalon.manage.sys.dto.request.RoleUpdateRequest;
import cn.novalon.manage.sys.core.command.CreateRoleCommand;
import cn.novalon.manage.sys.core.command.UpdateRoleCommand;
import io.swagger.v3.oas.annotations.Operation;
import cn.novalon.manage.sys.audit.OperationLog;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Validator;
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;

import java.util.HashMap;
import java.util.Map;

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

    private final ISysRoleService roleService;
    private final Validator validator;

    public SysRoleHandler(ISysRoleService roleService, Validator validator) {
        this.roleService = roleService;
        this.validator = validator;
    }

    @Operation(summary = "获取所有角色", description = "获取系统中所有角色列表")
    public Mono<ServerResponse> getAllRoles(ServerRequest request) {
        return ServerResponse.ok()
                .body(roleService.findAll(), SysRole.class);
    }

    @Operation(summary = "分页获取角色", description = "根据分页参数获取角色列表")
    public Mono<ServerResponse> getRolesByPage(ServerRequest request) {
        int page = Integer.parseInt(request.queryParam("page").orElse("0"));
        int size = Integer.parseInt(request.queryParam("size").orElse("10"));
        String sort = request.queryParam("sort").orElse("id");
        String order = request.queryParam("order").orElse("asc");
        String keyword = request.queryParam("keyword").orElse(null);

        PageRequest pageRequest = new PageRequest();
        pageRequest.setPage(page);
        pageRequest.setSize(size);
        pageRequest.setSort(sort);
        pageRequest.setOrder(order);
        pageRequest.setKeyword(keyword);

        return roleService.findRolesByPage(pageRequest)
                .flatMap(response -> ServerResponse.ok().bodyValue(response));
    }

    @Operation(summary = "获取角色总数", description = "获取系统中角色总数")
    public Mono<ServerResponse> getRoleCount(ServerRequest request) {
        return roleService.count()
                .flatMap(count -> ServerResponse.ok().bodyValue(count));
    }

    @Operation(summary = "根据角色名获取角色", description = "根据角色名称获取角色详细信息")
    public Mono<ServerResponse> getRoleByName(ServerRequest request) {
        String roleName = request.pathVariable("roleName");
        return roleService.findByRoleName(roleName)
                .flatMap(role -> ServerResponse.ok().bodyValue(role))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @Operation(summary = "检查角色名是否存在", description = "检查指定角色名是否已存在")
    public Mono<ServerResponse> checkNameExists(ServerRequest request) {
        String name = request.queryParam("name").orElse(null);
        return roleService.existsByRoleName(name)
                .flatMap(exists -> ServerResponse.ok().bodyValue(exists));
    }

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

    @Operation(summary = "创建角色", description = "创建新角色")
    @OperationLog(operation = "创建角色", module = "角色管理")
    public Mono<ServerResponse> createRole(ServerRequest request) {
        return request.bodyToMono(RoleCreateRequest.class)
                .flatMap(req -> {
                    var violations = validator.validate(req);
                    if (!violations.isEmpty()) {
                        Map<String, String> errors = new HashMap<>();
                        violations.forEach(v -> errors.put(v.getPropertyPath().toString(), v.getMessage()));
                        return ServerResponse.badRequest().bodyValue(errors);
                    }
                    
                    return Mono.just(CreateRoleCommand.of(
                            req.getRoleName(),
                            req.getRoleKey(),
                            req.getRoleSort(),
                            req.getStatus()
                    ))
                    .flatMap(roleService::createRole)
                    .flatMap(role -> ServerResponse.status(HttpStatus.CREATED).bodyValue(role));
                });
    }

    @Operation(summary = "更新角色", description = "更新角色信息")
    @OperationLog(operation = "更新角色", module = "角色管理")
    public Mono<ServerResponse> updateRole(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return request.bodyToMono(RoleUpdateRequest.class)
                .map(req -> UpdateRoleCommand.of(
                        id,
                        req.getRoleName(),
                        req.getRoleKey(),
                        req.getRoleSort(),
                        req.getStatus()
                ))
                .flatMap(roleService::updateRole)
                .flatMap(updatedRole -> ServerResponse.ok().bodyValue(updatedRole))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @Operation(summary = "删除角色", description = "逻辑删除角色")
    @OperationLog(operation = "删除角色", module = "角色管理")
    public Mono<ServerResponse> deleteRole(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return roleService.logicalDeleteRole(id)
                .flatMap(role -> ServerResponse.ok().bodyValue(role))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @Operation(summary = "恢复角色", description = "恢复被逻辑删除的角色")
    public Mono<ServerResponse> restoreRole(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return roleService.restoreRole(id)
                .flatMap(role -> ServerResponse.ok().bodyValue(role))
                .switchIfEmpty(ServerResponse.notFound().build());
    }
}
