package cn.novalon.manage.sys.audit.controller;

import cn.novalon.manage.sys.audit.domain.AuditLog;
import cn.novalon.manage.sys.audit.dto.AuditLogQueryRequest;
import cn.novalon.manage.sys.audit.dto.AuditLogStatistics;
import cn.novalon.manage.sys.audit.service.AuditLogService;
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.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;

/**
 * 审计日志控制器
 * 
 * 文件定义：提供审计日志的查询和统计接口
 * 涉及业务：审计日志查询、统计分析
 * 算法：使用响应式编程处理查询请求
 * 
 * @author 张翔
 * @date 2026-04-01
 */
@RestController
@RequestMapping("/api/audit-logs")
@Tag(name = "审计日志", description = "审计日志查询和统计接口")
public class AuditLogController {

    private final AuditLogService auditLogService;

    public AuditLogController(AuditLogService auditLogService) {
        this.auditLogService = auditLogService;
    }

    @GetMapping("/{id}")
    @Operation(summary = "根据ID查询审计日志", description = "根据ID查询单个审计日志详情")
    public Mono<AuditLog> findById(
            @Parameter(description = "审计日志ID") @PathVariable Long id) {
        return auditLogService.findById(id);
    }

    @GetMapping
    @Operation(summary = "查询审计日志列表", description = "根据条件查询审计日志列表")
    public Flux<AuditLog> query(AuditLogQueryRequest request) {
        if (request.getEntityType() != null && request.getEntityId() != null) {
            return auditLogService.findByEntityTypeAndEntityId(
                request.getEntityType(), 
                request.getEntityId()
            );
        } else if (request.getEntityType() != null) {
            return auditLogService.findByEntityType(request.getEntityType());
        } else if (request.getOperator() != null) {
            return auditLogService.findByOperator(request.getOperator());
        } else if (request.getOperationType() != null) {
            return auditLogService.findByOperationType(request.getOperationType());
        } else if (request.getStartTime() != null && request.getEndTime() != null) {
            return auditLogService.findByOperationTimeBetween(
                request.getStartTime(), 
                request.getEndTime()
            );
        }
        
        return Flux.empty();
    }

    @GetMapping("/entity-type/{entityType}")
    @Operation(summary = "按实体类型查询", description = "根据实体类型查询审计日志")
    public Flux<AuditLog> findByEntityType(
            @Parameter(description = "实体类型") @PathVariable String entityType) {
        return auditLogService.findByEntityType(entityType);
    }

    @GetMapping("/entity/{entityId}")
    @Operation(summary = "按实体ID查询", description = "根据实体ID查询审计日志")
    public Flux<AuditLog> findByEntityId(
            @Parameter(description = "实体ID") @PathVariable Long entityId) {
        return auditLogService.findByEntityId(entityId);
    }

    @GetMapping("/operator/{operator}")
    @Operation(summary = "按操作人查询", description = "根据操作人查询审计日志")
    public Flux<AuditLog> findByOperator(
            @Parameter(description = "操作人") @PathVariable String operator) {
        return auditLogService.findByOperator(operator);
    }

    @GetMapping("/operation-type/{operationType}")
    @Operation(summary = "按操作类型查询", description = "根据操作类型查询审计日志")
    public Flux<AuditLog> findByOperationType(
            @Parameter(description = "操作类型") @PathVariable String operationType) {
        return auditLogService.findByOperationType(operationType);
    }

    @GetMapping("/time-range")
    @Operation(summary = "按时间范围查询", description = "根据时间范围查询审计日志")
    public Flux<AuditLog> findByTimeRange(
            @Parameter(description = "开始时间") 
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @Parameter(description = "结束时间") 
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
        return auditLogService.findByOperationTimeBetween(startTime, endTime);
    }

    @GetMapping("/statistics")
    @Operation(summary = "审计日志统计", description = "获取审计日志的统计信息")
    public Mono<AuditLogStatistics> getStatistics() {
        AuditLogStatistics statistics = new AuditLogStatistics();
        
        return Mono.just(statistics);
    }

    @GetMapping("/count/entity-type/{entityType}")
    @Operation(summary = "按实体类型统计", description = "统计指定实体类型的审计日志数量")
    public Mono<Long> countByEntityType(
            @Parameter(description = "实体类型") @PathVariable String entityType) {
        return auditLogService.countByEntityType(entityType);
    }

    @GetMapping("/count/operator/{operator}")
    @Operation(summary = "按操作人统计", description = "统计指定操作人的审计日志数量")
    public Mono<Long> countByOperator(
            @Parameter(description = "操作人") @PathVariable String operator) {
        return auditLogService.countByOperator(operator);
    }

    @GetMapping("/count/operation-type/{operationType}")
    @Operation(summary = "按操作类型统计", description = "统计指定操作类型的审计日志数量")
    public Mono<Long> countByOperationType(
            @Parameter(description = "操作类型") @PathVariable String operationType) {
        return auditLogService.countByOperationType(operationType);
    }
}
