package com.stdproject.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.common.OperationLog;
import com.stdproject.common.PageRequest;
import com.stdproject.common.Result;
import com.stdproject.entity.AppOptLog;
import com.stdproject.service.IAppOptLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 应用-操作日志表 前端控制器
 * </p>
 *
 * @author StdProject
 * @since 2023-12-07
 */
@Tag(name = "操作日志管理", description = "操作日志查询、操作日志删除等功能")
@RestController
@RequestMapping("/api/optlog")
public class AppOptLogController {

    @Autowired
    private IAppOptLogService appOptLogService;

    @Operation(summary = "分页查询操作日志列表")
    @PostMapping("/page")
    @OperationLog(type = "06", module = "操作日志管理", description = "分页查询操作日志列表")
    public Result<IPage<AppOptLog>> page(@RequestBody @Valid PageRequest pageRequest) {
        Page<AppOptLog> page = new Page<>(pageRequest.getCurrent(), pageRequest.getSize());
        QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
        
        // 关键字搜索
        if (StringUtils.hasText(pageRequest.getKeyword())) {
            queryWrapper.and(wrapper -> wrapper
                .like("username", pageRequest.getKeyword())
                .or().like("module", pageRequest.getKeyword())
                .or().like("description", pageRequest.getKeyword())
            );
        }
        
        // 排序
        if (StringUtils.hasText(pageRequest.getOrderBy())) {
            if ("asc".equalsIgnoreCase(pageRequest.getOrderDirection())) {
                queryWrapper.orderByAsc(pageRequest.getOrderBy());
            } else {
                queryWrapper.orderByDesc(pageRequest.getOrderBy());
            }
        } else {
            queryWrapper.orderByDesc("logtime");
        }
        
        IPage<AppOptLog> result = appOptLogService.page(page, queryWrapper);
        return Result.success(result);
    }

    @Operation(summary = "根据ID查询操作日志详情")
    @GetMapping("/{id}")
    @OperationLog(type = "06", module = "操作日志管理", description = "查询操作日志详情")
    public Result<AppOptLog> getById(@Parameter(description = "日志ID") @PathVariable String id) {
        AppOptLog optLog = appOptLogService.getById(id);
        return Result.success(optLog);
    }

    @Operation(summary = "根据用户名查询操作日志")
    @GetMapping("/user/{username}")
    @OperationLog(type = "06", module = "操作日志管理", description = "根据用户名查询操作日志")
    public Result<List<AppOptLog>> getByUsername(
            @Parameter(description = "用户名") @PathVariable String username,
            @Parameter(description = "限制条数") @RequestParam(defaultValue = "100") Integer limit) {
        QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        queryWrapper.orderByDesc("logtime");
        queryWrapper.last("LIMIT " + limit);
        
        List<AppOptLog> logs = appOptLogService.list(queryWrapper);
        return Result.success(logs);
    }

    @Operation(summary = "根据操作类型查询操作日志")
    @GetMapping("/type/{type}")
    @OperationLog(type = "06", module = "操作日志管理", description = "根据操作类型查询操作日志")
    public Result<List<AppOptLog>> getByType(
            @Parameter(description = "操作类型") @PathVariable String type,
            @Parameter(description = "限制条数") @RequestParam(defaultValue = "100") Integer limit) {
        QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type", type);
        queryWrapper.orderByDesc("logtime");
        queryWrapper.last("LIMIT " + limit);
        
        List<AppOptLog> logs = appOptLogService.list(queryWrapper);
        return Result.success(logs);
    }

    @Operation(summary = "根据模块查询操作日志")
    @GetMapping("/module/{module}")
    @OperationLog(type = "06", module = "操作日志管理", description = "根据模块查询操作日志")
    public Result<List<AppOptLog>> getByModule(
            @Parameter(description = "模块名称") @PathVariable String module,
            @Parameter(description = "限制条数") @RequestParam(defaultValue = "100") Integer limit) {
        QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("module", module);
        queryWrapper.orderByDesc("opttime");
        queryWrapper.last("LIMIT " + limit);
        
        List<AppOptLog> logs = appOptLogService.list(queryWrapper);
        return Result.success(logs);
    }

    @Operation(summary = "根据时间范围查询操作日志")
    @GetMapping("/time-range")
    @OperationLog(type = "06", module = "操作日志管理", description = "根据时间范围查询操作日志")
    public Result<List<AppOptLog>> getByTimeRange(
            @Parameter(description = "开始时间") @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
            @Parameter(description = "限制条数") @RequestParam(defaultValue = "1000") Integer limit) {
        QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("opttime", startTime, endTime);
        queryWrapper.orderByDesc("opttime");
        queryWrapper.last("LIMIT " + limit);
        
        List<AppOptLog> logs = appOptLogService.list(queryWrapper);
        return Result.success(logs);
    }

    @Operation(summary = "根据IP地址查询操作日志")
    @GetMapping("/ip/{ip}")
    @OperationLog(type = "06", module = "操作日志管理", description = "根据IP地址查询操作日志")
    public Result<List<AppOptLog>> getByIp(
            @Parameter(description = "IP地址") @PathVariable String ip,
            @Parameter(description = "限制条数") @RequestParam(defaultValue = "100") Integer limit) {
        QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ip", ip);
        queryWrapper.orderByDesc("opttime");
        queryWrapper.last("LIMIT " + limit);
        
        List<AppOptLog> logs = appOptLogService.list(queryWrapper);
        return Result.success(logs);
    }

    
    @Operation(summary = "删除操作日志")
    @DeleteMapping("/{id}")
    @OperationLog(type = "03", module = "操作日志管理", description = "删除操作日志")
    public Result<String> delete(@Parameter(description = "日志ID") @PathVariable String id) {
        boolean success = appOptLogService.removeById(id);
        return success ? Result.success("删除成功") : Result.error("删除失败");
    }

    @Operation(summary = "批量删除操作日志")
    @DeleteMapping("/batch")
    @OperationLog(type = "03", module = "操作日志管理", description = "批量删除操作日志")
    public Result<String> deleteBatch(@RequestBody List<String> ids) {
        boolean success = appOptLogService.removeByIds(ids);
        return success ? Result.success("批量删除成功") : Result.error("批量删除失败");
    }

    @Operation(summary = "清理指定天数前的操作日志")
    @DeleteMapping("/clean/{days}")
    @OperationLog(type = "03", module = "操作日志管理", description = "清理历史操作日志")
    public Result<String> cleanOldLogs(@Parameter(description = "保留天数") @PathVariable Integer days) {
        LocalDateTime cutoffTime = LocalDateTime.now().minusDays(days);
        QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.lt("logtime", cutoffTime);
        
        boolean success = appOptLogService.remove(queryWrapper);
        return success ? Result.success("清理成功") : Result.error("清理失败");
    }

    @Operation(summary = "获取操作日志统计信息")
    @GetMapping("/statistics")
    @OperationLog(type = "06", module = "操作日志管理", description = "获取操作日志统计信息")
    public Result<LogStatistics> getStatistics() {
        // 总日志数
        long totalCount = appOptLogService.count();
        
        // 今日日志数
        LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        QueryWrapper<AppOptLog> todayQuery = new QueryWrapper<>();
        todayQuery.ge("opttime", todayStart);
        long todayCount = appOptLogService.count(todayQuery);
        
        // 本周日志数
        LocalDateTime weekStart = LocalDateTime.now().minusDays(7);
        QueryWrapper<AppOptLog> weekQuery = new QueryWrapper<>();
        weekQuery.ge("logtime", weekStart);
        long weekCount = appOptLogService.count(weekQuery);
        
        // 本月日志数
        LocalDateTime monthStart = LocalDateTime.now().minusDays(30);
        QueryWrapper<AppOptLog> monthQuery = new QueryWrapper<>();
        monthQuery.ge("logtime", monthStart);
        long monthCount = appOptLogService.count(monthQuery);
        
        LogStatistics statistics = new LogStatistics();
        statistics.setTotalCount(totalCount);
        statistics.setTodayCount(todayCount);
        statistics.setWeekCount(weekCount);
        statistics.setMonthCount(monthCount);
        
        return Result.success(statistics);
    }

    @Operation(summary = "获取最近的操作日志")
    @GetMapping("/recent")
    @OperationLog(type = "06", module = "操作日志管理", description = "获取最近的操作日志")
    public Result<List<AppOptLog>> getRecentLogs(
            @Parameter(description = "限制条数") @RequestParam(defaultValue = "50") Integer limit) {
        QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("logtime");
        queryWrapper.last("LIMIT " + limit);
        
        List<AppOptLog> logs = appOptLogService.list(queryWrapper);
        return Result.success(logs);
    }

    /**
     * 日志统计信息
     */
    public static class LogStatistics {
        private Long totalCount;
        private Long todayCount;
        private Long weekCount;
        private Long monthCount;

        public Long getTotalCount() { return totalCount; }
        public void setTotalCount(Long totalCount) { this.totalCount = totalCount; }
        public Long getTodayCount() { return todayCount; }
        public void setTodayCount(Long todayCount) { this.todayCount = todayCount; }
        public Long getWeekCount() { return weekCount; }
        public void setWeekCount(Long weekCount) { this.weekCount = weekCount; }
        public Long getMonthCount() { return monthCount; }
        public void setMonthCount(Long monthCount) { this.monthCount = monthCount; }
    }
}