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 lombok.extern.slf4j.Slf4j;
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.AiUsageStats;
import org.dromara.ai.domain.bo.AiUsageStatsBo;
import org.dromara.ai.domain.vo.AiUsageStatsVo;
import org.dromara.ai.mapper.AiUsageStatsMapper;
import org.dromara.ai.service.AiUsageStatsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * AI使用统计Service业务层处理
 *
 * @author pengles
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class AiUsageStatsServiceImpl implements AiUsageStatsService {

    private final AiUsageStatsMapper baseMapper;

    /**
     * 查询AI使用统计
     */
    @Override
    public AiUsageStatsVo queryById(Long id) {
        AiUsageStatsVo vo = baseMapper.selectVoById(id);
        if (vo != null) {
            calculateSuccessRate(vo);
        }
        return vo;
    }

    /**
     * 查询AI使用统计列表
     */
    @Override
    public TableDataInfo<AiUsageStatsVo> queryPageList(AiUsageStatsBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AiUsageStats> lqw = buildQueryWrapper(bo);
        Page<AiUsageStatsVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        // 计算成功率
        result.getRecords().forEach(this::calculateSuccessRate);
        return TableDataInfo.build(result);
    }

    /**
     * 查询AI使用统计列表
     */
    @Override
    public List<AiUsageStatsVo> queryList(AiUsageStatsBo bo) {
        LambdaQueryWrapper<AiUsageStats> lqw = buildQueryWrapper(bo);
        List<AiUsageStatsVo> list = baseMapper.selectVoList(lqw);
        // 计算成功率
        list.forEach(this::calculateSuccessRate);
        return list;
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<AiUsageStats> buildQueryWrapper(AiUsageStatsBo bo) {
        LambdaQueryWrapper<AiUsageStats> lqw = new LambdaQueryWrapper<>();
        lqw.eq(bo.getUserId() != null, AiUsageStats::getUserId, bo.getUserId());
        lqw.like(StringUtils.isNotBlank(bo.getProviderName()), AiUsageStats::getProviderName, bo.getProviderName());
        lqw.like(StringUtils.isNotBlank(bo.getModelName()), AiUsageStats::getModelName, bo.getModelName());
        // 时间范围查询
        lqw.ge(bo.getStatDateStart() != null, AiUsageStats::getStatDate, bo.getStatDateStart());
        lqw.le(bo.getStatDateEnd() != null, AiUsageStats::getStatDate, bo.getStatDateEnd());
        // 按统计日期倒序
        lqw.orderByDesc(AiUsageStats::getStatDate);
        return lqw;
    }

    /**
     * 记录使用统计
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recordUsage(Long userId, String providerName, String modelName,
                           Long tokens, BigDecimal cost, Integer responseTime, Boolean success) {
        if (userId == null || StringUtils.isBlank(providerName)) {
            return;
        }

        try {
            // 获取今天的日期（只取日期部分，忽略时间）
            LocalDate localDate = LocalDate.now();
            Date statDate = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());

            // 查询是否存在当天的统计记录
            LambdaQueryWrapper<AiUsageStats> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(AiUsageStats::getUserId, userId)
                    .eq(AiUsageStats::getProviderName, providerName)
                    .eq(statDate != null, AiUsageStats::getStatDate, statDate);
            if (StringUtils.isNotBlank(modelName)) {
                queryWrapper.eq(AiUsageStats::getModelName, modelName);
            } else {
                queryWrapper.isNull(AiUsageStats::getModelName);
            }

            AiUsageStats existing = baseMapper.selectOne(queryWrapper);

            if (existing != null) {
                // 更新现有记录
                existing.setRequestCount((existing.getRequestCount() != null ? existing.getRequestCount() : 0) + 1);
                if (success) {
                    existing.setSuccessCount((existing.getSuccessCount() != null ? existing.getSuccessCount() : 0) + 1);
                } else {
                    existing.setErrorCount((existing.getErrorCount() != null ? existing.getErrorCount() : 0) + 1);
                }
                if (tokens != null && tokens > 0) {
                    existing.setTotalTokens((existing.getTotalTokens() != null ? existing.getTotalTokens() : 0L) + tokens);
                }
                if (cost != null && cost.compareTo(BigDecimal.ZERO) > 0) {
                    existing.setTotalCost((existing.getTotalCost() != null ? existing.getTotalCost() : BigDecimal.ZERO).add(cost));
                }
                // 重新计算平均响应时间
                if (responseTime != null && responseTime > 0) {
                    int oldRequestCount = existing.getRequestCount() - 1;
                    int oldAvgResponseTime = existing.getAvgResponseTime() != null ? existing.getAvgResponseTime() : 0;
                    int newAvgResponseTime = (oldAvgResponseTime * oldRequestCount + responseTime) / existing.getRequestCount();
                    existing.setAvgResponseTime(newAvgResponseTime);
                }

                baseMapper.updateById(existing);
            } else {
                // 插入新记录
                AiUsageStats stats = new AiUsageStats();
                stats.setUserId(userId);
                stats.setProviderName(providerName);
                stats.setModelName(modelName);
                stats.setStatDate(statDate);
                stats.setRequestCount(1);
                stats.setSuccessCount(success ? 1 : 0);
                stats.setErrorCount(success ? 0 : 1);
                stats.setTotalTokens(tokens != null ? tokens : 0L);
                stats.setTotalCost(cost != null ? cost : BigDecimal.ZERO);
                stats.setAvgResponseTime(responseTime != null ? responseTime : 0);
                baseMapper.insert(stats);
            }
        } catch (Exception e) {
            log.error("记录使用统计失败 - 用户: {}, Provider: {}, 模型: {}", userId, providerName, modelName, e);
            // 不抛出异常，避免影响主业务流程
        }
    }

    /**
     * 获取汇总统计
     */
    @Override
    public Map<String, Object> getSummaryStats(Date startDate, Date endDate) {
        LambdaQueryWrapper<AiUsageStats> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(startDate != null, AiUsageStats::getStatDate, startDate)
                .le(endDate != null, AiUsageStats::getStatDate, endDate);

        List<AiUsageStats> list = baseMapper.selectList(queryWrapper);

        Map<String, Object> result = new HashMap<>();
        int totalRequests = list.stream().mapToInt(s -> s.getRequestCount() != null ? s.getRequestCount() : 0).sum();
        int totalSuccess = list.stream().mapToInt(s -> s.getSuccessCount() != null ? s.getSuccessCount() : 0).sum();
        int totalErrors = list.stream().mapToInt(s -> s.getErrorCount() != null ? s.getErrorCount() : 0).sum();
        long totalTokens = list.stream().mapToLong(s -> s.getTotalTokens() != null ? s.getTotalTokens() : 0L).sum();
        BigDecimal totalCost = list.stream()
                .map(s -> s.getTotalCost() != null ? s.getTotalCost() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 计算平均响应时间（加权平均）
        int totalResponseTime = 0;
        int requestCount = 0;
        for (AiUsageStats stats : list) {
            if (stats.getAvgResponseTime() != null && stats.getRequestCount() != null && stats.getRequestCount() > 0) {
                totalResponseTime += stats.getAvgResponseTime() * stats.getRequestCount();
                requestCount += stats.getRequestCount();
            }
        }
        int avgResponseTime = requestCount > 0 ? totalResponseTime / requestCount : 0;

        result.put("totalRequests", totalRequests);
        result.put("totalSuccess", totalSuccess);
        result.put("totalErrors", totalErrors);
        result.put("totalTokens", totalTokens);
        result.put("totalCost", totalCost);
        result.put("avgResponseTime", avgResponseTime);
        result.put("successRate", totalRequests > 0 ? (double) totalSuccess / totalRequests : 0.0);

        return result;
    }

    /**
     * 获取用户统计
     */
    @Override
    public Map<String, Object> getUserStats(Long userId, Date startDate, Date endDate) {
        LambdaQueryWrapper<AiUsageStats> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AiUsageStats::getUserId, userId)
                .ge(startDate != null, AiUsageStats::getStatDate, startDate)
                .le(endDate != null, AiUsageStats::getStatDate, endDate);

        List<AiUsageStats> list = baseMapper.selectList(queryWrapper);
        return calculateStats(list);
    }

    /**
     * 获取Provider统计
     */
    @Override
    public Map<String, Object> getProviderStats(String providerName, Date startDate, Date endDate) {
        LambdaQueryWrapper<AiUsageStats> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AiUsageStats::getProviderName, providerName)
                .ge(startDate != null, AiUsageStats::getStatDate, startDate)
                .le(endDate != null, AiUsageStats::getStatDate, endDate);

        List<AiUsageStats> list = baseMapper.selectList(queryWrapper);
        return calculateStats(list);
    }

    /**
     * 获取趋势数据
     */
    @Override
    public List<Map<String, Object>> getTrendData(Date startDate, Date endDate, String groupBy) {
        LambdaQueryWrapper<AiUsageStats> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(startDate != null, AiUsageStats::getStatDate, startDate)
                .le(endDate != null, AiUsageStats::getStatDate, endDate)
                .orderByAsc(AiUsageStats::getStatDate);

        List<AiUsageStats> list = baseMapper.selectList(queryWrapper);

        // 按日期分组聚合
        Map<Date, List<AiUsageStats>> grouped = list.stream()
                .collect(Collectors.groupingBy(AiUsageStats::getStatDate));

        List<Map<String, Object>> result = new ArrayList<>();
        for (Map.Entry<Date, List<AiUsageStats>> entry : grouped.entrySet()) {
            Map<String, Object> dayStats = calculateStats(entry.getValue());
            dayStats.put("date", entry.getKey());
            result.add(dayStats);
        }

        return result;
    }

    /**
     * 计算统计数据
     */
    private Map<String, Object> calculateStats(List<AiUsageStats> list) {
        Map<String, Object> result = new HashMap<>();
        int totalRequests = list.stream().mapToInt(s -> s.getRequestCount() != null ? s.getRequestCount() : 0).sum();
        int totalSuccess = list.stream().mapToInt(s -> s.getSuccessCount() != null ? s.getSuccessCount() : 0).sum();
        int totalErrors = list.stream().mapToInt(s -> s.getErrorCount() != null ? s.getErrorCount() : 0).sum();
        long totalTokens = list.stream().mapToLong(s -> s.getTotalTokens() != null ? s.getTotalTokens() : 0L).sum();
        BigDecimal totalCost = list.stream()
                .map(s -> s.getTotalCost() != null ? s.getTotalCost() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 计算平均响应时间
        int totalResponseTime = 0;
        int requestCount = 0;
        for (AiUsageStats stats : list) {
            if (stats.getAvgResponseTime() != null && stats.getRequestCount() != null && stats.getRequestCount() > 0) {
                totalResponseTime += stats.getAvgResponseTime() * stats.getRequestCount();
                requestCount += stats.getRequestCount();
            }
        }
        int avgResponseTime = requestCount > 0 ? totalResponseTime / requestCount : 0;

        result.put("totalRequests", totalRequests);
        result.put("totalSuccess", totalSuccess);
        result.put("totalErrors", totalErrors);
        result.put("totalTokens", totalTokens);
        result.put("totalCost", totalCost);
        result.put("avgResponseTime", avgResponseTime);
        result.put("successRate", totalRequests > 0 ? (double) totalSuccess / totalRequests : 0.0);

        return result;
    }

    /**
     * 计算成功率
     */
    private void calculateSuccessRate(AiUsageStatsVo vo) {
        if (vo.getRequestCount() != null && vo.getRequestCount() > 0) {
            double rate = (double) (vo.getSuccessCount() != null ? vo.getSuccessCount() : 0) / vo.getRequestCount();
            vo.setSuccessRate(BigDecimal.valueOf(rate).setScale(4, RoundingMode.HALF_UP).doubleValue());
        } else {
            vo.setSuccessRate(0.0);
        }
    }

}
