package org.dromara.system.service;

import lombok.extern.slf4j.Slf4j;
import org.dromara.system.domain.AiUserBalance;
import org.dromara.system.domain.SysTenant;
import org.dromara.system.mapper.AiUserBalanceMapper;
import org.dromara.system.mapper.SysTenantMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AiRedisSyncService implements ApplicationRunner {

    @Autowired
    private AiUserBalanceMapper balanceMapper;

    @Autowired
    private SysTenantMapper sysTenantMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    // OneAPI 实际读取的 Key
    private static final String KEY_TENANT_STATUS = "tenant_status_%s";
    private static final String KEY_WALLET_STATUS = "wallet_status_%s";
    private static final String KEY_USER_BALANCE = "user_balance_%s";
    private static final String KEY_WARN_THRESHOLD = "warn_threshold_%s";
// 原第38行：[BUG-7] video_task_max 只出现在已禁用的 Redis 同步死代码中
    private static final String KEY_VIDEO_TASK_MAX = "video_task_max_%s";

    @Override
// 原第41行：[BUG-15] 启动只打日志“[暂时不用]”，同步逻辑全部注释禁用
    public void run(ApplicationArguments args) {
        log.info("[AiRedisSync] 启动时全量同步...[暂时不用]");
        //syncAll();
    }

    //@Scheduled(cron = "0 0 2 * * ?")
    public void dailyRefresh() {
        log.info("[AiRedisSync] 开始每日兜底刷新...");
        //syncAll();
    }

    private void syncAll() {
        List<AiUserBalance> list = balanceMapper.selectList(null);
        if (list == null || list.isEmpty()) {
            log.warn("[AiRedisSync] ai_user_balance 表为空，跳过同步");
            return;
        }

        List<SysTenant> tenants = sysTenantMapper.selectList();
        Map<String, SysTenant> tenantMap = tenants.stream()
            .collect(Collectors.toMap(SysTenant::getTenantId, Function.identity(), (a, b) -> a));

        int success = 0;
        for (AiUserBalance item : list) {
            try {
                syncOne(item, tenantMap);
                success++;
            } catch (Exception e) {
                log.error("[AiRedisSync] 同步失败, tenantId={}", item.getTenantId(), e);
            }
        }
        log.info("[AiRedisSync] 全量同步完成, total={}, success={}", list.size(), success);
    }

    public void syncOne(AiUserBalance item, Map<String, SysTenant> tenantMap) {
        String tenantId = item.getTenantId();
        if (tenantId == null || tenantId.isEmpty()) {
            return;
        }

        SysTenant tenant = tenantMap.get(tenantId);
        String tenantStatusStr = (tenant != null) ? String.valueOf(tenant.getStatus()) : "1";

        // 钱包状态：正常 → "0"，冻结 → "1"
        String balanceStatusStr = (item.getStatus() != null) ? String.valueOf(item.getStatus()) : "1";

        // 余额：元 → 毫厘（*1000，取整）
        long balanceLi = item.getBalance();

        // 预警阈值（保持原样，元）
        String warnThresholdStr = item.getWarnThreshold() != null ? String.valueOf(item.getWarnThreshold()) : "10";

        // 视频任务上限（保持原样，整数）
        String videoTaskMaxStr = item.getVideoTaskMax() != null ? String.valueOf(item.getVideoTaskMax()) : "5";

        // 写入 Redis
        redisTemplate.opsForValue().set(String.format(KEY_TENANT_STATUS, tenantId), tenantStatusStr, 7, TimeUnit.DAYS);
        redisTemplate.opsForValue().set(String.format(KEY_WALLET_STATUS, tenantId), balanceStatusStr, 7, TimeUnit.DAYS);
        redisTemplate.opsForValue().set(String.format(KEY_USER_BALANCE, tenantId), String.valueOf(balanceLi), 7, TimeUnit.DAYS);
        redisTemplate.opsForValue().set(String.format(KEY_WARN_THRESHOLD, tenantId), warnThresholdStr, 7, TimeUnit.DAYS);
        redisTemplate.opsForValue().set(String.format(KEY_VIDEO_TASK_MAX, tenantId), videoTaskMaxStr, 7, TimeUnit.DAYS);

        log.info("[AiRedisSync] synced tenantId={}, balanceLi={}, tenantStatus={}, walletStatus={}, warnThreshold={}, videoTaskMax={}",
            tenantId, balanceLi, tenantStatusStr, balanceStatusStr, warnThresholdStr, videoTaskMaxStr);
    }

    /**
     * 充值：原子加（单位：元，内部转毫厘）
     * addedYuan 毫厘
     */
    public void addBalance(String tenantId, Long addedYuan) {
        redisTemplate.opsForValue().increment(String.format(KEY_USER_BALANCE, tenantId), addedYuan);
        redisTemplate.expire(String.format(KEY_USER_BALANCE, tenantId), 7, TimeUnit.DAYS);
        log.info("[AiRedisSync] 充值 tenantId={}, +{}毫厘", tenantId, addedYuan);
    }

    /**
     * 扣费：原子减（单位：元，内部转毫厘）
     * 返回扣减后的余额（毫厘），余额不足返回 null
     * costYuan 毫厘
     */
    public Long deductBalance(String tenantId, Long costYuan) {
        String key = String.format(KEY_USER_BALANCE, tenantId);
        // 不检查余额，直接原子扣减（允许变负数）
        Long remaining = redisTemplate.opsForValue().decrement(key, costYuan);
        redisTemplate.expire(key, 7, TimeUnit.DAYS);

        log.info("[AiRedisSync] 扣费 tenantId={}, -{}毫厘, 剩余{}毫厘", tenantId, costYuan, remaining);
        return remaining;  // 可能是负数
    }

    /**
     * 正常 → "0"，冻结 → "1"
     */
    public void updateTenantStatus(String tenantId, Integer status) {
        String statusStr = status != null ? String.valueOf(status) : "1";
        redisTemplate.opsForValue().set(String.format(KEY_TENANT_STATUS, tenantId), statusStr, 7, TimeUnit.DAYS);
        log.info("[AiRedisSync] 租户状态更新 tenantId={}, status={}", tenantId, statusStr);
    }

    /**
     * 正常 → "0"，冻结 → "1"
     */
    public void updateWalletStatus(String tenantId, Integer status) {
        String statusStr = status != null ? String.valueOf(status) : "1";
        redisTemplate.opsForValue().set(String.format(KEY_WALLET_STATUS, tenantId), statusStr, 7, TimeUnit.DAYS);
        log.info("[AiRedisSync] 钱包状态更新 tenantId={}, status={}", tenantId, statusStr);
    }

    public void updateWarnThreshold(String tenantId, Long warnThreshold) {
        String warnThresholdStr = warnThreshold != null ? warnThreshold.toString() : "10";
        redisTemplate.opsForValue().set(String.format(KEY_WARN_THRESHOLD, tenantId), warnThresholdStr, 7, TimeUnit.DAYS);
        log.info("[AiRedisSync] 预警阈值更新 tenantId={}, warnThreshold={}", tenantId, warnThresholdStr);
    }

    public void updateVideoTaskMax(String tenantId, Integer videoTaskMax) {
        String videoTaskMaxStr = videoTaskMax != null ? String.valueOf(videoTaskMax) : "5";
        redisTemplate.opsForValue().set(String.format(KEY_VIDEO_TASK_MAX, tenantId), videoTaskMaxStr, 7, TimeUnit.DAYS);
        log.info("[AiRedisSync] 视频任务上限更新 tenantId={}, videoTaskMax={}", tenantId, videoTaskMaxStr);
    }

    public void deleteUser(String tenantId) {
        redisTemplate.delete(String.format(KEY_TENANT_STATUS, tenantId));
        redisTemplate.delete(String.format(KEY_WALLET_STATUS, tenantId));
        redisTemplate.delete(String.format(KEY_USER_BALANCE, tenantId));
        redisTemplate.delete(String.format(KEY_WARN_THRESHOLD, tenantId));
        redisTemplate.delete(String.format(KEY_VIDEO_TASK_MAX, tenantId));
        log.info("[AiRedisSync] 删除用户 tenantId={}", tenantId);
    }
}
