package org.dromara.ai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.ai.domain.AiUserQuota;
import org.dromara.ai.domain.bo.AiUserQuotaBo;
import org.dromara.ai.domain.vo.AiUserQuotaVo;
import org.dromara.ai.mapper.AiUserQuotaMapper;
import org.dromara.ai.service.AiUserQuotaService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * AI用户配额Service业务层处理
 *
 * @author pengles
 */
@RequiredArgsConstructor
@Service
public class AiUserQuotaServiceImpl implements AiUserQuotaService {

    private final AiUserQuotaMapper baseMapper;

    /**
     * 查询AI用户配额
     */
    @Override
    public AiUserQuotaVo queryById(Long id) {
        AiUserQuotaVo vo = baseMapper.selectVoById(id);
        if (vo != null) {
            convertFields(vo);
        }
        return vo;
    }

    /**
     * 查询AI用户配额列表
     */
    @Override
    public TableDataInfo<AiUserQuotaVo> queryPageList(AiUserQuotaBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AiUserQuota> lqw = buildQueryWrapper(bo);
        Page<AiUserQuotaVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        result.getRecords().forEach(this::convertFields);
        return TableDataInfo.build(result);
    }

    /**
     * 查询AI用户配额列表
     */
    @Override
    public List<AiUserQuotaVo> queryList(AiUserQuotaBo bo) {
        LambdaQueryWrapper<AiUserQuota> lqw = buildQueryWrapper(bo);
        List<AiUserQuotaVo> list = baseMapper.selectVoList(lqw);
        list.forEach(this::convertFields);
        return list;
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<AiUserQuota> buildQueryWrapper(AiUserQuotaBo bo) {
        LambdaQueryWrapper<AiUserQuota> lqw = new LambdaQueryWrapper<>();
        lqw.eq(bo.getUserId() != null, AiUserQuota::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getPermissionLevel()), AiUserQuota::getPermissionLevel, bo.getPermissionLevel());
        // 时间范围查询
        lqw.ge(bo.getCreateTimeStart() != null, AiUserQuota::getCreateTime, bo.getCreateTimeStart());
        lqw.le(bo.getCreateTimeEnd() != null, AiUserQuota::getCreateTime, bo.getCreateTimeEnd());
        // 按创建时间倒序排序
        lqw.orderByDesc(AiUserQuota::getCreateTime);
        return lqw;
    }

    /**
     * 转换字段（用于显示）
     */
    private void convertFields(AiUserQuotaVo vo) {
        // 转换权限级别
        vo.setPermissionLevelStr(convertPermissionLevel(vo.getPermissionLevel()));
        // 计算剩余配额
        vo.setDailyRemaining(calculateRemaining(vo.getDailyQuota(), vo.getDailyUsed()));
        vo.setMonthlyRemaining(calculateRemaining(vo.getMonthlyQuota(), vo.getMonthlyUsed()));
    }

    /**
     * 转换权限级别
     */
    private String convertPermissionLevel(String permissionLevel) {
        if (StringUtils.isBlank(permissionLevel)) {
            return "";
        }
        return switch (permissionLevel) {
            case "GUEST" -> "访客";
            case "BASIC" -> "基础用户";
            case "PREMIUM" -> "高级用户";
            case "VIP" -> "VIP用户";
            case "ADMIN" -> "管理员";
            default -> permissionLevel;
        };
    }

    /**
     * 计算剩余配额
     */
    private Long calculateRemaining(Long quota, Long used) {
        if (quota == null || quota <= 0) {
            return -1L; // 无限制
        }
        if (used == null) {
            used = 0L;
        }
        return Math.max(0, quota - used);
    }

    /**
     * 新增AI用户配额
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(AiUserQuotaBo bo) {
        // 检查用户配额是否已存在
        LambdaQueryWrapper<AiUserQuota> lqw = new LambdaQueryWrapper<>();
        lqw.eq(AiUserQuota::getUserId, bo.getUserId());
        Long count = baseMapper.selectCount(lqw);
        if (count > 0) {
            throw new ServiceException("该用户的配额记录已存在");
        }

        AiUserQuota add = MapstructUtils.convert(bo, AiUserQuota.class);
        // 设置默认值
        if (StringUtils.isBlank(add.getPermissionLevel())) {
            add.setPermissionLevel("BASIC");
        }
        if (add.getDailyQuota() == null) {
            add.setDailyQuota(0L); // 默认无限制
        }
        if (add.getMonthlyQuota() == null) {
            add.setMonthlyQuota(0L); // 默认无限制
        }
        if (add.getDailyUsed() == null) {
            add.setDailyUsed(0L);
        }
        if (add.getMonthlyUsed() == null) {
            add.setMonthlyUsed(0L);
        }
        Date now = new Date();
        if (add.getLastResetDaily() == null) {
            add.setLastResetDaily(now);
        }
        if (add.getLastResetMonthly() == null) {
            add.setLastResetMonthly(now);
        }
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改AI用户配额
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(AiUserQuotaBo bo) {
        AiUserQuota update = MapstructUtils.convert(bo, AiUserQuota.class);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 批量删除AI用户配额
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // 可以添加业务校验逻辑
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 根据用户ID查询配额
     */
    @Override
    public AiUserQuotaVo queryByUserId(Long userId) {
        LambdaQueryWrapper<AiUserQuota> lqw = new LambdaQueryWrapper<>();
        lqw.eq(AiUserQuota::getUserId, userId);
        AiUserQuotaVo vo = baseMapper.selectVoOne(lqw);
        if (vo != null) {
            convertFields(vo);
        }
        return vo;
    }

    /**
     * 重置用户配额（按日/按月）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean resetQuota(Long userId, String resetType) {
        AiUserQuota quota = baseMapper.selectOne(new LambdaQueryWrapper<AiUserQuota>()
                .eq(AiUserQuota::getUserId, userId));
        if (quota == null) {
            throw new ServiceException("用户配额记录不存在");
        }

        Date now = new Date();
        if ("DAILY".equals(resetType)) {
            quota.setDailyUsed(0L);
            quota.setLastResetDaily(now);
        } else if ("MONTHLY".equals(resetType)) {
            quota.setMonthlyUsed(0L);
            quota.setLastResetMonthly(now);
        } else {
            throw new ServiceException("无效的重置类型");
        }

        return baseMapper.updateById(quota) > 0;
    }

    /**
     * 增加用户配额使用量
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean increaseUsage(Long userId, Long dailyAmount, Long monthlyAmount) {
        AiUserQuota quota = baseMapper.selectOne(new LambdaQueryWrapper<AiUserQuota>()
                .eq(AiUserQuota::getUserId, userId));
        if (quota == null) {
            // 如果配额记录不存在，创建一个默认记录
            quota = new AiUserQuota();
            quota.setUserId(userId);
            quota.setPermissionLevel("BASIC");
            quota.setDailyQuota(0L);
            quota.setMonthlyQuota(0L);
            quota.setDailyUsed(0L);
            quota.setMonthlyUsed(0L);
            Date now = new Date();
            quota.setLastResetDaily(now);
            quota.setLastResetMonthly(now);
            baseMapper.insert(quota);
        }

        Date now = new Date();
        // 检查是否需要重置日配额
        if (needResetDaily(quota.getLastResetDaily(), now)) {
            quota.setDailyUsed(0L);
            quota.setLastResetDaily(now);
        }
        // 检查是否需要重置月配额
        if (needResetMonthly(quota.getLastResetMonthly(), now)) {
            quota.setMonthlyUsed(0L);
            quota.setLastResetMonthly(now);
        }

        // 增加使用量
        if (dailyAmount != null && dailyAmount > 0) {
            quota.setDailyUsed((quota.getDailyUsed() != null ? quota.getDailyUsed() : 0L) + dailyAmount);
        }
        if (monthlyAmount != null && monthlyAmount > 0) {
            quota.setMonthlyUsed((quota.getMonthlyUsed() != null ? quota.getMonthlyUsed() : 0L) + monthlyAmount);
        }

        return baseMapper.updateById(quota) > 0;
    }

    /**
     * 检查是否需要重置日配额
     */
    private boolean needResetDaily(Date lastReset, Date now) {
        if (lastReset == null) {
            return true;
        }
        Calendar last = Calendar.getInstance();
        last.setTime(lastReset);
        Calendar current = Calendar.getInstance();
        current.setTime(now);
        return last.get(Calendar.YEAR) != current.get(Calendar.YEAR) ||
                last.get(Calendar.DAY_OF_YEAR) != current.get(Calendar.DAY_OF_YEAR);
    }

    /**
     * 检查是否需要重置月配额
     */
    private boolean needResetMonthly(Date lastReset, Date now) {
        if (lastReset == null) {
            return true;
        }
        Calendar last = Calendar.getInstance();
        last.setTime(lastReset);
        Calendar current = Calendar.getInstance();
        current.setTime(now);
        return last.get(Calendar.YEAR) != current.get(Calendar.YEAR) ||
                last.get(Calendar.MONTH) != current.get(Calendar.MONTH);
    }

}
