package com.ssyf.third.bmiss.services;

import com.ssyf.module.robot.domain.vo.FeeStatistics;
import com.ssyf.module.robot.service.RRobotFeeService;
import com.ssyf.third.bmiss.model.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 资金池服务类
 * 提供资金池查询、资金申请等功能，并支持Redis缓存
 * 
 * @author system
 * @since 1.0
 */
@Slf4j
@Service
public class FundPoolService {

    private static final String FUND_POOL_CACHE_KEY = "fund:pool:total";
    private static final String FUND_POOL_DETAIL_CACHE_KEY = "fund:pool:detail";
    private static final String FUND_APPLY_LOCK_PREFIX = "fund:apply:lock:";
    private static final long DEFAULT_CACHE_TTL = 5 * 60; // 5分钟
    
    @Autowired
    private BusinessService businessService;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private RRobotFeeService rRobotFeeService;
    
    /**
     * 获取资金池总资金
     * 优先从缓存获取，缓存不存在时调用BusinessService获取并缓存
     * 
     * @return 资金池总资金
     */
    public Double getTotalFund() {
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        
        // 从缓存获取
        Double cachedFund = (Double) ops.get(FUND_POOL_CACHE_KEY);
        if (cachedFund != null) {
            log.info("从缓存获取资金池总资金: {}", cachedFund);
            return cachedFund;
        }
        
        // 缓存不存在，调用业务服务获取资金池详情
        ApiResponse<Double> response = businessService.getRobotFundPool();
        
        Double totalFund = null;
        if (response != null && response.getCode() == 200 && response.getData() != null) {
            totalFund = response.getData();
        }
        
        // 缓存结果
        if (totalFund != null) {
            ops.set(FUND_POOL_CACHE_KEY, totalFund, DEFAULT_CACHE_TTL, TimeUnit.SECONDS);
            
            // 同时缓存资金池详情
            if (response != null && response.getData() != null) {
                ops.set(FUND_POOL_DETAIL_CACHE_KEY, response.getData(), DEFAULT_CACHE_TTL, TimeUnit.SECONDS);
            }
            
            log.info("资金池信息已缓存，总资金: {}, TTL: {}秒", totalFund, DEFAULT_CACHE_TTL);
        }
        
        return totalFund;
    }
    
    /**
     * 申请资金
     * 需要全局锁，防止并发申请
     * 
     * @param amount 申请金额
     * @return 申请结果
     */
    public ApiResponse<Object> applyForBalance(Integer userId, String reason, Double amount) {
        if (amount == null || amount <= 0) {
            return ApiResponse.error("申请金额必须大于0");
        }
        
        String lockKey = FUND_APPLY_LOCK_PREFIX + "global";
        
        // 使用Redis分布式锁
        Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "locked", 30, TimeUnit.SECONDS);
        
        if (lockAcquired != null && lockAcquired) {
            try {
                log.info("获取资金申请锁成功，申请金额: {}", amount);
                
                // 检查当前资金池余额
                Double currentFund = getTotalFund();
                if (currentFund == null) {
                    return ApiResponse.error("无法获取当前资金池信息");
                }
                
                // 检查余额是否足够
                if (currentFund < amount) {
                    log.warn("资金池余额不足，当前余额: {}，申请金额: {}", currentFund, amount);
                    return ApiResponse.error("资金池余额不足");
                }
                
                // 调用业务服务申请资金
                ApiResponse<Object> response = businessService.applyForBalance(userId, reason, amount, null);
                
                // 申请成功后更新资金池缓存
                if (response != null && response.getCode() == 200) {
                    updateFundPoolAfterApply(amount);
                    log.info("资金申请成功，已更新资金池缓存，申请金额: {}", amount);
                }
                
                return response;
            } finally {
                // 释放锁
                redisTemplate.delete(lockKey);
                log.info("释放资金申请锁");
            }
        } else {
            log.warn("获取资金申请锁失败，可能正在处理其他申请请求");
            return ApiResponse.error("资金申请请求过于频繁，请稍后重试");
        }
    }
    
    /**
     * 重置资金池缓存
     */
    public void resetCache() {
        clearFundPoolCache();
        log.info("资金池服务缓存已重置");
    }
    
    /**
     * 清空资金池缓存
     */
    public void clearFundPoolCache() {
        // 清除资金池总资金缓存
        redisTemplate.delete(FUND_POOL_CACHE_KEY);
        
        // 清除资金池详情缓存
        redisTemplate.delete(FUND_POOL_DETAIL_CACHE_KEY);
        
        log.info("资金池服务缓存已清空");
    }
    
    /**
     * 申请资金后更新资金池缓存
     * 
     * @param appliedAmount 申请金额
     */
    private void updateFundPoolAfterApply(Double appliedAmount) {
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        
        // 获取当前缓存的总资金
        Double currentFund = (Double) ops.get(FUND_POOL_CACHE_KEY);
        if (currentFund != null) {
            // 更新总资金
            Double newFund = currentFund - appliedAmount;
            ops.set(FUND_POOL_CACHE_KEY, newFund, DEFAULT_CACHE_TTL, TimeUnit.SECONDS);
            
            log.info("资金池缓存已更新，原余额: {}，申请金额: {}，新余额: {}", 
                    currentFund, appliedAmount, newFund);
        } else {
            // 如果缓存不存在，清除缓存，下次会自动重新获取
            clearFundPoolCache();
            log.info("资金池缓存不存在，已清除缓存，下次将重新获取");
        }
    }
    
    /**
     * 获取资金池详情
     * 
     * @return 资金池详情
     */
    public Double getFundPoolDetail() {
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        
        // 从缓存获取
        Double cachedDetail = (Double) ops.get(FUND_POOL_DETAIL_CACHE_KEY);
        if (cachedDetail != null) {
            log.info("从缓存获取资金池详情");
            return cachedDetail;
        }
        
        // 缓存不存在，调用业务服务获取
        ApiResponse<Double> response = businessService.getRobotFundPool();
        
        Double detail = null;
        if (response != null && response.getCode() == 200 && response.getData() != null) {
            detail = response.getData();
            
            // 缓存结果
            ops.set(FUND_POOL_DETAIL_CACHE_KEY, detail, DEFAULT_CACHE_TTL, TimeUnit.SECONDS);
            
            // 同时缓存总资金
            ops.set(FUND_POOL_CACHE_KEY, detail, DEFAULT_CACHE_TTL, TimeUnit.SECONDS);
            
            log.info("资金池详情已缓存，TTL: {}秒", DEFAULT_CACHE_TTL);
        }
        
        return detail;
    }
}