#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
小程序专用抖音播放量数据API服务器
优化的数据格式和接口设计，专为小程序使用
"""

from flask import Blueprint, request, jsonify
from datetime import datetime, timedelta
import logging
import re
from database import db

# 创建蓝图
rank_bp = Blueprint('rank', __name__, url_prefix='/api/rank')

# 获取数据库集合
collection = db['Rankings_list']
daily_rankings_collection = db['Ranking_storage']  # 榜单存储表

def format_playcount(playcount_str):
    """格式化播放量字符串为数字"""
    if not playcount_str:
        return 0
    
    try:
        if isinstance(playcount_str, (int, float)):
            return int(playcount_str)
        
        playcount_str = str(playcount_str).strip()
        
        # 处理亿、万等单位
        if "亿" in playcount_str:
            num = float(re.findall(r'[\d.]+', playcount_str)[0])
            return int(num * 100000000)
        elif "万" in playcount_str:
            num = float(re.findall(r'[\d.]+', playcount_str)[0])
            return int(num * 10000)
        else:
            # 尝试直接转换数字
            return int(float(playcount_str))
    except:
        return 0

def format_cover_url(cover_data):
    """格式化封面图片URL"""
    if not cover_data:
        return ""
    
    if isinstance(cover_data, str):
        return cover_data
    elif isinstance(cover_data, dict) and 'url_list' in cover_data:
        return cover_data['url_list'][0] if cover_data['url_list'] else ""
    else:
        return ""

def format_time(time_obj):
    """格式化时间"""
    if not time_obj:
        return ""
    
    if isinstance(time_obj, datetime):
        return time_obj.strftime("%Y-%m-%d %H:%M:%S")
    else:
        return str(time_obj)

def sort_ranking_data(ranking_data, sort_by, sort_order='desc'):
    """
    对榜单数据进行动态排序
    
    Args:
        ranking_data: 榜单数据列表
        sort_by: 排序字段 (play_vv_change, play_vv_change_rate, play_vv, rank)
        sort_order: 排序顺序 (asc, desc)
    
    Returns:
        排序后的榜单数据
    """
    try:
        # 定义排序键函数
        def get_sort_key(item):
            if sort_by == 'play_vv_change':
                # 按播放量差值排序
                timeline_data = item.get('timeline_data', {})
                return timeline_data.get('play_vv_change', 0)
            elif sort_by == 'play_vv_change_rate':
                # 按播放量变化率排序
                timeline_data = item.get('timeline_data', {})
                return timeline_data.get('play_vv_change_rate', 0)
            elif sort_by == 'play_vv':
                # 按当前播放量排序
                return item.get('play_vv', 0)
            elif sort_by == 'rank':
                # 按排名排序
                return item.get('rank', 999999)
            else:
                # 默认按排名排序
                return item.get('rank', 999999)
        
        # 执行排序
        reverse = (sort_order == 'desc')
        
        # 对于排名字段，降序实际上是升序（排名越小越好）
        if sort_by == 'rank':
            reverse = (sort_order == 'asc')
        
        sorted_data = sorted(ranking_data, key=get_sort_key, reverse=reverse)
        
        # 重新分配排名
        for i, item in enumerate(sorted_data, 1):
            item['current_sort_rank'] = i
        
        return sorted_data
        
    except Exception as e:
        logging.error(f"排序榜单数据失败: {e}")
        # 如果排序失败，返回原始数据
        return ranking_data

def format_mix_item(doc):
    """格式化合集数据项 - 完全按照数据库原始字段返回"""
    return {
        "_id": str(doc.get("_id", "")),
        "batch_time": format_time(doc.get("batch_time")),
        "mix_name": doc.get("mix_name", ""),
        "video_url": doc.get("video_url", ""),
        "playcount": doc.get("playcount", ""),
        "play_vv": doc.get("play_vv", 0),
        "request_id": doc.get("request_id", ""),
        "rank": doc.get("rank", 0),
        "cover_image_url": doc.get("cover_image_url", ""),
        # 新增字段
        "series_author": doc.get("series_author", ""),
        "desc": doc.get("desc", ""),
        "updated_to_episode": doc.get("updated_to_episode", 0),
        "cover_backup_urls": doc.get("cover_backup_urls", []),
        "mix_id": doc.get("mix_id", ""),
        "episode_video_ids": doc.get("episode_video_ids", []),
        "episode_details": doc.get("episode_details", [])
    }

def get_mix_list(page=1, limit=20, sort_by="playcount"):
    """获取合集列表（分页）"""
    try:
        # 计算跳过的数量
        skip = (page - 1) * limit

        # 设置排序字段
        if sort_by == "growth":
            # 按增长排序需要特殊处理
            return get_growth_mixes(page, limit)
        else:
            sort_field = "play_vv" if sort_by == "playcount" else "batch_time"
            sort_order = -1  # 降序

            # 获取今天的日期
            today = datetime.now().date()

            # 只查询今天的数据
            query_condition = {
                "batch_time": {
                    "$gte": datetime(today.year, today.month, today.day),
                    "$lt": datetime(today.year, today.month, today.day) + timedelta(days=1)
                }
            }

            # 查询数据并按短剧名称分组，取每个短剧的最新记录
            pipeline = [
                {"$match": query_condition},
                {"$sort": {"batch_time": -1}},  # 按时间倒序
                {"$group": {
                    "_id": "$mix_name",  # 按短剧名称分组
                    "latest_doc": {"$first": "$$ROOT"}  # 取每个分组的第一条记录（最新记录）
                }},
                {"$replaceRoot": {"newRoot": "$latest_doc"}},
                {"$sort": {sort_field: sort_order}},
                {"$skip": skip},
                {"$limit": limit}
            ]

            docs = list(collection.aggregate(pipeline))

            # 获取总数
            total_pipeline = [
                {"$match": query_condition},
                {"$sort": {"batch_time": -1}},
                {"$group": {"_id": "$mix_name"}},
                {"$count": "total"}
            ]
            total_result = list(collection.aggregate(total_pipeline))
            total = total_result[0]["total"] if total_result else 0

            # 格式化数据
            mix_list = []
            for doc in docs:
                item = format_mix_item(doc)
                mix_list.append(item)

            return {
                "success": True,
                "data": mix_list,
                "pagination": {
                    "page": page,
                    "limit": limit,
                    "total": total,
                    "pages": (total + limit - 1) // limit,
                    "has_next": page * limit < total,
                    "has_prev": page > 1
                },
                "sort_by": sort_by,
                "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }

    except Exception as e:
        logging.error(f"获取合集列表失败: {e}")
        return {"success": False, "message": f"获取数据失败: {str(e)}"}

def get_growth_mixes(page=1, limit=20, start_date=None, end_date=None):
    """获取按播放量增长排序的合集列表 - 仅从Ranking_storage读取预计算数据"""
    try:
        # 计算跳过的数量
        skip = (page - 1) * limit

        # 如果没有提供日期，默认使用今天和昨天
        if not start_date or not end_date:
            end_date = datetime.now().date()
            start_date = end_date - timedelta(days=1)
        else:
            # 转换字符串日期为datetime对象
            if isinstance(start_date, str):
                start_date = datetime.strptime(start_date, "%Y-%m-%d").date()
            if isinstance(end_date, str):
                end_date = datetime.strptime(end_date, "%Y-%m-%d").date()

        end_date_str = end_date.strftime("%Y-%m-%d")
        start_date_str = start_date.strftime("%Y-%m-%d")

        # 从Ranking_storage读取预计算的增长榜数据
        growth_ranking = daily_rankings_collection.find_one({
            "date": end_date_str,
            "type": "comprehensive"  # 使用comprehensive类型，包含增长数据
        }, sort=[("calculation_sequence", -1)])  # 获取最新的计算结果

        if not growth_ranking or "data" not in growth_ranking:
            # 如果没有找到comprehensive类型，尝试查找growth类型
            growth_ranking = daily_rankings_collection.find_one({
                "date": end_date_str,
                "type": "growth"
            }, sort=[("calculation_sequence", -1)])

        if growth_ranking and "data" in growth_ranking:
            logging.info(f"📈 从Ranking_storage读取 {end_date_str} 的增长榜数据")
            
            # 获取预先计算好的增长榜数据
            growth_data = growth_ranking["data"]
            
            # 如果是comprehensive类型，需要按增长值排序
            if growth_ranking.get("type") == "comprehensive":
                # 按timeline_data中的play_vv_change排序
                growth_data = sorted(growth_data, 
                    key=lambda x: x.get("timeline_data", {}).get("play_vv_change", 0), 
                    reverse=True)
            
            # 分页处理
            total = len(growth_data)
            paginated_data = growth_data[skip:skip + limit]

            # 为分页数据添加排名
            for i, item in enumerate(paginated_data):
                item["rank"] = skip + i + 1

            return {
                "success": True,
                "data": paginated_data,
                "pagination": {
                    "page": page,
                    "limit": limit,
                    "total": total,
                    "pages": (total + limit - 1) // limit,
                    "has_next": page * limit < total,
                    "has_prev": page > 1
                },
                "sort_by": "growth",
                "date_range": {
                    "start_date": start_date_str,
                    "end_date": end_date_str
                },
                "data_source": "ranking_storage",  # 标识数据来源
                "update_time": growth_ranking.get("created_at", datetime.now()).strftime("%Y-%m-%d %H:%M:%S") if isinstance(growth_ranking.get("created_at"), datetime) else str(growth_ranking.get("created_at", ""))
            }
        else:
            # 如果Ranking_storage中没有数据，返回空结果
            logging.warning(f"Ranking_storage中未找到 {end_date_str} 的增长榜数据")
            return {
                "success": True,
                "message": f"暂无 {end_date_str} 的增长榜数据，请等待定时任务生成",
                "data": [],
                "pagination": {
                    "page": page,
                    "limit": limit,
                    "total": 0,
                    "pages": 0,
                    "has_next": False,
                    "has_prev": False
                },
                "sort_by": "growth",
                "date_range": {
                    "start_date": start_date_str,
                    "end_date": end_date_str
                },
                "data_source": "ranking_storage",
                "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }

    except Exception as e:
        logging.error(f"获取增长合集列表失败: {e}")
        # 返回错误信息，不再回退到播放量排序
        return {
            "success": False,
            "message": f"获取增长榜数据失败: {str(e)}",
            "data": [],
            "pagination": {
                "page": page,
                "limit": limit,
                "total": 0,
                "pages": 0,
                "has_next": False,
                "has_prev": False
            },
            "sort_by": "growth",
            "data_source": "ranking_storage"
        }

def get_top_mixes(limit=10):
    """获取热门合集（TOP榜单）"""
    try:
        # 按播放量排序获取热门合集
        cursor = collection.find().sort("play_vv", -1).limit(limit)
        docs = list(cursor)
        
        if not docs:
            return {"success": False, "message": "暂无数据"}
        
        # 格式化数据
        top_list = []
        for doc in docs:
            item = format_mix_item(doc)
            top_list.append(item)

        return {
            "success": True,
            "data": top_list,
            "total": len(top_list),
            "update_time": format_time(docs[0].get("batch_time")) if docs else ""
        }
        
    except Exception as e:
        logging.error(f"获取热门合集失败: {e}")
        return {"success": False, "message": f"获取数据失败: {str(e)}"}

def search_mixes(keyword, page=1, limit=10):
    """搜索合集"""
    try:
        if not keyword:
            return {"success": False, "message": "请提供搜索关键词"}
        
        # 计算跳过的数量
        skip = (page - 1) * limit
        
        # 构建搜索条件（模糊匹配合集名称）
        search_condition = {
            "mix_name": {"$regex": keyword, "$options": "i"}
        }
        
        # 查询数据
        cursor = collection.find(search_condition).sort("play_vv", -1).skip(skip).limit(limit)
        docs = list(cursor)
        
        # 获取搜索结果总数
        total = collection.count_documents(search_condition)
        
        # 格式化数据
        search_results = []
        for doc in docs:
            item = format_mix_item(doc)
            search_results.append(item)
        
        return {
            "success": True,
            "data": search_results,
            "keyword": keyword,
            "pagination": {
                "page": page,
                "limit": limit,
                "total": total,
                "pages": (total + limit - 1) // limit,
                "has_next": page * limit < total,
                "has_prev": page > 1
            },
            "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        
    except Exception as e:
        logging.error(f"搜索合集失败: {e}")
        return {"success": False, "message": f"搜索失败: {str(e)}"}

def get_mix_detail(mix_id):
    """获取合集详情"""
    try:
        from bson import ObjectId
        
        # 尝试通过ObjectId查找
        try:
            doc = collection.find_one({"_id": ObjectId(mix_id)})
        except:
            # 如果ObjectId无效，尝试其他字段
            doc = collection.find_one({
                "$or": [
                    {"mix_name": mix_id},
                    {"request_id": mix_id}
                ]
            })
        
        if not doc:
            return {"success": False, "message": "未找到合集信息"}
        
        # 格式化详细信息 - 只返回数据库原始字段
        detail = format_mix_item(doc)
        
        return {
            "success": True,
            "data": detail,
            "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        
    except Exception as e:
        logging.error(f"获取合集详情失败: {e}")
        return {"success": False, "message": f"获取详情失败: {str(e)}"}

def get_statistics():
    """获取统计信息"""
    try:
        # 基本统计
        total_mixes = collection.count_documents({})
        
        if total_mixes == 0:
            return {"success": False, "message": "暂无数据"}
        
        # 播放量统计
        pipeline = [
            {
                "$group": {
                    "_id": None,
                    "total_playcount": {"$sum": "$play_vv"},
                    "avg_playcount": {"$avg": "$play_vv"},
                    "max_playcount": {"$max": "$play_vv"},
                    "min_playcount": {"$min": "$play_vv"}
                }
            }
        ]
        
        stats_result = list(collection.aggregate(pipeline))
        stats = stats_result[0] if stats_result else {}
        
        # 获取最新更新时间
        latest_doc = collection.find().sort("batch_time", -1).limit(1)
        latest_time = ""
        if latest_doc:
            latest_list = list(latest_doc)
            if latest_list:
                latest_time = format_time(latest_list[0].get("batch_time"))
        
        # 热门分类统计（按播放量区间）
        categories = [
            {"name": "超热门", "min": 100000000, "count": 0},  # 1亿+
            {"name": "热门", "min": 50000000, "max": 99999999, "count": 0},  # 5000万-1亿
            {"name": "中等", "min": 10000000, "max": 49999999, "count": 0},  # 1000万-5000万
            {"name": "一般", "min": 0, "max": 9999999, "count": 0}  # 1000万以下
        ]
        
        for category in categories:
            if "max" in category:
                count = collection.count_documents({
                    "play_vv": {"$gte": category["min"], "$lte": category["max"]}
                })
            else:
                count = collection.count_documents({
                    "play_vv": {"$gte": category["min"]}
                })
            category["count"] = count
        
        return {
            "success": True,
            "data": {
                "total_mixes": total_mixes,
                "total_playcount": stats.get("total_playcount", 0),
                "avg_playcount": int(stats.get("avg_playcount", 0)),
                "max_playcount": stats.get("max_playcount", 0),
                "min_playcount": stats.get("min_playcount", 0),
                "categories": categories,
                "latest_update": latest_time
            },
            "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        
    except Exception as e:
        logging.error(f"获取统计信息失败: {e}")
        return {"success": False, "message": f"获取统计失败: {str(e)}"}

# 路由定义
@rank_bp.route('/videos')
def get_videos():
    """获取合集列表 - 兼容app.py调用"""
    page = int(request.args.get('page', 1))
    limit = int(request.args.get('limit', 20))
    sort_by = request.args.get('sort', 'playcount')

    if sort_by == 'growth':
        start_date = request.args.get('start_date')
        end_date = request.args.get('end_date')
        result = get_growth_mixes(page, limit, start_date, end_date)
    else:
        result = get_mix_list(page, limit, sort_by)
    
    return jsonify(result)

@rank_bp.route('/top')
def get_top():
    """获取热门榜单 - 兼容app.py调用"""
    limit = int(request.args.get('limit', 10))
    result = get_top_mixes(limit)
    return jsonify(result)

@rank_bp.route('/search')
def search():
    """搜索合集 - 兼容app.py调用"""
    keyword = request.args.get('q', '')
    page = int(request.args.get('page', 1))
    limit = int(request.args.get('limit', 10))
    result = search_mixes(keyword, page, limit)
    return jsonify(result)

@rank_bp.route('/detail')
def get_detail():
    """获取合集详情 - 兼容app.py调用"""
    mix_id = request.args.get('id', '')
    result = get_mix_detail(mix_id)
    return jsonify(result)

@rank_bp.route('/stats')
def get_stats():
    """获取统计信息 - 兼容app.py调用"""
    result = get_statistics()
    return jsonify(result)

@rank_bp.route('/health')
def health_check():
    """健康检查 - 兼容app.py调用"""
    try:
        from database import client
        
        # 检查数据库连接
        if not client:
            return jsonify({"success": False, "message": "数据库未连接"})
        
        # 测试数据库连接
        client.admin.command('ping')
        
        # 获取数据统计
        total_count = collection.count_documents({})
        
        return jsonify({
            "success": True,
            "message": "服务正常",
            "data": {
                "database": "连接正常",
                "total_records": total_count,
                "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }
        })
    except Exception as e:
        logging.error(f"健康检查失败: {e}")
        return jsonify({"success": False, "message": f"服务异常: {str(e)}"})


# ==================== 榜单查询API接口 ====================

@rank_bp.route('/rankings')
def get_rankings():
    """获取榜单列表 - 支持按日期和类型查询，支持动态排序"""
    try:
        # 获取查询参数
        date = request.args.get('date')  # 日期，格式：YYYY-MM-DD
        ranking_type = request.args.get('type')  # 榜单类型：playcount, growth, newcomer
        sort_by = request.args.get('sort_by', 'default')  # 排序方式：default, play_vv_change, play_vv_change_rate, play_vv
        sort_order = request.args.get('sort_order', 'desc')  # 排序顺序：asc, desc
        page = int(request.args.get('page', 1))
        limit = int(request.args.get('limit', 50))
        
        # 构建查询条件
        query = {}
        if date:
            query['date'] = date
        if ranking_type:
            query['ranking_type'] = ranking_type
        
        # 如果没有指定日期，默认获取最新日期的榜单
        if not date:
            latest_ranking = daily_rankings_collection.find_one(
                {}, sort=[('date', -1)]
            )
            if latest_ranking:
                query['date'] = latest_ranking['date']
        
        # 查询榜单
        rankings = list(daily_rankings_collection.find(query).sort('generated_at', -1))
        
        if not rankings:
            return jsonify({
                "success": True,
                "message": "暂无榜单数据",
                "data": {
                    "rankings": [],
                    "total": 0,
                    "page": page,
                    "limit": limit
                }
            })
        
        # 格式化返回数据
        formatted_rankings = []
        for ranking in rankings:
            ranking_data = ranking.get('data', [])
            
            # 动态排序逻辑
            if sort_by != 'default' and ranking_data:
                ranking_data = sort_ranking_data(ranking_data, sort_by, sort_order)
            
            # 分页处理榜单数据
            start_idx = (page - 1) * limit
            end_idx = start_idx + limit
            paginated_data = ranking_data[start_idx:end_idx]
            
            formatted_rankings.append({
                "date": ranking.get('date'),
                "ranking_type": ranking.get('ranking_type'),
                "ranking_name": ranking.get('ranking_name'),
                "description": ranking.get('description'),
                "data": paginated_data,
                "total_count": len(ranking_data),
                "current_page_count": len(paginated_data),
                "generated_at": format_time(ranking.get('generated_at')),
                "version": ranking.get('version', '1.0'),
                "sort_info": {
                    "sort_by": sort_by,
                    "sort_order": sort_order
                }
            })
        
        return jsonify({
            "success": True,
            "message": "获取榜单成功",
            "data": {
                "rankings": formatted_rankings,
                "total": len(formatted_rankings),
                "page": page,
                "limit": limit,
                "sort_by": sort_by,
                "sort_order": sort_order
            }
        })
        
    except Exception as e:
        logging.error(f"获取榜单失败: {e}")
        return jsonify({"success": False, "message": f"获取榜单失败: {str(e)}"})


@rank_bp.route('/rankings/dates')
def get_ranking_dates():
    """获取可用的榜单日期列表"""
    try:
        # 获取所有不重复的日期
        dates = daily_rankings_collection.distinct('date')
        dates.sort(reverse=True)  # 按日期倒序排列
        
        return jsonify({
            "success": True,
            "message": "获取日期列表成功",
            "data": {
                "dates": dates,
                "total": len(dates)
            }
        })
        
    except Exception as e:
        logging.error(f"获取日期列表失败: {e}")
        return jsonify({"success": False, "message": f"获取日期列表失败: {str(e)}"})


@rank_bp.route('/rankings/types')
def get_ranking_types():
    """获取支持的榜单类型"""
    try:
        # 获取所有不重复的榜单类型
        types = daily_rankings_collection.distinct('ranking_type')
        
        # 添加类型说明
        type_descriptions = {
            'playcount': '播放量榜 - 按播放量排序',
            'growth': '增长榜 - 播放量增长最快',
            'newcomer': '新晋榜 - 新上榜内容'
        }
        
        formatted_types = []
        for type_name in types:
            formatted_types.append({
                "type": type_name,
                "description": type_descriptions.get(type_name, type_name)
            })
        
        return jsonify({
            "success": True,
            "message": "获取榜单类型成功",
            "data": {
                "types": formatted_types,
                "total": len(formatted_types)
            }
        })
        
    except Exception as e:
        logging.error(f"获取榜单类型失败: {e}")
        return jsonify({"success": False, "message": f"获取榜单类型失败: {str(e)}"})


@rank_bp.route('/rankings/latest')
def get_latest_rankings():
    """获取最新的所有类型榜单"""
    try:
        # 获取最新日期
        latest_ranking = daily_rankings_collection.find_one(
            {}, sort=[('date', -1)]
        )
        
        if not latest_ranking:
            return jsonify({
                "success": True,
                "message": "暂无榜单数据",
                "data": {
                    "date": None,
                    "rankings": []
                }
            })
        
        latest_date = latest_ranking['date']
        
        # 获取该日期的所有榜单
        rankings = list(daily_rankings_collection.find({
            'date': latest_date
        }).sort('ranking_type', 1))
        
        formatted_rankings = []
        for ranking in rankings:
            # 只返回前20条数据
            ranking_data = ranking.get('data', [])[:20]
            
            formatted_rankings.append({
                "ranking_type": ranking.get('ranking_type'),
                "ranking_name": ranking.get('ranking_name'),
                "description": ranking.get('description'),
                "data": ranking_data,
                "total_count": ranking.get('total_count', 0),
                "preview_count": len(ranking_data)
            })
        
        return jsonify({
            "success": True,
            "message": "获取最新榜单成功",
            "data": {
                "date": latest_date,
                "rankings": formatted_rankings,
                "total_types": len(formatted_rankings)
            }
        })
        
    except Exception as e:
        logging.error(f"获取最新榜单失败: {e}")
        return jsonify({"success": False, "message": f"获取最新榜单失败: {str(e)}"})


@rank_bp.route('/rankings/stats')
def get_rankings_stats():
    """获取榜单统计信息"""
    try:
        # 统计总榜单数
        total_rankings = daily_rankings_collection.count_documents({})
        
        # 统计日期数量
        total_dates = len(daily_rankings_collection.distinct('date'))
        
        # 统计榜单类型数量
        total_types = len(daily_rankings_collection.distinct('ranking_type'))
        
        # 获取最新和最早日期
        latest_ranking = daily_rankings_collection.find_one({}, sort=[('date', -1)])
        earliest_ranking = daily_rankings_collection.find_one({}, sort=[('date', 1)])
        
        latest_date = latest_ranking['date'] if latest_ranking else None
        earliest_date = earliest_ranking['date'] if earliest_ranking else None
        
        return jsonify({
            "success": True,
            "message": "获取榜单统计成功",
            "data": {
                "total_rankings": total_rankings,
                "total_dates": total_dates,
                "total_types": total_types,
                "latest_date": latest_date,
                "earliest_date": earliest_date,
                "date_range": f"{earliest_date} 至 {latest_date}" if earliest_date and latest_date else "暂无数据"
            }
        })
        
    except Exception as e:
        logging.error(f"获取榜单统计失败: {e}")
        return jsonify({"success": False, "message": f"获取榜单统计失败: {str(e)}"})