package com.mosquito.project.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mosquito.project.dto.ApiResponse;
import com.mosquito.project.permission.ApprovalFlowService;
import com.mosquito.project.permission.RequirePermission;
import com.mosquito.project.service.RiskService;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 风险管理控制器
 */
@RestController
@RequestMapping("/api/v1/risks")
public class RiskController {

    private static final Logger log = LoggerFactory.getLogger(RiskController.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();

    private final RiskService riskService;

    // 业务类型常量
    private static final String BIZ_TYPE_RISK_RULE = "RISK_RULE";
    private static final String BIZ_TYPE_RISK_RULE_CREATE = "RISK_RULE_CREATE";
    private static final String BIZ_TYPE_RISK_RULE_UPDATE = "RISK_RULE_UPDATE";
    private static final String BIZ_TYPE_RISK_RULE_DELETE = "RISK_RULE_DELETE";

    @Autowired(required = false)
    private ApprovalFlowService approvalFlowService;

    public RiskController(RiskService riskService) {
        this.riskService = riskService;
    }

    /**
     * 获取当前用户ID
     */
    private Long getCurrentUserId(HttpServletRequest request) {
        Object userIdObj = request.getAttribute("userId");
        if (userIdObj instanceof Long) {
            return (Long) userIdObj;
        } else if (userIdObj instanceof Integer) {
            return ((Integer) userIdObj).longValue();
        } else if (userIdObj instanceof String) {
            try {
                return Long.parseLong((String) userIdObj);
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }

    /**
     * 获取风险告警列表
     */
    @GetMapping("/alerts")
    @RequirePermission("risk.index.view.ALL")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getAlerts(
            @RequestParam(required = false) Integer page,
            @RequestParam(required = false) Integer size,
            @RequestParam(required = false) String type,
            @RequestParam(required = false) String level,
            @RequestParam(required = false) String status,
            HttpServletRequest request) {

        Long currentUserId = getCurrentUserId(request);
        Map<String, Object> data = riskService.getAlerts(page, size, type, level, status, currentUserId);
        return ResponseEntity.ok(ApiResponse.success(data));
    }

    /**
     * 获取单个告警详情
     */
    @GetMapping("/alerts/{id}")
    @RequirePermission("risk.detail.view.ALL")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getAlertById(@PathVariable Long id) {
        Map<String, Object> data = riskService.getAlertById(id);
        return ResponseEntity.ok(ApiResponse.success(data));
    }

    /**
     * 处理风险告警
     * PRD要求: handlerId必须从JWT获取，不可从请求体读取（防止伪造）
     */
    @PostMapping("/alerts/{id}/handle")
    @RequirePermission("risk.alert.handle.ALL")
    public ResponseEntity<ApiResponse<Void>> handleAlert(
            @PathVariable Long id,
            @RequestBody Map<String, Object> request,
            HttpServletRequest httpRequest) {

        // 强制使用当前登录用户ID，不可从请求体读取
        Long currentUserId = getCurrentUserId(httpRequest);
        if (currentUserId == null) {
            return ResponseEntity.status(401).body(ApiResponse.error(401, "未获取到登录用户信息"));
        }

        boolean success = riskService.handleAlert(id, request, currentUserId);
        if (success) {
            return ResponseEntity.ok(ApiResponse.success(null, "告警处理完成"));
        }
        return ResponseEntity.ok(ApiResponse.error(404, "告警不存在"));
    }

    /**
     * 批量处理告警
     * PRD要求: handlerId必须从JWT获取，不可从请求体读取
     */
    @PostMapping("/alerts/batch-handle")
    @RequirePermission("risk.alert.handle.ALL")
    public ResponseEntity<ApiResponse<Integer>> batchHandleAlerts(
            @RequestBody Map<String, Object> request,
            HttpServletRequest httpRequest) {

        // 强制使用当前登录用户ID
        Long currentUserId = getCurrentUserId(httpRequest);
        if (currentUserId == null) {
            return ResponseEntity.status(401).body(ApiResponse.error(401, "未获取到登录用户信息"));
        }

        @SuppressWarnings("unchecked")
        List<Long> ids = (List<Long>) request.get("ids");
        int count = riskService.batchHandleAlerts(ids, request, currentUserId);
        return ResponseEntity.ok(ApiResponse.success(count, "批量处理完成"));
    }

    /**
     * 获取待处理告警数量
     */
    @GetMapping("/alerts/pending-count")
    @RequirePermission("risk.index.view.ALL")
    public ResponseEntity<ApiResponse<Long>> getPendingAlertCount() {
        long count = riskService.getPendingCount();
        return ResponseEntity.ok(ApiResponse.success(count));
    }

    /**
     * 获取风控规则列表
     */
    @GetMapping("/rules")
    @RequirePermission("risk.rule.manage.ALL")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getRules(
            @RequestParam(required = false) Integer page,
            @RequestParam(required = false) Integer size,
            @RequestParam(required = false) String riskType,
            @RequestParam(required = false) String status,
            HttpServletRequest request) {

        Long currentUserId = getCurrentUserId(request);
        Map<String, Object> data = riskService.getRules(page, size, riskType, status, currentUserId);
        return ResponseEntity.ok(ApiResponse.success(data));
    }

    /**
     * 创建风控规则（需要审批）
     */
    @PostMapping("/rules")
    @RequirePermission("risk.rule.create.ALL")
    public ResponseEntity<ApiResponse<Map<String, Object>>> createRule(
            @RequestBody Map<String, Object> request,
            HttpServletRequest httpRequest) {

        Long currentUserId = getCurrentUserId(httpRequest);
        String ruleName = (String) request.get("name");

        // 先保存待审批的规则
        Long pendingId = riskService.savePendingRule(request);

        // 尝试提交审批
        if (approvalFlowService != null && currentUserId != null) {
            try {
                String bizData = objectMapper.writeValueAsString(request);

                Map<String, Object> approvalResult = approvalFlowService.submitApprovalByEvent(
                    "RISK_RULE_CREATE",
                    BIZ_TYPE_RISK_RULE_CREATE,
                    pendingId,
                    "风控规则审批: " + ruleName,
                    currentUserId,
                    "申请创建风控规则: " + ruleName,
                    bizData
                );

                Map<String, Object> result = new HashMap<>();
                result.put("ruleId", pendingId);
                result.put("recordId", approvalResult.get("recordId"));
                result.put("status", "PENDING_APPROVAL");
                result.put("message", "规则已提交审批，审批通过后生效");

                return ResponseEntity.ok(ApiResponse.success(result, "规则已提交审批"));
            } catch (Exception e) {
                log.error("提交审批失败，拒绝执行敏感操作: ruleName={}, error={}", ruleName, e.getMessage());
                // 审批失败，拒绝执行敏感操作（Fail-Closed）
                return ResponseEntity.status(409).body(ApiResponse.error(409, "审批服务不可用，无法执行敏感操作，请稍后重试"));
            }
        }

        // 如果没有审批服务，返回409（Fail-Closed原则）
        return ResponseEntity.status(409).body(ApiResponse.error(409, "审批服务不可用，无法执行敏感操作"));
    }

    /**
     * 更新风控规则（需要审批）
     */
    @PutMapping("/rules/{id}")
    @RequirePermission("risk.rule.edit.ALL")
    public ResponseEntity<ApiResponse<Map<String, Object>>> updateRule(
            @PathVariable Long id,
            @RequestBody Map<String, Object> request,
            HttpServletRequest httpRequest) {

        Long currentUserId = getCurrentUserId(httpRequest);

        // 先保存待审批的规则
        riskService.savePendingRuleUpdate(id, request);

        // 尝试提交审批
        if (approvalFlowService != null && currentUserId != null) {
            try {
                String bizData = objectMapper.writeValueAsString(request);

                Map<String, Object> approvalResult = approvalFlowService.submitApprovalByEvent(
                    "RISK_RULE_UPDATE",
                    BIZ_TYPE_RISK_RULE_UPDATE,
                    id,
                    "风控规则审批: " + id,
                    currentUserId,
                    "申请更新风控规则: " + id,
                    bizData
                );

                Map<String, Object> result = new HashMap<>();
                result.put("ruleId", id);
                result.put("recordId", approvalResult.get("recordId"));
                result.put("status", "PENDING_APPROVAL");
                result.put("message", "规则已提交审批，审批通过后生效");

                return ResponseEntity.ok(ApiResponse.success(result, "规则已提交审批"));
            } catch (Exception e) {
                log.error("提交审批失败，拒绝执行敏感操作: ruleId={}, error={}", id, e.getMessage());
                // 审批失败，拒绝执行敏感操作（Fail-Closed）
                return ResponseEntity.status(409).body(ApiResponse.error(409, "审批服务不可用，无法执行敏感操作，请稍后重试"));
            }
        }

        // 如果没有审批服务，返回409（Fail-Closed原则）
        return ResponseEntity.status(409).body(ApiResponse.error(409, "审批服务不可用，无法执行敏感操作"));
    }

    /**
     * 删除风控规则（需要审批）
     */
    @DeleteMapping("/rules/{id}")
    @RequirePermission("risk.rule.delete.ALL")
    public ResponseEntity<ApiResponse<Map<String, Object>>> deleteRule(
            @PathVariable Long id,
            HttpServletRequest httpRequest) {

        Long currentUserId = getCurrentUserId(httpRequest);

        // 尝试提交审批
        if (approvalFlowService != null && currentUserId != null) {
            try {
                Map<String, Object> approvalResult = approvalFlowService.submitApprovalByEvent(
                    "RISK_RULE_DELETE",
                    BIZ_TYPE_RISK_RULE_DELETE,
                    id,
                    "风控规则删除审批: " + id,
                    currentUserId,
                    "申请删除风控规则: " + id,
                    "{\"action\":\"delete\",\"ruleId\":" + id + "}"
                );

                Map<String, Object> result = new HashMap<>();
                result.put("ruleId", id);
                result.put("recordId", approvalResult.get("recordId"));
                result.put("status", "PENDING_APPROVAL");
                result.put("message", "删除申请已提交审批，审批通过后规则将被删除");

                return ResponseEntity.ok(ApiResponse.success(result, "删除申请已提交审批"));
            } catch (Exception e) {
                log.error("提交审批失败，拒绝执行敏感操作: ruleId={}, error={}", id, e.getMessage());
                // 审批失败，拒绝执行敏感操作（Fail-Closed）
                return ResponseEntity.status(409).body(ApiResponse.error(409, "审批服务不可用，无法执行敏感操作，请稍后重试"));
            }
        }

        // 如果没有审批服务，返回409（Fail-Closed原则）
        return ResponseEntity.status(409).body(ApiResponse.error(409, "审批服务不可用，无法执行敏感操作"));
    }

    /**
     * 启用/禁用规则
     */
    @PostMapping("/rules/{id}/toggle")
    @RequirePermission("risk.rule.enable.ALL")
    public ResponseEntity<ApiResponse<Void>> toggleRule(
            @PathVariable Long id,
            @RequestBody Map<String, Boolean> request) {

        boolean enabled = request.getOrDefault("enabled", true);
        boolean success = riskService.toggleRule(id, enabled);
        if (success) {
            return ResponseEntity.ok(ApiResponse.success(null, "规则状态已更新"));
        }
        return ResponseEntity.ok(ApiResponse.error(404, "规则不存在"));
    }

    /**
     * 获取风控项列表（管理后台接口）
     */
    @GetMapping("/items")
    @RequirePermission("risk.index.view.ALL")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getRiskItems(
            @RequestParam(required = false) Integer page,
            @RequestParam(required = false) Integer size,
            @RequestParam(required = false) String riskType,
            @RequestParam(required = false) String status,
            HttpServletRequest request) {
        Long currentUserId = getCurrentUserId(request);
        Map<String, Object> data = riskService.getRules(page, size, riskType, status, currentUserId);
        return ResponseEntity.ok(ApiResponse.success(data));
    }

    /**
     * 执行风险拦截（阻断）
     * 对应权限: risk.block.execute.ALL
     */
    @PostMapping("/alerts/{id}/block")
    @RequirePermission("risk.block.execute.ALL")
    public ResponseEntity<ApiResponse<Void>> blockAlert(
            @PathVariable Long id,
            @RequestBody(required = false) Map<String, Object> request,
            HttpServletRequest httpRequest) {

        Long currentUserId = getCurrentUserId(httpRequest);
        if (currentUserId == null) {
            return ResponseEntity.status(401).body(ApiResponse.error(401, "未获取到登录用户信息"));
        }

        String comment = request != null && request.get("comment") != null
            ? request.get("comment").toString() : null;

        boolean success = riskService.blockAlert(id, currentUserId, comment);
        if (success) {
            return ResponseEntity.ok(ApiResponse.success(null, "风险拦截执行成功"));
        }
        return ResponseEntity.ok(ApiResponse.error(404, "告警不存在或状态异常"));
    }

    /**
     * 解除风险拦截（解除阻断）
     * 对应权限: risk.block.release.ALL
     */
    @PostMapping("/alerts/{id}/release")
    @RequirePermission("risk.block.release.ALL")
    public ResponseEntity<ApiResponse<Void>> releaseAlert(
            @PathVariable Long id,
            @RequestBody(required = false) Map<String, Object> request,
            HttpServletRequest httpRequest) {

        Long currentUserId = getCurrentUserId(httpRequest);
        if (currentUserId == null) {
            return ResponseEntity.status(401).body(ApiResponse.error(401, "未获取到登录用户信息"));
        }

        String comment = request != null && request.get("comment") != null
            ? request.get("comment").toString() : null;

        boolean success = riskService.releaseAlert(id, currentUserId, comment);
        if (success) {
            return ResponseEntity.ok(ApiResponse.success(null, "风险拦截解除成功"));
        }
        return ResponseEntity.ok(ApiResponse.error(400, "告警不存在或状态异常（非BLOCKED状态无法解除）"));
    }

    /**
     * 审核风控告警
     * 对应权限: risk.index.audit.ALL
     */
    @PostMapping("/{id}/audit")
    @RequirePermission("risk.index.audit.ALL")
    public ResponseEntity<ApiResponse<Map<String, Object>>> auditAlert(
            @PathVariable Long id,
            @RequestBody Map<String, Object> request,
            HttpServletRequest httpRequest) {

        Long currentUserId = getCurrentUserId(httpRequest);
        if (currentUserId == null) {
            return ResponseEntity.status(401).body(ApiResponse.error(401, "未获取到登录用户信息"));
        }

        String auditResult = request.get("result") != null ? request.get("result").toString() : "APPROVED";
        String comment = request.get("comment") != null ? request.get("comment").toString() : null;

        Map<String, Object> result = riskService.auditAlert(id, auditResult, comment, currentUserId);
        if (result == null) {
            return ResponseEntity.ok(ApiResponse.error(404, "告警不存在"));
        }

        return ResponseEntity.ok(ApiResponse.success(result, "审核完成"));
    }

    /**
     * 导出风控规则列表（CSV格式）
     * 对应权限: risk.index.export.ALL
     */
    @GetMapping("/rules/export")
    @RequirePermission("risk.index.export.ALL")
    public ResponseEntity<byte[]> exportRules(HttpServletRequest request) {
        Long currentUserId = getCurrentUserId(request);

        byte[] csvData = riskService.exportRules(currentUserId);

        String filename = "risk-rules-" + java.time.LocalDate.now() + ".csv";
        return ResponseEntity.ok()
            .header("Content-Disposition", "attachment; filename=\"" + filename + "\"")
            .header("Content-Type", "text/csv; charset=UTF-8")
            .body(csvData);
    }

    /**
     * 获取黑名单列表
     * 对应权限: risk.blacklist.manage.ALL
     */
    @GetMapping("/blacklist")
    @RequirePermission("risk.blacklist.manage.ALL")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getBlacklist(
            @RequestParam(required = false) Integer page,
            @RequestParam(required = false) Integer size,
            @RequestParam(required = false) String query,
            HttpServletRequest request) {
        Long currentUserId = getCurrentUserId(request);
        Map<String, Object> data = riskService.getBlacklist(page, size, query, currentUserId);
        return ResponseEntity.ok(ApiResponse.success(data));
    }

    /**
     * 添加用户到黑名单
     * 对应权限: risk.blacklist.manage.ALL
     */
    @PostMapping("/blacklist/{userId}")
    @RequirePermission("risk.blacklist.manage.ALL")
    public ResponseEntity<ApiResponse<Void>> addToBlacklist(
            @PathVariable Long userId,
            @RequestBody(required = false) Map<String, Object> request,
            HttpServletRequest httpRequest) {
        Long currentUserId = getCurrentUserId(httpRequest);
        if (currentUserId == null) {
            return ResponseEntity.status(401).body(ApiResponse.error(401, "未获取到登录用户信息"));
        }

        String reason = request != null && request.get("reason") != null
            ? request.get("reason").toString() : null;

        boolean success = riskService.addToBlacklist(userId, currentUserId, reason);
        if (success) {
            return ResponseEntity.ok(ApiResponse.success(null, "已添加到黑名单"));
        }
        return ResponseEntity.ok(ApiResponse.error(400, "添加黑名单失败"));
    }

    /**
     * 从黑名单移除用户
     * 对应权限: risk.blacklist.manage.ALL
     */
    @PostMapping("/blacklist/{userId}/remove")
    @RequirePermission("risk.blacklist.manage.ALL")
    public ResponseEntity<ApiResponse<Void>> removeFromBlacklist(
            @PathVariable Long userId,
            @RequestBody(required = false) Map<String, Object> request,
            HttpServletRequest httpRequest) {
        Long currentUserId = getCurrentUserId(httpRequest);
        if (currentUserId == null) {
            return ResponseEntity.status(401).body(ApiResponse.error(401, "未获取到登录用户信息"));
        }

        String reason = request != null && request.get("reason") != null
            ? request.get("reason").toString() : null;

        boolean success = riskService.removeFromBlacklist(userId, currentUserId, reason);
        if (success) {
            return ResponseEntity.ok(ApiResponse.success(null, "已从黑名单移除"));
        }
        return ResponseEntity.ok(ApiResponse.error(400, "移除黑名单失败"));
    }
}
