# app/controllers/statistics.py
from flask import Blueprint, render_template, jsonify, request
from flask_login import login_required, current_user
from app.models.book import Book, db
from app.models.borrow import BorrowRecord
from app.models.user import User
from app.utils.auth import permission_required  # 修改为导入permission_required
from app.models.log import Log  # 导入日志模型
from sqlalchemy import func, case, desc, and_
from datetime import datetime, timedelta
import calendar

statistics_bp = Blueprint('statistics', __name__, url_prefix='/statistics')


@statistics_bp.route('/')
@login_required
@permission_required('view_statistics')  # 替代 @admin_required
def index():
    """统计分析首页"""
    # 记录访问统计分析首页的日志
    Log.add_log(
        action="访问统计分析",
        user_id=current_user.id,
        target_type="statistics",
        description="访问统计分析首页"
    )
    return render_template('statistics/index.html')


@statistics_bp.route('/book-ranking')
@login_required
@permission_required('view_statistics')  # 替代 @admin_required
def book_ranking():
    """热门图书排行榜页面"""
    # 记录访问热门图书排行的日志
    Log.add_log(
        action="查看统计数据",
        user_id=current_user.id,
        target_type="statistics",
        description="查看热门图书排行榜"
    )
    return render_template('statistics/book_ranking.html')


@statistics_bp.route('/api/book-ranking')
@login_required
@permission_required('view_statistics')  # 替代 @admin_required
def api_book_ranking():
    """获取热门图书排行数据API"""
    time_range = request.args.get('time_range', 'month')
    limit = request.args.get('limit', 10, type=int)

    # 记录获取热门图书排行数据的日志
    Log.add_log(
        action="获取数据",
        user_id=current_user.id,
        target_type="statistics",
        description=f"获取热门图书排行数据(时间范围:{time_range}, 数量:{limit})"
    )

    # 根据时间范围设置过滤条件
    if time_range == 'week':
        start_date = datetime.now() - timedelta(days=7)
    elif time_range == 'month':
        start_date = datetime.now() - timedelta(days=30)
    elif time_range == 'year':
        start_date = datetime.now() - timedelta(days=365)
    else:  # all time
        start_date = datetime(1900, 1, 1)

    # 查询借阅次数最多的图书
    popular_books = db.session.query(
        Book.id, Book.title, Book.author, Book.cover_url,
        func.count(BorrowRecord.id).label('borrow_count')
    ).join(
        BorrowRecord, Book.id == BorrowRecord.book_id
    ).filter(
        BorrowRecord.borrow_date >= start_date
    ).group_by(
        Book.id
    ).order_by(
        desc('borrow_count')
    ).limit(limit).all()

    result = [
        {
            'id': book.id,
            'title': book.title,
            'author': book.author,
            'cover_url': book.cover_url,
            'borrow_count': book.borrow_count
        } for book in popular_books
    ]

    return jsonify(result)


@statistics_bp.route('/borrow-statistics')
@login_required
@permission_required('view_statistics')  # 替代 @admin_required
def borrow_statistics():
    """借阅统计分析页面"""
    # 记录访问借阅统计分析的日志
    Log.add_log(
        action="查看统计数据",
        user_id=current_user.id,
        target_type="statistics",
        description="查看借阅统计分析"
    )
    return render_template('statistics/borrow_statistics.html')


@statistics_bp.route('/api/borrow-trend')
@login_required
@permission_required('view_statistics')  # 替代 @admin_required
def api_borrow_trend():
    """获取借阅趋势数据API"""
    time_range = request.args.get('time_range', 'month')

    now = datetime.now()

    # 记录获取借阅趋势数据的日志
    Log.add_log(
        action="获取数据",
        user_id=current_user.id,
        target_type="statistics",
        description=f"获取借阅趋势数据(时间范围:{time_range})"
    )

    if time_range == 'week':
        # 获取过去7天每天的借阅和归还数量
        start_date = datetime.now() - timedelta(days=6)
        results = []

        for i in range(7):
            day = start_date + timedelta(days=i)
            day_start = day.replace(hour=0, minute=0, second=0, microsecond=0)
            day_end = day.replace(hour=23, minute=59, second=59, microsecond=999999)

            # 查询当天借阅量
            borrow_count = BorrowRecord.query.filter(
                BorrowRecord.borrow_date >= day_start,
                BorrowRecord.borrow_date <= day_end
            ).count()

            # 查询当天归还量
            return_count = BorrowRecord.query.filter(
                BorrowRecord.return_date >= day_start,
                BorrowRecord.return_date <= day_end
            ).count()

            # 当天逾期未还的数量
            overdue_count = BorrowRecord.query.filter(
                BorrowRecord.return_date.is_(None),  # 未归还
                BorrowRecord.due_date < now  # 应还日期早于当前时间
            ).count()

            results.append({
                'date': day.strftime('%m-%d'),
                'borrow': borrow_count,
                'return': return_count,
                'overdue': overdue_count
            })

        return jsonify(results)

    elif time_range == 'month':
        # 获取过去30天每天的借阅和归还数量
        start_date = datetime.now() - timedelta(days=29)
        results = []

        for i in range(30):
            day = start_date + timedelta(days=i)
            day_start = day.replace(hour=0, minute=0, second=0, microsecond=0)
            day_end = day.replace(hour=23, minute=59, second=59, microsecond=999999)

            # 查询当天借阅量
            borrow_count = BorrowRecord.query.filter(
                BorrowRecord.borrow_date >= day_start,
                BorrowRecord.borrow_date <= day_end
            ).count()

            # 查询当天归还量
            return_count = BorrowRecord.query.filter(
                BorrowRecord.return_date >= day_start,
                BorrowRecord.return_date <= day_end
            ).count()

            # 当天逾期未还的数量
            now = datetime.now()
            overdue_count = BorrowRecord.query.filter(
                BorrowRecord.return_date.is_(None),
                BorrowRecord.due_date < now
            ).count()

            results.append({
                'date': day.strftime('%m-%d'),
                'borrow': borrow_count,
                'return': return_count,
                'overdue': overdue_count
            })

        return jsonify(results)

    elif time_range == 'year':
        # 获取过去12个月每月的借阅和归还数量
        current_month = datetime.now().month
        current_year = datetime.now().year
        results = []

        for i in range(12):
            # 计算月份和年份
            month = (current_month - i) % 12
            if month == 0:
                month = 12
            year = current_year - ((i - (current_month - 1)) // 12)

            # 计算该月的开始和结束日期
            days_in_month = calendar.monthrange(year, month)[1]
            month_start = datetime(year, month, 1)
            month_end = datetime(year, month, days_in_month, 23, 59, 59, 999999)

            # 查询当月借阅量
            borrow_count = BorrowRecord.query.filter(
                BorrowRecord.borrow_date >= month_start,
                BorrowRecord.borrow_date <= month_end
            ).count()

            # 查询当月归还量
            return_count = BorrowRecord.query.filter(
                BorrowRecord.return_date >= month_start,
                BorrowRecord.return_date <= month_end
            ).count()

            # 当月逾期未还的数量
            now = datetime.now()
            overdue_count = BorrowRecord.query.filter(
                BorrowRecord.return_date.is_(None),
                BorrowRecord.due_date < now
            ).count()

            results.append({
                'date': f'{year}-{month:02d}',
                'borrow': borrow_count,
                'return': return_count,
                'overdue': overdue_count
            })

        # 按时间顺序排序
        results.reverse()
        return jsonify(results)

    return jsonify([])


@statistics_bp.route('/api/category-distribution')
@login_required
@permission_required('view_statistics')  # 替代 @admin_required
def api_category_distribution():
    """获取图书分类分布数据API"""
    # 记录获取图书分类分布数据的日志
    Log.add_log(
        action="获取数据",
        user_id=current_user.id,
        target_type="statistics",
        description="获取图书分类分布数据"
    )

    # 计算每个分类的总借阅次数
    category_stats = db.session.query(
        Book.category_id,
        func.count(BorrowRecord.id).label('borrow_count')
    ).join(
        BorrowRecord, Book.id == BorrowRecord.book_id
    ).group_by(
        Book.category_id
    ).all()

    # 获取分类名称
    from app.models.book import Category
    categories = {cat.id: cat.name for cat in Category.query.all()}

    # 准备结果
    result = [
        {
            'category': categories.get(stat.category_id, '未分类'),
            'count': stat.borrow_count
        } for stat in category_stats if stat.category_id is not None
    ]

    # 添加未分类数据
    uncategorized = next((stat for stat in category_stats if stat.category_id is None), None)
    if uncategorized:
        result.append({'category': '未分类', 'count': uncategorized.borrow_count})

    return jsonify(result)


@statistics_bp.route('/user-activity')
@login_required
@permission_required('view_statistics')  # 替代 @admin_required
def user_activity():
    """用户活跃度分析页面"""
    # 记录访问用户活跃度分析的日志
    Log.add_log(
        action="查看统计数据",
        user_id=current_user.id,
        target_type="statistics",
        description="查看用户活跃度分析"
    )
    return render_template('statistics/user_activity.html')


@statistics_bp.route('/api/user-activity')
@login_required
@permission_required('view_statistics')  # 替代 @admin_required
def api_user_activity():
    """获取用户活跃度数据API"""
    # 记录获取用户活跃度数据的日志
    Log.add_log(
        action="获取数据",
        user_id=current_user.id,
        target_type="statistics",
        description="获取用户活跃度数据"
    )

    # 查询最活跃的用户(借阅量最多)
    active_users = db.session.query(
        User.id, User.username, User.nickname,
        func.count(BorrowRecord.id).label('borrow_count')
    ).join(
        BorrowRecord, User.id == BorrowRecord.user_id
    ).group_by(
        User.id
    ).order_by(
        desc('borrow_count')
    ).limit(10).all()

    result = [
        {
            'id': user.id,
            'username': user.username,
            'nickname': user.nickname or user.username,
            'borrow_count': user.borrow_count
        } for user in active_users
    ]

    return jsonify(result)


@statistics_bp.route('/overdue-analysis')
@login_required
@permission_required('view_statistics')  # 替代 @admin_required
def overdue_analysis():
    """逾期分析页面"""
    # 记录访问逾期分析的日志
    Log.add_log(
        action="查看统计数据",
        user_id=current_user.id,
        target_type="statistics",
        description="查看借阅逾期分析"
    )
    return render_template('statistics/overdue_analysis.html')


@statistics_bp.route('/api/overdue-statistics')
@login_required
@permission_required('view_statistics')  # 替代 @admin_required
def api_overdue_statistics():
    """获取逾期统计数据API"""
    # 记录获取逾期统计数据的日志
    Log.add_log(
        action="获取数据",
        user_id=current_user.id,
        target_type="statistics",
        description="获取借阅逾期统计数据"
    )

    now = datetime.now()

    # 计算总借阅量
    total_borrows = BorrowRecord.query.count()

    # 计算已归还的逾期借阅
    returned_overdue = BorrowRecord.query.filter(
        BorrowRecord.return_date.isnot(None),
        BorrowRecord.return_date > BorrowRecord.due_date
    ).count()

    # 计算未归还的逾期借阅
    current_overdue = BorrowRecord.query.filter(
        BorrowRecord.return_date.is_(None),
        BorrowRecord.due_date < now
    ).count()

    # 计算总逾期率
    overdue_rate = round((returned_overdue + current_overdue) / total_borrows * 100, 2) if total_borrows > 0 else 0

    # 计算各逾期时长区间的数量
    overdue_range_data = []

    # 1-7天逾期
    range1 = BorrowRecord.query.filter(
        and_(
            BorrowRecord.return_date.is_(None),
            BorrowRecord.due_date < now,
            BorrowRecord.due_date >= now - timedelta(days=7)
        )
    ).count()
    overdue_range_data.append({'range': '1-7天', 'count': range1})

    # 8-14天逾期
    range2 = BorrowRecord.query.filter(
        and_(
            BorrowRecord.return_date.is_(None),
            BorrowRecord.due_date < now - timedelta(days=7),
            BorrowRecord.due_date >= now - timedelta(days=14)
        )
    ).count()
    overdue_range_data.append({'range': '8-14天', 'count': range2})

    # 15-30天逾期
    range3 = BorrowRecord.query.filter(
        and_(
            BorrowRecord.return_date.is_(None),
            BorrowRecord.due_date < now - timedelta(days=14),
            BorrowRecord.due_date >= now - timedelta(days=30)
        )
    ).count()
    overdue_range_data.append({'range': '15-30天', 'count': range3})

    # 30天以上逾期
    range4 = BorrowRecord.query.filter(
        and_(
            BorrowRecord.return_date.is_(None),
            BorrowRecord.due_date < now - timedelta(days=30)
        )
    ).count()
    overdue_range_data.append({'range': '30天以上', 'count': range4})

    result = {
        'total_borrows': total_borrows,
        'returned_overdue': returned_overdue,
        'current_overdue': current_overdue,
        'overdue_rate': overdue_rate,
        'overdue_ranges': overdue_range_data
    }

    return jsonify(result)
