package com.example.demo.service;

import com.example.demo.model.LogRecord;
import jakarta.annotation.PostConstruct;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * 日志审计管理服务。
 * 使用内存假数据实现登录日志、操作日志、异常日志的记录和多条件日志溯源查询。
 */
@Service
public class LogService {

    /** 内存数据存储 */
    private final Map<Long, LogRecord> logMap = new ConcurrentHashMap<>();

    private final AtomicLong idGenerator = new AtomicLong(2000);

    /**
     * 记录登录日志。
     *
     * @requirement(name="登录日志记录", id="SRS-IMS_F-023")
     *
     * @param logRecord 登录日志信息
     * @return 记录后的日志
     */
    public LogRecord recordLoginLog(LogRecord logRecord) {
        long id = idGenerator.incrementAndGet();
        logRecord.setId(id);
        logRecord.setLogType("login");
        logRecord.setCreateTime(LocalDateTime.now());
        logMap.put(id, logRecord);
        return logRecord;
    }

    /**
     * 记录操作日志。
     *
     * @requirement(name="操作日志记录", id="SRS-IMS_F-024")
     *
     * @param logRecord 操作日志信息
     * @return 记录后的日志
     */
    public LogRecord recordOperationLog(LogRecord logRecord) {
        long id = idGenerator.incrementAndGet();
        logRecord.setId(id);
        logRecord.setLogType("operation");
        logRecord.setCreateTime(LocalDateTime.now());
        logMap.put(id, logRecord);
        return logRecord;
    }

    /**
     * 记录异常日志。
     *
     * @requirement(name="异常日志记录", id="SRS-IMS_F-025")
     *
     * @param logRecord 异常日志信息
     * @return 记录后的日志
     */
    public LogRecord recordExceptionLog(LogRecord logRecord) {
        long id = idGenerator.incrementAndGet();
        logRecord.setId(id);
        logRecord.setLogType("exception");
        logRecord.setCreateTime(LocalDateTime.now());
        logMap.put(id, logRecord);
        return logRecord;
    }

    /**
     * 多条件日志溯源查询。
     *
     * @requirement(name="日志溯源查询", id="SRS-IMS_F-026")
     * 支持按日志类型、操作人、关键字、时间范围等多条件组合查询。
     *
     * @param logType     日志类型（login/operation/exception，可选）
     * @param operatorId  操作人ID（可选）
     * @param keyword     内容关键字（可选）
     * @param startTime   开始时间（可选）
     * @param endTime     结束时间（可选）
     * @param page        页码（从0开始）
     * @param size        每页条数
     * @return 符合条件的日志列表
     */
    public List<LogRecord> queryLogs(String logType, Long operatorId, String keyword,
                                      LocalDateTime startTime, LocalDateTime endTime,
                                      int page, int size) {
        List<LogRecord> allLogs = new ArrayList<>(logMap.values());

        if (logType != null && !logType.isBlank()) {
            allLogs = allLogs.stream()
                    .filter(log -> logType.equals(log.getLogType()))
                    .collect(Collectors.toList());
        }
        if (operatorId != null) {
            allLogs = allLogs.stream()
                    .filter(log -> operatorId.equals(log.getOperatorId()))
                    .collect(Collectors.toList());
        }
        if (keyword != null && !keyword.isBlank()) {
            String kw = keyword.toLowerCase();
            allLogs = allLogs.stream()
                    .filter(log -> (log.getContent() != null && log.getContent().toLowerCase().contains(kw))
                            || (log.getOperatorName() != null && log.getOperatorName().toLowerCase().contains(kw)))
                    .collect(Collectors.toList());
        }
        if (startTime != null) {
            allLogs = allLogs.stream()
                    .filter(log -> log.getCreateTime() != null && !log.getCreateTime().isBefore(startTime))
                    .collect(Collectors.toList());
        }
        if (endTime != null) {
            allLogs = allLogs.stream()
                    .filter(log -> log.getCreateTime() != null && !log.getCreateTime().isAfter(endTime))
                    .collect(Collectors.toList());
        }

        // 按时间倒序
        allLogs.sort((a, b) -> b.getCreateTime().compareTo(a.getCreateTime()));

        int start = page * size;
        if (start >= allLogs.size()) {
            return List.of();
        }
        int end = Math.min(start + size, allLogs.size());
        return allLogs.subList(start, end);
    }

    /**
     * 初始化默认日志数据。
     */
    @PostConstruct
    public void initDefaultLogs() {
        if (logMap.isEmpty()) {
            LogRecord loginLog = new LogRecord(1L, "login", 1L, "admin",
                    "用户登录系统", "192.168.1.100", "success", null);
            loginLog.setCreateTime(LocalDateTime.now().minusHours(2));
            logMap.put(1L, loginLog);

            LogRecord operLog = new LogRecord(2L, "operation", 1L, "admin",
                    "新增业务数据：年度预算报告", "192.168.1.100", "success", null);
            operLog.setCreateTime(LocalDateTime.now().minusHours(1));
            logMap.put(2L, operLog);

            LogRecord excLog = new LogRecord(3L, "exception", 2L, "zhangsan",
                    "数据导出异常：文件生成失败", "192.168.1.101", "fail",
                    "java.io.IOException: 磁盘空间不足");
            excLog.setCreateTime(LocalDateTime.now().minusMinutes(30));
            logMap.put(3L, excLog);
        }
    }
}
