package com.mosquito.project.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mosquito.project.persistence.entity.RiskAlertEntity;
import com.mosquito.project.persistence.entity.RiskRuleEntity;
import com.mosquito.project.persistence.repository.RiskAlertRepository;
import com.mosquito.project.persistence.repository.RiskRuleRepository;
import com.mosquito.project.permission.PermissionCheckService;
import com.mosquito.project.permission.SysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.*;

import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 风险管理服务
 * PRD要求: 风险处理流程（警告/限制/冻结/封禁）
 */
@Service
public class RiskService {

    private static final Logger log = LoggerFactory.getLogger(RiskService.class);

    // 风险处置动作常量
    public static final String ACTION_WARNING = "WARNING";     // 警告
    public static final String ACTION_LIMIT = "LIMIT";         // 限制
    public static final String ACTION_FREEZE = "FREEZE";       // 冻结
    public static final String ACTION_BAN = "BAN";             // 封禁

    // 风险级别常量
    public static final String LEVEL_LOW = "LOW";
    public static final String LEVEL_MEDIUM = "MEDIUM";
    public static final String LEVEL_HIGH = "HIGH";
    public static final String LEVEL_CRITICAL = "CRITICAL";

    private final RiskAlertRepository alertRepository;
    private final RiskRuleRepository ruleRepository;
    private final SysUserService sysUserService;
    private final PermissionCheckService permissionCheckService;
    private final AuditService auditService;
    private final StringRedisTemplate redisTemplate;
    private final ObjectMapper objectMapper;

    // 用户限制key前缀
    private static final String USER_LIMIT_KEY_PREFIX = "risk:limit:";
    // 限制时长（1小时）
    private static final Duration LIMIT_DURATION = Duration.ofHours(1);
    // 限制期间的API调用次数上限
    private static final int LIMITED_API_CALLS_PER_HOUR = 10;

    public RiskService(RiskAlertRepository alertRepository,
                      RiskRuleRepository ruleRepository,
                      SysUserService sysUserService,
                      PermissionCheckService permissionCheckService,
                      AuditService auditService,
                      StringRedisTemplate redisTemplate,
                      ObjectMapper objectMapper) {
        this.alertRepository = alertRepository;
        this.ruleRepository = ruleRepository;
        this.sysUserService = sysUserService;
        this.permissionCheckService = permissionCheckService;
        this.auditService = auditService;
        this.redisTemplate = redisTemplate;
        this.objectMapper = objectMapper;
    }

    /**
     * 获取风险告警列表（带数据权限过滤）
     */
    public Map<String, Object> getAlerts(Integer page, Integer size, String type, String level, String status, Long currentUserId) {
        int pageNum = page != null && page > 0 ? page - 1 : 0;
        int pageSize = size != null && size > 0 ? size : 10;

        PageRequest pageRequest = PageRequest.of(pageNum, pageSize, Sort.by(Sort.Direction.DESC, "createdAt"));

        // 获取数据权限范围
        String dataScope = currentUserId != null ? permissionCheckService.getUserDataScope(currentUserId) : "OWN";
        Long userDeptId = currentUserId != null ? permissionCheckService.getUserDepartmentId(currentUserId) : null;
        List<Long> deptIds = currentUserId != null ? permissionCheckService.getUserDepartmentAndChildIds(currentUserId) : List.of();

        Page<RiskAlertEntity> alertPage = alertRepository.findByFiltersWithDataScope(
                type, level, status, dataScope, deptIds, currentUserId, pageRequest);

        List<Map<String, Object>> data = alertPage.getContent().stream()
                .map(this::toAlertMap)
                .collect(Collectors.toList());

        Map<String, Object> result = new HashMap<>();
        result.put("data", data);
        result.put("total", alertPage.getTotalElements());
        result.put("page", pageNum + 1);
        result.put("size", pageSize);
        return result;
    }

    /**
     * 转换告警实体为Map
     */
    private Map<String, Object> toAlertMap(RiskAlertEntity entity) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", entity.getId());
        map.put("type", entity.getAlertType());
        map.put("level", entity.getRiskLevel());
        map.put("title", entity.getTitle());
        map.put("description", entity.getDescription());
        map.put("relatedUserId", entity.getRelatedUserId());
        map.put("relatedActivityId", entity.getRelatedActivityId());
        map.put("relatedRuleId", entity.getRelatedRuleId());
        map.put("status", entity.getStatus());
        map.put("handlerId", entity.getHandlerId());
        map.put("handlerComment", entity.getHandlerComment());
        map.put("handledAt", entity.getHandledAt() != null ? entity.getHandledAt().toString() : null);
        map.put("createdAt", entity.getCreatedAt() != null ? entity.getCreatedAt().toString() : null);
        return map;
    }

    /**
     * 获取单个告警详情
     */
    public Map<String, Object> getAlertById(Long id) {
        return alertRepository.findById(id)
                .map(this::toAlertMap)
                .orElse(null);
    }

    /**
     * 处理风险告警
     * PRD要求: 支持分级处置（警告/限制/冻结/封禁）
     * 注意: handlerId必须从JWT获取，不可从请求体读取（安全修复）
     */
    public boolean handleAlert(Long id, Map<String, Object> request, Long currentUserId) {
        Optional<RiskAlertEntity> optAlert = alertRepository.findById(id);
        if (!optAlert.isPresent()) return false;

        RiskAlertEntity alert = optAlert.get();

        // 获取处置动作，默认为WARNING
        String action = request.get("action") != null ? request.get("action").toString() : ACTION_WARNING;
        String comment = request.get("comment") != null ? request.get("comment").toString() : null;
        // 强制使用当前登录用户ID，不再从请求体读取（防止handlerId伪造）
        Long handlerId = currentUserId;

        // 执行分级处置
        boolean actionSuccess = executeRiskAction(alert, action, comment, handlerId);

        // 更新告警状态
        alert.setStatus("RESOLVED");
        alert.setHandlerId(handlerId);
        alert.setHandlerComment(action + (comment != null ? ": " + comment : ""));
        alert.setHandledAt(OffsetDateTime.now(ZoneOffset.UTC));
        alertRepository.save(alert);

        // 记录审计日志
        if (auditService != null) {
            Map<String, Object> details = new HashMap<>();
            details.put("alertId", id);
            details.put("action", action);
            details.put("handlerId", handlerId); // 记录实际处理人
            details.put("relatedUserId", alert.getRelatedUserId());
            details.put("comment", comment);
            auditService.recordAuditLog(details);
        }

        log.info("风险告警处理完成: alertId={}, action={}, handlerId={}, relatedUserId={}",
                id, action, handlerId, alert.getRelatedUserId());
        return actionSuccess;
    }

    /**
     * 执行风险拦截（风险阻断）
     * 对应权限: risk.block.execute
     */
    public boolean blockAlert(Long alertId, Long currentUserId, String comment) {
        Optional<RiskAlertEntity> optAlert = alertRepository.findById(alertId);
        if (!optAlert.isPresent()) {
            log.warn("风险拦截失败: 告警不存在, alertId={}", alertId);
            return false;
        }

        RiskAlertEntity alert = optAlert.get();
        String previousStatus = alert.getStatus();

        // 更新告警状态为BLOCKED
        alert.setStatus("BLOCKED");
        alert.setHandlerId(currentUserId);
        alert.setHandlerComment("执行拦截" + (comment != null ? ": " + comment : ""));
        alert.setHandledAt(OffsetDateTime.now(ZoneOffset.UTC));
        alert.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        alertRepository.save(alert);

        // 记录审计日志
        if (auditService != null) {
            Map<String, Object> details = new HashMap<>();
            details.put("alertId", alertId);
            details.put("action", "BLOCK");
            details.put("previousStatus", previousStatus);
            details.put("newStatus", "BLOCKED");
            details.put("handlerId", currentUserId);
            details.put("relatedUserId", alert.getRelatedUserId());
            details.put("relatedActivityId", alert.getRelatedActivityId());
            details.put("comment", comment);
            auditService.recordAuditLog(details);
        }

        log.info("风险拦截执行成功: alertId={}, handlerId={}, relatedUserId={}",
                alertId, currentUserId, alert.getRelatedUserId());
        return true;
    }

    /**
     * 解除风险拦截（解除阻断）
     * 对应权限: risk.block.release
     */
    public boolean releaseAlert(Long alertId, Long currentUserId, String comment) {
        Optional<RiskAlertEntity> optAlert = alertRepository.findById(alertId);
        if (!optAlert.isPresent()) {
            log.warn("解除拦截失败: 告警不存在, alertId={}", alertId);
            return false;
        }

        RiskAlertEntity alert = optAlert.get();

        // 只有BLOCKED状态可以解除
        if (!"BLOCKED".equals(alert.getStatus())) {
            log.warn("解除拦截失败: 告警状态不是BLOCKED, alertId={}, status={}", alertId, alert.getStatus());
            return false;
        }

        String previousStatus = alert.getStatus();

        // 更新告警状态为RELEASED
        alert.setStatus("RELEASED");
        alert.setHandlerId(currentUserId);
        alert.setHandlerComment("解除拦截" + (comment != null ? ": " + comment : ""));
        alert.setHandledAt(OffsetDateTime.now(ZoneOffset.UTC));
        alert.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        alertRepository.save(alert);

        // 记录审计日志
        if (auditService != null) {
            Map<String, Object> details = new HashMap<>();
            details.put("alertId", alertId);
            details.put("action", "RELEASE");
            details.put("previousStatus", previousStatus);
            details.put("newStatus", "RELEASED");
            details.put("handlerId", currentUserId);
            details.put("relatedUserId", alert.getRelatedUserId());
            details.put("relatedActivityId", alert.getRelatedActivityId());
            details.put("comment", comment);
            auditService.recordAuditLog(details);
        }

        log.info("风险拦截解除成功: alertId={}, handlerId={}, relatedUserId={}",
                alertId, currentUserId, alert.getRelatedUserId());
        return true;
    }

    /**
     * 审核风控告警
     * 对应权限: risk.index.audit.ALL
     */
    public Map<String, Object> auditAlert(Long alertId, String auditResult, String comment, Long currentUserId) {
        Optional<RiskAlertEntity> optAlert = alertRepository.findById(alertId);
        if (!optAlert.isPresent()) {
            log.warn("审核风控失败: 告警不存在, alertId={}", alertId);
            return null;
        }

        RiskAlertEntity alert = optAlert.get();
        String previousStatus = alert.getStatus();
        String newStatus;

        // 根据审核结果决定新状态
        if ("APPROVED".equalsIgnoreCase(auditResult)) {
            newStatus = "APPROVED";
        } else if ("REJECTED".equalsIgnoreCase(auditResult)) {
            newStatus = "REJECTED";
        } else if ("PENDING".equalsIgnoreCase(auditResult)) {
            newStatus = "PENDING";
        } else {
            log.warn("审核风控失败: 无效的审核结果, alertId={}, auditResult={}", alertId, auditResult);
            return null;
        }

        // 更新告警状态
        alert.setStatus(newStatus);
        alert.setHandlerId(currentUserId);
        alert.setHandlerComment("审核" + auditResult + (comment != null ? ": " + comment : ""));
        alert.setHandledAt(OffsetDateTime.now(ZoneOffset.UTC));
        alert.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        alertRepository.save(alert);

        // 记录审计日志
        if (auditService != null) {
            Map<String, Object> details = new HashMap<>();
            details.put("alertId", alertId);
            details.put("action", "AUDIT");
            details.put("auditResult", auditResult);
            details.put("previousStatus", previousStatus);
            details.put("newStatus", newStatus);
            details.put("auditorId", currentUserId);
            details.put("relatedUserId", alert.getRelatedUserId());
            details.put("relatedActivityId", alert.getRelatedActivityId());
            details.put("comment", comment);
            auditService.recordAuditLog(details);
        }

        Map<String, Object> result = new HashMap<>();
        result.put("alertId", alertId);
        result.put("previousStatus", previousStatus);
        result.put("newStatus", newStatus);
        result.put("auditorId", currentUserId);
        result.put("auditResult", auditResult);
        result.put("comment", comment);

        log.info("风控审核完成: alertId={}, auditResult={}, auditorId={}, previousStatus={}, newStatus={}",
                alertId, auditResult, currentUserId, previousStatus, newStatus);
        return result;
    }

    /**
     * 执行风险分级处置动作
     */
    private boolean executeRiskAction(RiskAlertEntity alert, String action, String comment, Long handlerId) {
        Long userId = alert.getRelatedUserId();
        if (userId == null) {
            log.warn("风险告警无关联用户，跳过处置: alertId={}", alert.getId());
            return false;
        }

        try {
            switch (action) {
                case ACTION_WARNING:
                    // 警告：记录警告日志，不执行业务操作
                    log.warn("风险警告: userId={}, alertId={}, comment={}", userId, alert.getId(), comment);
                    return true;

                case ACTION_LIMIT:
                    // 限制：设置用户API调用频率限制
                    log.info("风险限制: userId={}, alertId={}, comment={}", userId, alert.getId(), comment);
                    boolean limited = applyUserLimit(userId, alert.getId());
                    if (limited) {
                        log.info("用户已被限制API调用: userId={}, alertId={}, 每小时最多{}次调用",
                                userId, alert.getId(), LIMITED_API_CALLS_PER_HOUR);
                    }
                    return limited;

                case ACTION_FREEZE:
                    // 冻结：临时冻结用户账号
                    log.info("风险冻结: userId={}, alertId={}, comment={}", userId, alert.getId(), comment);
                    boolean frozen = sysUserService.freezeUser(userId);
                    if (frozen) {
                        log.info("用户已被冻结: userId={}, alertId={}", userId, alert.getId());
                    }
                    return frozen;

                case ACTION_BAN:
                    // 封禁：永久封禁用户账号
                    log.info("风险封禁: userId={}, alertId={}, comment={}", userId, alert.getId(), comment);
                    boolean banned = sysUserService.banUser(userId, comment);
                    if (banned) {
                        log.info("用户已被封禁: userId={}, alertId={}", userId, alert.getId());
                    }
                    return banned;

                default:
                    log.warn("未知的风险处置动作: action={}, alertId={}", action, alert.getId());
                    return false;
            }
        } catch (Exception e) {
            log.error("执行风险处置动作失败: alertId={}, action={}, error={}", alert.getId(), action, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 对用户实施API调用限制
     * 通过Redis设置限制标记和频率上限
     */
    private boolean applyUserLimit(Long userId, Long alertId) {
        try {
            String limitKey = USER_LIMIT_KEY_PREFIX + userId;
            // 设置限制标记（1小时过期）
            redisTemplate.opsForValue().set(limitKey, String.valueOf(alertId), LIMIT_DURATION);
            // 设置限制期间的API调用次数上限
            String rateLimitKey = "rl:limit:" + userId;
            redisTemplate.opsForValue().set(rateLimitKey, String.valueOf(LIMITED_API_CALLS_PER_HOUR), LIMIT_DURATION);
            log.info("已对用户设置API调用限制: userId={}, alertId={}, maxCalls={}, duration={}",
                    userId, alertId, LIMITED_API_CALLS_PER_HOUR, LIMIT_DURATION.toMinutes());
            return true;
        } catch (Exception e) {
            log.error("设置用户API调用限制失败: userId={}, alertId={}, error={}",
                    userId, alertId, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 检查用户是否被限制
     */
    public boolean isUserLimited(Long userId) {
        try {
            String limitKey = USER_LIMIT_KEY_PREFIX + userId;
            return Boolean.TRUE.equals(redisTemplate.hasKey(limitKey));
        } catch (Exception e) {
            log.warn("检查用户限制状态失败: userId={}, error={}", userId, e.getMessage());
            return false;
        }
    }

    /**
     * 批量处理告警
     * 注意: handlerId必须从JWT获取（安全修复）
     */
    public int batchHandleAlerts(List<Long> ids, Map<String, Object> request, Long currentUserId) {
        int count = 0;
        for (Long id : ids) {
            if (handleAlert(id, request, currentUserId)) {
                count++;
            }
        }
        return count;
    }

    /**
     * 获取待处理告警数量
     */
    public long getPendingCount() {
        return alertRepository.countByStatus("PENDING");
    }

    /**
     * 获取风控规则列表（带数据权限过滤）
     */
    public Map<String, Object> getRules(Integer page, Integer size, String riskType, String status, Long currentUserId) {
        int pageNum = page != null && page > 0 ? page - 1 : 0;
        int pageSize = size != null && size > 0 ? size : 10;

        PageRequest pageRequest = PageRequest.of(pageNum, pageSize, Sort.by(Sort.Direction.DESC, "priority"));

        // 获取数据权限范围
        String dataScope = currentUserId != null ? permissionCheckService.getUserDataScope(currentUserId) : "OWN";
        Long userDeptId = currentUserId != null ? permissionCheckService.getUserDepartmentId(currentUserId) : null;
        List<Long> deptIds = currentUserId != null ? permissionCheckService.getUserDepartmentAndChildIds(currentUserId) : List.of();

        Page<RiskRuleEntity> rulePage = ruleRepository.findByFiltersWithDataScope(
                riskType, status, dataScope, deptIds, currentUserId, pageRequest);

        List<Map<String, Object>> data = rulePage.getContent().stream()
                .map(this::toRuleMap)
                .collect(Collectors.toList());

        Map<String, Object> result = new HashMap<>();
        result.put("data", data);
        result.put("total", rulePage.getTotalElements());
        result.put("page", pageNum + 1);
        result.put("size", pageSize);
        return result;
    }

    /**
     * 转换规则实体为Map
     */
    private Map<String, Object> toRuleMap(RiskRuleEntity entity) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", entity.getId());
        map.put("name", entity.getName());
        map.put("type", entity.getRiskType());
        map.put("condition", entity.getConditionExpr());
        map.put("action", entity.getAction());
        map.put("actionParams", entity.getActionParams());
        map.put("status", entity.getStatus());
        map.put("priority", entity.getPriority());
        map.put("createdAt", entity.getCreatedAt() != null ? entity.getCreatedAt().toString() : null);
        return map;
    }

    /**
     * 保存待审批的风控规则
     */
    public Long savePendingRule(Map<String, Object> request) {
        RiskRuleEntity rule = new RiskRuleEntity();
        rule.setName(request.get("name").toString());
        // 兼容 riskType 和 type 两种字段名（前端使用 riskType，后端旧接口使用 type）
        String riskType = request.containsKey("riskType")
            ? request.get("riskType").toString()
            : request.get("type").toString();
        rule.setRiskType(riskType);
        rule.setConditionExpr(request.get("condition").toString());
        rule.setAction(request.get("action").toString());
        if (request.get("actionParams") != null) {
            rule.setActionParams(request.get("actionParams").toString());
        }
        rule.setStatus("PENDING_APPROVAL");
        rule.setPriority(request.get("priority") != null ? Integer.parseInt(request.get("priority").toString()) : 0);
        rule.setCreatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        rule.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        rule = ruleRepository.save(rule);
        log.info("待审批风控规则已保存: id={}, name={}", rule.getId(), rule.getName());
        return rule.getId();
    }

    /**
     * 保存待审批的规则更新
     */
    public boolean savePendingRuleUpdate(Long id, Map<String, Object> request) {
        Optional<RiskRuleEntity> optRule = ruleRepository.findById(id);
        if (!optRule.isPresent()) return false;

        RiskRuleEntity rule = optRule.get();
        try {
            // 将更新内容保存到 pendingUpdate 字段
            rule.setPendingUpdate(objectMapper.writeValueAsString(request));
        } catch (Exception e) {
            log.error("序列化待审批更新内容失败: id={}, error={}", id, e.getMessage());
            return false;
        }
        // 将当前规则保存为待审批状态
        rule.setStatus("PENDING_APPROVAL_UPDATE");
        rule.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        ruleRepository.save(rule);
        log.info("待审批规则更新已保存: id={}", id);
        return true;
    }

    /**
     * 审批通过后应用规则
     */
    public boolean applyPendingRule(Long id) {
        Optional<RiskRuleEntity> optRule = ruleRepository.findById(id);
        if (optRule.isPresent()) {
            RiskRuleEntity rule = optRule.get();
            if ("PENDING_APPROVAL".equals(rule.getStatus())) {
                rule.setStatus("ENABLED");
                rule.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
                ruleRepository.save(rule);
                log.info("审批通过，风控规则已生效: id={}", id);
                return true;
            } else if ("PENDING_APPROVAL_UPDATE".equals(rule.getStatus())) {
                // 应用待审批的更新内容
                String pendingUpdate = rule.getPendingUpdate();
                if (pendingUpdate != null && !pendingUpdate.isEmpty()) {
                    try {
                        Map<String, Object> updateData = objectMapper.readValue(pendingUpdate,
                            new TypeReference<Map<String, Object>>() {});
                        // 应用更新字段
                        if (updateData.get("name") != null) {
                            rule.setName(updateData.get("name").toString());
                        }
                        if (updateData.get("type") != null) {
                            rule.setRiskType(updateData.get("type").toString());
                        }
                        if (updateData.get("condition") != null) {
                            rule.setConditionExpr(updateData.get("condition").toString());
                        }
                        if (updateData.get("action") != null) {
                            rule.setAction(updateData.get("action").toString());
                        }
                        if (updateData.get("actionParams") != null) {
                            rule.setActionParams(updateData.get("actionParams").toString());
                        }
                        if (updateData.get("priority") != null) {
                            rule.setPriority(Integer.parseInt(updateData.get("priority").toString()));
                        }
                        log.info("已应用风控规则更新内容: id={}, updateData={}", id, updateData);
                    } catch (JsonProcessingException e) {
                        log.error("解析待审批更新内容失败: id={}, error={}", id, e.getMessage());
                        return false;
                    }
                }
                // 清除待审批更新内容并启用规则
                rule.setPendingUpdate(null);
                rule.setStatus("ENABLED");
                rule.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
                ruleRepository.save(rule);
                log.info("审批通过，风控规则更新已生效: id={}", id);
                return true;
            }
        }
        return false;
    }

    /**
     * 创建风控规则
     */
    public Long createRule(Map<String, Object> request) {
        RiskRuleEntity rule = new RiskRuleEntity();
        rule.setName(request.get("name").toString());
        rule.setRiskType(request.get("type").toString());
        rule.setConditionExpr(request.get("condition").toString());
        rule.setAction(request.get("action").toString());
        if (request.get("actionParams") != null) {
            rule.setActionParams(request.get("actionParams").toString());
        }
        rule.setStatus("ENABLED");
        rule.setPriority(request.get("priority") != null ? Integer.parseInt(request.get("priority").toString()) : 0);
        rule.setCreatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        rule.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        rule = ruleRepository.save(rule);
        return rule.getId();
    }

    /**
     * 更新风控规则
     */
    public boolean updateRule(Long id, Map<String, Object> request) {
        Optional<RiskRuleEntity> optRule = ruleRepository.findById(id);
        if (!optRule.isPresent()) return false;

        RiskRuleEntity rule = optRule.get();
        if (request.get("name") != null) rule.setName(request.get("name").toString());
        if (request.get("type") != null) rule.setRiskType(request.get("type").toString());
        if (request.get("condition") != null) rule.setConditionExpr(request.get("condition").toString());
        if (request.get("action") != null) rule.setAction(request.get("action").toString());
        if (request.get("actionParams") != null) rule.setActionParams(request.get("actionParams").toString());
        if (request.get("priority") != null) rule.setPriority(Integer.parseInt(request.get("priority").toString()));
        rule.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        ruleRepository.save(rule);
        return true;
    }

    /**
     * 删除风控规则
     */
    public boolean deleteRule(Long id) {
        if (!ruleRepository.existsById(id)) return false;
        ruleRepository.deleteById(id);
        return true;
    }

    /**
     * 切换规则状态
     */
    public boolean toggleRule(Long id, boolean enabled) {
        Optional<RiskRuleEntity> optRule = ruleRepository.findById(id);
        if (!optRule.isPresent()) return false;

        RiskRuleEntity rule = optRule.get();
        rule.setStatus(enabled ? "ENABLED" : "DISABLED");
        rule.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        ruleRepository.save(rule);
        return true;
    }

    /**
     * 创建告警（内部使用）
     */
    public Long createAlert(Map<String, Object> alertData) {
        RiskAlertEntity alert = new RiskAlertEntity();
        alert.setAlertType(alertData.getOrDefault("type", "RISK").toString());
        alert.setRiskLevel(alertData.getOrDefault("level", "MEDIUM").toString());
        alert.setTitle(alertData.get("title").toString());
        if (alertData.get("description") != null) {
            alert.setDescription(alertData.get("description").toString());
        }
        if (alertData.get("relatedUserId") != null) {
            alert.setRelatedUserId(Long.parseLong(alertData.get("relatedUserId").toString()));
        }
        if (alertData.get("relatedActivityId") != null) {
            alert.setRelatedActivityId(Long.parseLong(alertData.get("relatedActivityId").toString()));
        }
        if (alertData.get("relatedRuleId") != null) {
            alert.setRelatedRuleId(Long.parseLong(alertData.get("relatedRuleId").toString()));
        }
        alert.setStatus("PENDING");
        alert.setCreatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        alert.setUpdatedAt(OffsetDateTime.now(ZoneOffset.UTC));
        alert = alertRepository.save(alert);
        return alert.getId();
    }

    /**
     * 导出风控规则列表（CSV格式）
     * 应用数据权限过滤
     */
    public byte[] exportRules(Long currentUserId) {
        // 获取数据权限范围
        String dataScope = currentUserId != null ? permissionCheckService.getUserDataScope(currentUserId) : "OWN";
        List<Long> deptIds = currentUserId != null ? permissionCheckService.getUserDepartmentAndChildIds(currentUserId) : List.of();

        // 查询所有规则（不受分页限制）
        List<RiskRuleEntity> rules = ruleRepository.findByFiltersWithDataScope(
            null, null, dataScope, deptIds, currentUserId);

        // 生成CSV
        StringBuilder csv = new StringBuilder();
        csv.append("ID,规则名称,规则类型,条件,动作,状态,优先级,创建时间\n");

        for (RiskRuleEntity rule : rules) {
            csv.append(rule.getId()).append(",");
            csv.append(escapeCsv(rule.getName())).append(",");
            csv.append(escapeCsv(rule.getRiskType())).append(",");
            csv.append(escapeCsv(rule.getConditionExpr())).append(",");
            csv.append(escapeCsv(rule.getAction())).append(",");
            csv.append(escapeCsv(rule.getStatus())).append(",");
            csv.append(rule.getPriority()).append(",");
            csv.append(rule.getCreatedAt() != null ? rule.getCreatedAt().toString() : "").append("\n");
        }

        return csv.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8);
    }

    /**
     * CSV字段转义
     */
    private String escapeCsv(String value) {
        if (value == null) {
            return "";
        }
        // 如果包含逗号、引号或换行符，需要用双引号包裹
        if (value.contains(",") || value.contains("\"") || value.contains("\n")) {
            return "\"" + value.replace("\"", "\"\"") + "\"";
        }
        return value;
    }

    /**
     * 获取黑名单列表（分页）
     * 对应权限: risk.blacklist.manage.ALL
     */
    public Map<String, Object> getBlacklist(Integer page, Integer size, String query, Long currentUserId) {
        int pageNum = page != null && page > 0 ? page - 1 : 0;
        int pageSize = size != null && size > 0 ? size : 10;

        var blacklistPage = sysUserService.getBlacklist(pageNum + 1, pageSize, query);

        List<Map<String, Object>> data = blacklistPage.getContent().stream()
                .map(user -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", user.getId());
                    map.put("username", user.getUsername());
                    map.put("realName", user.getRealName());
                    map.put("email", user.getEmail());
                    map.put("phone", user.getPhone());
                    map.put("isBlacklisted", user.getIsBlacklisted());
                    map.put("status", user.getStatus());
                    map.put("departmentId", user.getDepartmentId());
                    map.put("createdAt", user.getCreatedAt() != null ? user.getCreatedAt().toString() : null);
                    map.put("updatedAt", user.getUpdatedAt() != null ? user.getUpdatedAt().toString() : null);
                    return map;
                })
                .collect(Collectors.toList());

        Map<String, Object> result = new HashMap<>();
        result.put("data", data);
        result.put("total", blacklistPage.getTotalElements());
        result.put("page", pageNum + 1);
        result.put("size", pageSize);
        return result;
    }

    /**
     * 添加用户到黑名单
     * 对应权限: risk.blacklist.manage.ALL
     */
    public boolean addToBlacklist(Long userId, Long operatorId, String reason) {
        boolean success = sysUserService.addToBlacklist(userId, reason);
        if (success && auditService != null) {
            Map<String, Object> details = new HashMap<>();
            details.put("action", "ADD_TO_BLACKLIST");
            details.put("userId", userId);
            details.put("operatorId", operatorId);
            details.put("reason", reason);
            auditService.recordAuditLog(details);
        }
        return success;
    }

    /**
     * 从黑名单移除用户
     * 对应权限: risk.blacklist.manage.ALL
     */
    public boolean removeFromBlacklist(Long userId, Long operatorId, String reason) {
        boolean success = sysUserService.removeFromBlacklist(userId);
        if (success && auditService != null) {
            Map<String, Object> details = new HashMap<>();
            details.put("action", "REMOVE_FROM_BLACKLIST");
            details.put("userId", userId);
            details.put("operatorId", operatorId);
            details.put("reason", reason);
            auditService.recordAuditLog(details);
        }
        return success;
    }
}
