package com.pharmacopoeia.service;

import com.pharmacopoeia.config.DashScopeRateLimitProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 百炼 API 全局调用限流器（内存计数，重启清零）。
 * 控制后端 → 百炼的总调用量，与用户侧限流独立。
 */
@Service
public class DashScopeRateLimiter {

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

    private final DashScopeRateLimitProperties props;
    private final AtomicInteger minuteCount = new AtomicInteger(0);
    private final AtomicInteger hourCount = new AtomicInteger(0);
    private final AtomicInteger dayCount = new AtomicInteger(0);
    private volatile String currentDate = LocalDate.now().toString();
    private volatile int currentHour = java.time.LocalTime.now().getHour();

    public DashScopeRateLimiter(DashScopeRateLimitProperties props) {
        this.props = props;
    }

    /** 尝试获取一次调用许可。返回 true 表示放行，false 表示超限。 */
    public boolean tryAcquire() {
        if (!props.isEnabled()) return true;

        resetIfNeeded();

        if (props.getPerMinute() > 0 && minuteCount.incrementAndGet() > props.getPerMinute()) {
            log.warn("百炼 API 每分钟限流触发: {}/{}", minuteCount.get(), props.getPerMinute());
            return false;
        }
        if (props.getPerHour() > 0 && hourCount.incrementAndGet() > props.getPerHour()) {
            log.warn("百炼 API 每小时限流触发: {}/{}", hourCount.get(), props.getPerHour());
            return false;
        }
        if (props.getPerDay() > 0 && dayCount.incrementAndGet() > props.getPerDay()) {
            log.warn("百炼 API 每日限流触发: {}/{}", dayCount.get(), props.getPerDay());
            return false;
        }
        return true;
    }

    private void resetIfNeeded() {
        String today = LocalDate.now().toString();
        int nowHour = java.time.LocalTime.now().getHour();
        if (!currentDate.equals(today)) {
            dayCount.set(0);
            currentDate = today;
        }
        if (currentHour != nowHour) {
            hourCount.set(0);
            currentHour = nowHour;
        }
    }
}