package com.mosquito.project.job;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.UUID;

/**
 * 内部奖励发放适配器
 * 对接内部账户系统API，支持超时、重试、幂等键
 */
@Component
public class InternalRewardDistributor implements RewardJobProcessor.RewardDistributor {

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

    @Value("${app.internal-account.api-url:}")
    private String apiUrl;

    @Value("${app.internal-account.api-key:}")
    private String apiKey;

    @Value("${app.internal-account.timeout:5000}")
    private int timeout;

    /**
     * 是否允许模拟成功模式（仅开发/测试环境使用）
     * 生产环境必须设置为false，否则可能造成"假成功发放"
     */
    @Value("${app.internal-account.allow-mock-success:false}")
    private boolean allowMockSuccess;

    private final RestTemplate restTemplate;

    public InternalRewardDistributor(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public boolean distribute(Long userId, Long activityId, String trackingId, int points, String rewardType) {
        // 生成幂等键，确保重试不会重复发放
        String idempotencyKey = generateIdempotencyKey(userId, activityId, trackingId);

        log.info("发放奖励: userId={}, activityId={}, trackingId={}, points={}, type={}, idempotencyKey={}, allowMockSuccess={}",
            userId, activityId, trackingId, points, rewardType, idempotencyKey, allowMockSuccess);

        // 如果未配置API地址
        if (apiUrl == null || apiUrl.isBlank()) {
            // 生产环境(Fail-Closed)：不允许模拟成功，返回false进入重试队列
            if (!allowMockSuccess) {
                log.error("内部账户系统API地址未配置且不允许模拟成功，奖励发放失败，请检查配置");
                return false;
            }
            // 开发/测试环境：允许模拟成功
            log.warn("内部账户系统API地址未配置，模拟奖励发放成功（仅开发环境）");
            return true;
        }

        try {
            return callInternalAccountApi(userId, points, rewardType, idempotencyKey);
        } catch (Exception e) {
            log.error("奖励发放失败: userId={}, error={}", userId, e.getMessage());
            return false;
        }
    }

    /**
     * 调用内部账户系统API
     */
    private boolean callInternalAccountApi(Long userId, int points, String rewardType, String idempotencyKey) {
        // 构建请求体
        String requestBody = String.format(
            "{\"userId\":%d,\"points\":%d,\"type\":\"%s\",\"idempotencyKey\":\"%s\"}",
            userId, points, rewardType, idempotencyKey
        );

        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        if (apiKey != null && !apiKey.isBlank()) {
            headers.set("X-API-Key", apiKey);
        }
        headers.set("X-Idempotency-Key", idempotencyKey);

        HttpEntity<String> request = new HttpEntity<>(requestBody, headers);

        try {
            ResponseEntity<String> response = restTemplate.exchange(
                apiUrl + "/api/v1/points/grant",
                HttpMethod.POST,
                request,
                String.class
            );

            if (response.getStatusCode() == HttpStatus.OK || response.getStatusCode() == HttpStatus.CREATED) {
                log.info("奖励发放成功: userId={}, response={}", userId, response.getBody());
                return true;
            } else {
                log.error("奖励发放失败: userId={}, status={}", userId, response.getStatusCode());
                return false;
            }
        } catch (Exception e) {
            log.error("调用内部账户系统API异常: userId={}, error={}", userId, e.getMessage());
            throw e;
        }
    }

    /**
     * 生成幂等键
     */
    private String generateIdempotencyKey(Long userId, Long activityId, String trackingId) {
        return UUID.nameUUIDFromBytes(
            String.format("%d-%d-%s", userId, activityId, trackingId).getBytes()
        ).toString();
    }
}
