package org.jeecg.modules.adweb.quota.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.ibatis.reflection.property.PropertyNamer;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.FastJsonUtil;
import org.jeecg.modules.adweb.gpt.entity.ChatHistory;
import org.jeecg.modules.adweb.gpt.service.IChatHistoryService;
import org.jeecg.modules.adweb.gpt.vo.ChatHistoryVO;
import org.jeecg.modules.adweb.quota.entity.ResourceQuota;
import org.jeecg.modules.adweb.quota.mapper.ResourceQuotaMapper;
import org.jeecg.modules.adweb.quota.service.IResourceQuotaService;
import org.jeecg.modules.adweb.quota.vo.ResourceQuotaVO;
import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * @Description: adweb_resource_quota
 * @Author: jeecg-boot
 * @Date: 2025-12-07
 * @Version: V1.0
 */
@Slf4j
@Service
public class ResourceQuotaServiceImpl extends ServiceImpl<ResourceQuotaMapper, ResourceQuota>
        implements IResourceQuotaService {

    // ResourceQuota entity对应的数据库列名称
    private static final String DB_COLUMN_CUSTOMS_DATA_USAGE =
            StringUtils.camelToUnderline(
                    PropertyNamer.methodToProperty(
                            LambdaUtils.extract(ResourceQuota::getCustomsDataUsage)
                                    .getImplMethodName()));

    @Value("${resource-quota.default-website-quota}")
    private int defaultWebsiteQuota;

    @Value("${resource-quota.default-ai-power-quota}")
    private int defaultAiPowerQuota;

    @Value("${resource-quota.default-customs-data-quota}")
    private int defaultCustomsDataQuota;

    @Autowired private IAdwebSiteService adwebSiteService;

    @Autowired private IChatHistoryService chatHistoryService;

    @Override
    public ResourceQuotaVO getResourceQuotaByUid(String uid) {
        ResourceQuota resourceQuota = this.getResourceQuota(uid);

        ResourceQuotaVO resourceQuotaVO = new ResourceQuotaVO();
        resourceQuotaVO.setUid(uid);
        resourceQuotaVO.setWebsiteQuota(resourceQuota.getWebsiteQuota());
        resourceQuotaVO.setWebsiteUsage(0);
        resourceQuotaVO.setAiPowerQuota(resourceQuota.getAiPowerQuota());
        resourceQuotaVO.setAiPowerUsage(0);
        resourceQuotaVO.setCustomsDataQuota(resourceQuota.getCustomsDataQuota());
        resourceQuotaVO.setCustomsDataUsage(resourceQuota.getCustomsDataUsage());

        return resourceQuotaVO;
    }

    @Override
    public boolean updateResourceQuota(ResourceQuotaVO resourceQuotaVO) {
        ResourceQuota resourceQuota = this.getResourceQuota(resourceQuotaVO.getUid());

        // 检查是否有额度字段更新
        if (resourceQuota.getWebsiteQuota() != resourceQuotaVO.getWebsiteQuota()
                || resourceQuota.getAiPowerQuota() != resourceQuotaVO.getAiPowerQuota()
                || resourceQuota.getCustomsDataQuota() != resourceQuotaVO.getCustomsDataQuota()) {
            resourceQuota.setWebsiteQuota(resourceQuotaVO.getWebsiteQuota());
            resourceQuota.setAiPowerQuota(resourceQuotaVO.getAiPowerQuota());
            resourceQuota.setCustomsDataQuota(resourceQuotaVO.getCustomsDataQuota());

            this.saveOrUpdate(resourceQuota);
            log.info(
                    "管理员 {} 为用户 {} 更新资源额度 {}",
                    this.getLoginUser().getUsername(),
                    resourceQuotaVO.getUid(),
                    FastJsonUtil.toJSONString(resourceQuota));
            return true;
        }

        return false;
    }

    @Override
    public Pair<Integer, Integer> getWebsiteQuota(String uid) {
        return Pair.of(
                this.getResourceQuota(uid).getWebsiteQuota(),
                adwebSiteService.getAllSiteIdByUid(uid).size());
    }

    @Override
    public Pair<Integer, Integer> getAIPowerQuota(String uid) {
        long aiPowerUsage =
                chatHistoryService.getChatHistoriesByUid(uid).stream()
                        .map(ChatHistory::getContent)
                        .filter(StringUtils::isNotBlank)
                        .map(
                                content ->
                                        FastJsonUtil.parseObject(
                                                content, ChatHistoryVO.Content.class))
                        .filter(Objects::nonNull)
                        .map(content -> content.getChat())
                        .flatMap(List::stream)
                        .map(ChatHistoryVO.Content.Chat::getData)
                        .flatMap(List::stream)
                        .filter(
                                chatData ->
                                        BooleanUtils.isFalse(chatData.isError())
                                                &&
                                                // AI生成的消息
                                                BooleanUtils.isFalse(chatData.isInversion()))
                        .count();

        return Pair.of(this.getResourceQuota(uid).getAiPowerQuota(), (int) aiPowerUsage);
    }

    @Override
    public Pair<Integer, Integer> getCustomsDataQuota(String uid) {
        ResourceQuota resourceQuota = this.getResourceQuota(uid);
        return Pair.of(resourceQuota.getCustomsDataQuota(), resourceQuota.getCustomsDataUsage());
    }

    @Override
    public boolean consumeCustomsDataQuota(String uid) {
        Wrapper<ResourceQuota> updateWrapper =
                Wrappers.lambdaUpdate(ResourceQuota.class)
                        .eq(ResourceQuota::getUid, uid)
                        .setSql(
                                StringUtils.isNotBlank(DB_COLUMN_CUSTOMS_DATA_USAGE),
                                String.format(
                                        "%s = %s + 1",
                                        DB_COLUMN_CUSTOMS_DATA_USAGE,
                                        DB_COLUMN_CUSTOMS_DATA_USAGE));
        return this.update(updateWrapper);
    }

    /**
     * 获取用户{@link ResourceQuota}记录
     *
     * @param uid
     * @return
     */
    private ResourceQuota getResourceQuota(String uid) {
        // 1. 根据uid查询
        ResourceQuota resourceQuota =
                this.getOne(new LambdaQueryWrapper<ResourceQuota>().eq(ResourceQuota::getUid, uid));
        if (Objects.nonNull(resourceQuota)) {
            return resourceQuota;
        }

        // 2. 初始化DB entity
        log.info("用户 {} 未配置资源额度", uid);
        resourceQuota = new ResourceQuota();
        resourceQuota.setUid(uid);
        resourceQuota.setWebsiteQuota(defaultWebsiteQuota);
        resourceQuota.setAiPowerQuota(defaultAiPowerQuota);
        resourceQuota.setCustomsDataQuota(defaultCustomsDataQuota);
        resourceQuota.setCustomsDataUsage(0);

        // 3. 更新数据库
        this.save(resourceQuota);
        log.info(
                "管理员 {} 为用户 {} 配置资源额度 {}",
                this.getLoginUser().getUsername(),
                uid,
                FastJsonUtil.toJSONString(resourceQuota));

        return resourceQuota;
    }

    /** 获取当前登陆用户 */
    private LoginUser getLoginUser() {
        return (LoginUser) SecurityUtils.getSubject().getPrincipal();
    }
}
