package com.reading.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.reading.platform.common.security.SecurityUtils;
import com.reading.platform.entity.OperationLog;
import com.reading.platform.mapper.OperationLogMapper;
import com.reading.platform.service.OperationLogService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 操作日志服务实现类
 */
@Service
@RequiredArgsConstructor
public class OperationLogServiceImpl implements OperationLogService {

    private final OperationLogMapper operationLogMapper;

    @Override
    public Page<OperationLog> getLogs(int pageNum, int pageSize, String tenantId, String module) {
        Page<OperationLog> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<OperationLog> wrapper = new LambdaQueryWrapper<>();
        if (tenantId != null) {
            wrapper.eq(OperationLog::getTenantId, tenantId);
        }
        if (module != null && !module.isEmpty()) {
            wrapper.eq(OperationLog::getModule, module);
        }
        wrapper.orderByDesc(OperationLog::getCreatedAt);
        return operationLogMapper.selectPage(page, wrapper);
    }

    @Override
    public Page<OperationLog> getLogs(int pageNum, int pageSize, String tenantId, String module, String startDate, String endDate) {
        Page<OperationLog> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<OperationLog> wrapper = new LambdaQueryWrapper<>();
        if (tenantId != null) {
            wrapper.eq(OperationLog::getTenantId, tenantId);
        }
        if (module != null && !module.isEmpty()) {
            wrapper.eq(OperationLog::getModule, module);
        }
        if (startDate != null && !startDate.isEmpty()) {
            wrapper.ge(OperationLog::getCreatedAt, LocalDate.parse(startDate).atStartOfDay());
        }
        if (endDate != null && !endDate.isEmpty()) {
            wrapper.le(OperationLog::getCreatedAt, LocalDate.parse(endDate).plusDays(1).atStartOfDay());
        }
        wrapper.orderByDesc(OperationLog::getCreatedAt);
        return operationLogMapper.selectPage(page, wrapper);
    }

    @Override
    public List<Map<String, Object>> getModuleStats(String tenantId, String startDate, String endDate) {
        LambdaQueryWrapper<OperationLog> wrapper = new LambdaQueryWrapper<>();
        if (tenantId != null) {
            wrapper.eq(OperationLog::getTenantId, tenantId);
        }
        if (startDate != null && !startDate.isEmpty()) {
            wrapper.ge(OperationLog::getCreatedAt, LocalDate.parse(startDate).atStartOfDay());
        }
        if (endDate != null && !endDate.isEmpty()) {
            wrapper.le(OperationLog::getCreatedAt, LocalDate.parse(endDate).plusDays(1).atStartOfDay());
        }

        List<OperationLog> logs = operationLogMapper.selectList(wrapper);
        Map<String, Long> moduleCount = logs.stream()
                .collect(Collectors.groupingBy(OperationLog::getModule, Collectors.counting()));

        List<Map<String, Object>> stats = new ArrayList<>();
        moduleCount.forEach((module, count) -> {
            Map<String, Object> item = new HashMap<>();
            item.put("module", module);
            item.put("count", count);
            stats.add(item);
        });
        return stats;
    }

    @Override
    public OperationLog getLogById(String id) {
        return operationLogMapper.selectById(id);
    }

    @Override
    public void log(String action, String module, String targetType, String targetId, String details) {
        try {
            OperationLog log = new OperationLog();
            log.setAction(action);
            log.setModule(module);
            log.setTargetType(targetType);
            log.setTargetId(targetId);
            log.setDetails(details);
            try {
                log.setUserId(SecurityUtils.getCurrentUserId());
                log.setUserRole(SecurityUtils.getCurrentRole());
                log.setTenantId(SecurityUtils.getCurrentTenantId());
            } catch (Exception ignored) {}
            operationLogMapper.insert(log);
        } catch (Exception e) {
            // Log silently - don't fail main operations
        }
    }
}
