package com.mosquito.project.controller;

import com.mosquito.project.dto.RegisterCallbackRequest;
import com.mosquito.project.persistence.entity.ProcessedCallbackEntity;
import com.mosquito.project.persistence.entity.ShortLinkEntity;
import com.mosquito.project.persistence.repository.ProcessedCallbackRepository;
import com.mosquito.project.persistence.repository.ShortLinkRepository;
import com.mosquito.project.service.CallbackRiskGuardService;
import com.mosquito.project.service.CallbackRiskGuardService.RiskCheckResult;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
@RequestMapping("/api/v1/callback")
public class CallbackController {

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

    private final ProcessedCallbackRepository processedCallbackRepository;
    private final ShortLinkRepository shortLinkRepository;
    private final com.mosquito.project.service.RewardQueue rewardQueue;
    private final CallbackRiskGuardService riskGuardService;

    public CallbackController(ProcessedCallbackRepository processedCallbackRepository,
                             ShortLinkRepository shortLinkRepository,
                             com.mosquito.project.service.RewardQueue rewardQueue,
                             CallbackRiskGuardService riskGuardService) {
        this.processedCallbackRepository = processedCallbackRepository;
        this.shortLinkRepository = shortLinkRepository;
        this.rewardQueue = rewardQueue;
        this.riskGuardService = riskGuardService;
    }

    /**
     * 从HttpServletRequest获取真实客户端IP（不从请求体获取）
     * 优先从X-Forwarded-For获取，再从remoteAddr获取
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            // 多次代理时取第一个IP
            int index = ip.indexOf(',');
            if (index != -1) {
                return ip.substring(0, index).trim();
            }
            return ip.trim();
        }
        // 尝试从Proxy-Client-IP获取
        ip = request.getHeader("Proxy-Client-IP");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
        // 尝试从WL-Proxy-Client-IP获取
        ip = request.getHeader("WL-Proxy-Client-IP");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
        // 获取远程地址
        return request.getRemoteAddr();
    }

    // 统一响应结构
    private ResponseEntity<Map<String, Object>> successResponse(String message, Object data) {
        Map<String, Object> body = new java.util.HashMap<>();
        body.put("code", 0);
        body.put("message", message);
        body.put("data", data != null ? data : new java.util.HashMap<>());
        return ResponseEntity.ok(body);
    }

    private ResponseEntity<Map<String, Object>> errorResponse(int httpStatus, int code, String message) {
        Map<String, Object> body = new java.util.HashMap<>();
        body.put("code", code);
        body.put("message", message);
        body.put("data", new java.util.HashMap<>());
        HttpStatus status = HttpStatus.valueOf(httpStatus);
        return new ResponseEntity<>(body, status);
    }

    // 便捷方法：参数错误
    private ResponseEntity<Map<String, Object>> badRequest(String message) {
        return errorResponse(400, 400, message);
    }

    // 便捷方法：未授权
    private ResponseEntity<Map<String, Object>> unauthorized(String message) {
        return errorResponse(401, 401, message);
    }

    // 便捷方法：禁止访问
    private ResponseEntity<Map<String, Object>> forbidden(String message) {
        return errorResponse(403, 403, message);
    }

    // 便捷方法：资源不存在
    private ResponseEntity<Map<String, Object>> notFound(String message) {
        return errorResponse(404, 404, message);
    }

    @PostMapping("/register")
    public ResponseEntity<Map<String, Object>> register(@Valid @RequestBody RegisterCallbackRequest request, HttpServletRequest httpRequest) {
        String trackingId = request.getTrackingId();

        // 1. 风控校验（来源IP从服务端提取，不再信任请求体）
        String clientIp = getClientIp(httpRequest);
        if (clientIp == null || clientIp.isBlank()) {
            clientIp = "unknown";
        }
        String deviceFingerprint = request.getDeviceFingerprint();

        RiskCheckResult riskResult = riskGuardService.checkRisk(clientIp, deviceFingerprint);
        if (!riskResult.isPassed()) {
            log.warn("风控拦截: trackingId={}, ip={}, reason={}", trackingId, clientIp, riskResult.getCode());
            return forbidden(riskResult.getMessage());
        }

        // 2. 校验 tracking_id 是否存在且有效
        if (trackingId == null || trackingId.isBlank()) {
            log.warn("回调请求缺少tracking_id");
            return badRequest("tracking_id不能为空");
        }

        // 验证tracking_id是否存在于short_links表中
        var shortLinkOpt = shortLinkRepository.findByTrackingId(trackingId);
        if (shortLinkOpt.isEmpty()) {
            log.warn("无效的tracking_id: {}", trackingId);
            return notFound("tracking_id无效或已过期");
        }
        ShortLinkEntity shortLink = shortLinkOpt.get();

        // 2.5 校验 API Key 与 trackingId 的活动绑定关系
        Long apiKeyActivityId = (Long) httpRequest.getAttribute("activityId");
        if (apiKeyActivityId != null) {
            // API Key 关联了特定活动，必须匹配
            if (!apiKeyActivityId.equals(shortLink.getActivityId())) {
                log.warn("API Key活动绑定校验失败: apiKeyActivityId={}, trackingId对应的activityId={}",
                    apiKeyActivityId, shortLink.getActivityId());
                return forbidden("API Key与tracking_id不匹配：密钥只能用于其关联活动的回调");
            }
        }

        // 3. 幂等检查：已经处理过的tracking_id直接返回成功
        if (processedCallbackRepository.existsById(trackingId)) {
            log.debug("重复回调 tracking_id: {}", trackingId);
            Map<String, Object> data = new java.util.HashMap<>();
            data.put("tracking_id", trackingId);
            data.put("status", "already_processed");
            return successResponse("回调已处理（幂等）", data);
        }

        // 4. 记录回调
        ProcessedCallbackEntity e = new ProcessedCallbackEntity();
        e.setTrackingId(trackingId);
        e.setCreatedAt(java.time.OffsetDateTime.now(java.time.ZoneOffset.UTC));
        processedCallbackRepository.save(e);

        // 5. 加入奖励队列（使用tracking_id精确归因）
        rewardQueue.enqueueReward(trackingId, request.getExternalUserId(), null);
        Map<String, Object> data = new java.util.HashMap<>();
        data.put("tracking_id", trackingId);
        data.put("status", "registered");
        return successResponse("注册成功", data);
    }
}

