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

import cn.novalon.gym.manage.sys.core.domain.SysLoginLog;
import cn.novalon.gym.manage.sys.core.domain.SysExceptionLog;
import cn.novalon.gym.manage.sys.core.service.ISysLoginLogService;
import cn.novalon.gym.manage.sys.core.service.ISysExceptionLogService;
import cn.novalon.gym.manage.common.dto.PageRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
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 SysLogHandler {

    private final ISysLoginLogService loginLogService;
    private final ISysExceptionLogService exceptionLogService;

    public SysLogHandler(ISysLoginLogService loginLogService, ISysExceptionLogService exceptionLogService) {
        this.loginLogService = loginLogService;
        this.exceptionLogService = exceptionLogService;
    }

    @Operation(summary = "获取所有登录日志", description = "获取系统中所有登录日志列表")
    public Mono<ServerResponse> getAllLoginLogs(ServerRequest request) {
        return ServerResponse.ok()
                .body(loginLogService.findAll(), SysLoginLog.class);
    }

    @Operation(summary = "根据ID获取登录日志", description = "根据登录日志ID获取详细信息")
    public Mono<ServerResponse> getLoginLogById(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return loginLogService.findById(id)
                .flatMap(log -> ServerResponse.ok().bodyValue(log))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @Operation(summary = "创建登录日志", description = "创建新的登录日志")
    public Mono<ServerResponse> createLoginLog(ServerRequest request) {
        return request.bodyToMono(SysLoginLog.class)
                .flatMap(loginLogService::save)
                .flatMap(log -> ServerResponse.status(HttpStatus.CREATED).bodyValue(log));
    }

    @Operation(summary = "分页获取登录日志", description = "根据分页参数获取登录日志列表")
    public Mono<ServerResponse> getLoginLogsByPage(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("loginTime");
        String order = request.queryParam("order").orElse("desc");
        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 loginLogService.findLoginLogsByPage(pageRequest)
                .flatMap(response -> ServerResponse.ok().bodyValue(response));
    }

    @Operation(summary = "获取登录日志总数", description = "获取系统中登录日志总数")
    public Mono<ServerResponse> getLoginLogCount(ServerRequest request) {
        return loginLogService.count()
                .flatMap(count -> ServerResponse.ok().bodyValue(count));
    }

    @Operation(summary = "获取今日登录次数", description = "获取今日登录次数统计")
    public Mono<ServerResponse> getTodayLoginCount(ServerRequest request) {
        return loginLogService.countToday()
                .flatMap(count -> ServerResponse.ok().bodyValue(count));
    }

    @Operation(summary = "获取最近登录日志", description = "获取最近N条登录日志记录")
    public Mono<ServerResponse> getRecentLoginLogs(ServerRequest request) {
        int limit = Integer.parseInt(request.queryParam("limit").orElse("10"));
        return ServerResponse.ok()
                .body(loginLogService.findRecent(limit), SysLoginLog.class);
    }

    @Operation(summary = "获取所有异常日志", description = "获取系统中所有异常日志列表")
    public Mono<ServerResponse> getAllExceptionLogs(ServerRequest request) {
        return ServerResponse.ok()
                .body(exceptionLogService.findAll(), SysExceptionLog.class);
    }

    @Operation(summary = "根据ID获取异常日志", description = "根据异常日志ID获取详细信息")
    public Mono<ServerResponse> getExceptionLogById(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return exceptionLogService.findById(id)
                .flatMap(log -> ServerResponse.ok().bodyValue(log))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @Operation(summary = "创建异常日志", description = "创建新的异常日志")
    public Mono<ServerResponse> createExceptionLog(ServerRequest request) {
        return request.bodyToMono(SysExceptionLog.class)
                .flatMap(exceptionLogService::save)
                .flatMap(log -> ServerResponse.status(HttpStatus.CREATED).bodyValue(log));
    }

    @Operation(summary = "分页获取异常日志", description = "根据分页参数获取异常日志列表")
    public Mono<ServerResponse> getExceptionLogsByPage(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("desc");
        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 exceptionLogService.findExceptionLogsByPage(pageRequest)
                .flatMap(response -> ServerResponse.ok().bodyValue(response));
    }

    @Operation(summary = "获取异常日志总数", description = "获取系统中异常日志总数")
    public Mono<ServerResponse> getExceptionLogCount(ServerRequest request) {
        return exceptionLogService.count()
                .flatMap(count -> ServerResponse.ok().bodyValue(count));
    }
}