package com.ruoyi.generator.service.front;

import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.generator.domain.front.AiQuotaBucket;
import com.ruoyi.generator.domain.front.dto.AiQuotaResponse;
import com.ruoyi.generator.mapper.front.AiQuotaBucketMapper;

@Service
public class AiQuotaService
{
    private static final int DAILY_TASK_LIMIT = 20;
    private static final int MONTHLY_COST_LIMIT_CENTS = 5000;
    private static final int RUNNING_LIMIT = 1;

    @Autowired(required = false)
    private AiQuotaBucketMapper aiQuotaBucketMapper;

    @Transactional
    public void reserve(Long userId)
    {
        if (aiQuotaBucketMapper == null)
        {
            return;
        }
        AiQuotaBucket day = ensureBucket(userId, "DAY", new SimpleDateFormat("yyyyMMdd").format(new Date()));
        AiQuotaBucket month = ensureBucket(userId, "MONTH", new SimpleDateFormat("yyyyMM").format(new Date()));
        if (safe(day.getTaskUsed()) >= safe(day.getTaskLimit()))
        {
            throw new ServiceException("今日 AI 生成次数已用完");
        }
        if (safe(month.getCostUsedCents()) >= safe(month.getCostLimitCents()))
        {
            throw new ServiceException("本月 AI 生成成本配额已用完");
        }
        if (safe(day.getRunningCount()) >= safe(day.getRunningLimit()))
        {
            throw new ServiceException("已有 AI 生成任务正在执行，请稍后再试");
        }
        day.setTaskUsed(safe(day.getTaskUsed()) + 1);
        day.setRunningCount(safe(day.getRunningCount()) + 1);
        aiQuotaBucketMapper.updateQuotaBucket(day);
    }

    @Transactional
    public void releaseRunning(Long userId)
    {
        if (aiQuotaBucketMapper == null)
        {
            return;
        }
        AiQuotaBucket day = ensureBucket(userId, "DAY", new SimpleDateFormat("yyyyMMdd").format(new Date()));
        day.setRunningCount(Math.max(0, safe(day.getRunningCount()) - 1));
        aiQuotaBucketMapper.updateQuotaBucket(day);
    }

    @Transactional
    public void settleCost(Long userId, int totalTokens, int costCents)
    {
        if (aiQuotaBucketMapper == null)
        {
            return;
        }
        AiQuotaBucket month = ensureBucket(userId, "MONTH", new SimpleDateFormat("yyyyMM").format(new Date()));
        month.setTokenUsed(safe(month.getTokenUsed()) + Math.max(totalTokens, 0));
        month.setCostUsedCents(safe(month.getCostUsedCents()) + Math.max(costCents, 0));
        aiQuotaBucketMapper.updateQuotaBucket(month);
    }

    public AiQuotaResponse getQuota(Long userId)
    {
        AiQuotaResponse response = new AiQuotaResponse();
        response.setDailyTaskLimit(DAILY_TASK_LIMIT);
        response.setDailyTaskUsed(0);
        response.setMonthlyCostLimitCents(MONTHLY_COST_LIMIT_CENTS);
        response.setMonthlyCostUsedCents(0);
        response.setRunningLimit(RUNNING_LIMIT);
        response.setRunningCount(0);
        if (aiQuotaBucketMapper != null)
        {
            AiQuotaBucket day = aiQuotaBucketMapper.selectQuotaBucket(userId, "DAY", new SimpleDateFormat("yyyyMMdd").format(new Date()));
            AiQuotaBucket month = aiQuotaBucketMapper.selectQuotaBucket(userId, "MONTH", new SimpleDateFormat("yyyyMM").format(new Date()));
            if (day != null)
            {
                response.setDailyTaskUsed(safe(day.getTaskUsed()));
                response.setRunningCount(safe(day.getRunningCount()));
            }
            if (month != null)
            {
                response.setMonthlyCostUsedCents(safe(month.getCostUsedCents()));
            }
        }
        return response;
    }

    private AiQuotaBucket ensureBucket(Long userId, String periodType, String periodKey)
    {
        AiQuotaBucket bucket = aiQuotaBucketMapper.selectQuotaBucket(userId, periodType, periodKey);
        if (bucket != null)
        {
            return bucket;
        }
        bucket = new AiQuotaBucket();
        bucket.setUserId(userId);
        bucket.setPeriodType(periodType);
        bucket.setPeriodKey(periodKey);
        bucket.setTaskLimit("DAY".equals(periodType) ? DAILY_TASK_LIMIT : 0);
        bucket.setTaskUsed(0);
        bucket.setTokenLimit(0);
        bucket.setTokenUsed(0);
        bucket.setCostLimitCents("MONTH".equals(periodType) ? MONTHLY_COST_LIMIT_CENTS : 0);
        bucket.setCostUsedCents(0);
        bucket.setRunningLimit("DAY".equals(periodType) ? RUNNING_LIMIT : 0);
        bucket.setRunningCount(0);
        aiQuotaBucketMapper.insertQuotaBucket(bucket);
        return bucket;
    }

    private int safe(Integer value)
    {
        return value == null ? 0 : value;
    }
}
