from flask import Blueprint, request, redirect, url_for, flash, render_template, jsonify
from flask_login import current_user, login_required
from app.models.book import Book
from app.models.borrow import BorrowRecord
from app.models.inventory import InventoryLog
from app.models.user import db, User
from app.models.log import Log  # 导入日志模型
import datetime
from app.utils.auth import permission_required  # 修改导入，使用permission_required而不是admin_required

# 创建借阅蓝图
borrow_bp = Blueprint('borrow', __name__, url_prefix='/borrow')


@borrow_bp.route('/book', methods=['POST'])
@login_required
def borrow_book():
    book_id = request.form.get('book_id', type=int)
    borrow_days = request.form.get('borrow_days', type=int, default=14)

    if not book_id:
        flash('请选择要借阅的图书', 'danger')
        return redirect(url_for('book.book_list'))

    # 检查用户当前借阅数量是否达到上限(5本)
    current_borrows_count = BorrowRecord.query.filter_by(
        user_id=current_user.id,
        status=1  # 1表示借阅中
    ).count()

    if current_borrows_count >= 5:
        flash('您当前已借阅5本图书，达到借阅上限。请先归还后再借阅新书。', 'warning')
        return redirect(url_for('book.book_detail', book_id=book_id))

    book = Book.query.get_or_404(book_id)

    # 检查库存
    if book.stock <= 0:
        flash(f'《{book.title}》当前无库存，无法借阅', 'danger')
        return redirect(url_for('book.book_detail', book_id=book_id))

    # 检查当前用户是否已借阅此书
    existing_borrow = BorrowRecord.query.filter_by(
        user_id=current_user.id,
        book_id=book_id,
        status=1  # 1表示借阅中
    ).first()

    if existing_borrow:
        flash(f'您已借阅《{book.title}》，请勿重复借阅', 'warning')
        return redirect(url_for('book.book_detail', book_id=book_id))

    try:
        # 创建借阅记录
        now = datetime.datetime.now()
        due_date = now + datetime.timedelta(days=borrow_days)

        borrow_record = BorrowRecord(
            user_id=current_user.id,
            book_id=book_id,
            borrow_date=now,
            due_date=due_date,
            status=1,  # 1表示借阅中
            created_at=now,
            updated_at=now
        )

        # 更新图书库存
        book.stock -= 1
        book.updated_at = now

        db.session.add(borrow_record)
        db.session.commit()

        # 添加库存变更日志
        inventory_log = InventoryLog(
            book_id=book_id,
            change_type='借出',
            change_amount=-1,
            after_stock=book.stock,
            operator_id=current_user.id,
            remark='用户借书',
            changed_at=now
        )
        db.session.add(inventory_log)

        # 添加系统操作日志
        Log.add_log(
            action='借阅图书',
            user_id=current_user.id,
            target_type='book',
            target_id=book_id,
            ip_address=request.remote_addr,
            description=f'用户借阅图书《{book.title}》，归还日期: {due_date.strftime("%Y-%m-%d")}'
        )

        db.session.commit()

        flash(f'成功借阅《{book.title}》，请在 {due_date.strftime("%Y-%m-%d")} 前归还', 'success')

    except Exception as e:
        db.session.rollback()
        flash(f'借阅失败: {str(e)}', 'danger')

    return redirect(url_for('book.book_detail', book_id=book_id))


@borrow_bp.route('/add/<int:book_id>', methods=['POST'])
@login_required
def add_borrow(book_id):
    # 验证图书存在
    book = Book.query.get_or_404(book_id)

    # 检查用户当前借阅数量是否达到上限(5本)
    current_borrows_count = BorrowRecord.query.filter_by(
        user_id=current_user.id,
        status=1  # 1表示借阅中
    ).count()

    if current_borrows_count >= 5:
        return jsonify({
            'success': False,
            'message': '您当前已借阅5本图书，达到借阅上限。请先归还后再借阅新书。'
        })

    # 默认借阅天数
    borrow_days = 14

    # 检查库存
    if book.stock <= 0:
        return jsonify({
            'success': False,
            'message': f'《{book.title}》当前无库存，无法借阅'
        })

    # 检查是否已借阅
    existing_borrow = BorrowRecord.query.filter_by(
        user_id=current_user.id,
        book_id=book_id,
        status=1  # 1表示借阅中
    ).first()

    if existing_borrow:
        return jsonify({
            'success': False,
            'message': f'您已借阅《{book.title}》，请勿重复借阅'
        })

    try:
        # 创建借阅记录
        now = datetime.datetime.now()
        due_date = now + datetime.timedelta(days=borrow_days)

        borrow_record = BorrowRecord(
            user_id=current_user.id,
            book_id=book_id,
            borrow_date=now,
            due_date=due_date,
            status=1,  # 1表示借阅中
            created_at=now,
            updated_at=now
        )

        # 更新图书库存
        book.stock -= 1
        book.updated_at = now

        db.session.add(borrow_record)
        db.session.commit()

        # 添加库存变更日志
        inventory_log = InventoryLog(
            book_id=book_id,
            change_type='借出',
            change_amount=-1,
            after_stock=book.stock,
            operator_id=current_user.id,
            remark='用户借书',
            changed_at=now
        )
        db.session.add(inventory_log)

        # 添加系统操作日志
        Log.add_log(
            action='借阅图书',
            user_id=current_user.id,
            target_type='book',
            target_id=book_id,
            ip_address=request.remote_addr,
            description=f'用户借阅图书《{book.title}》，归还日期: {due_date.strftime("%Y-%m-%d")}'
        )

        db.session.commit()

        return jsonify({
            'success': True,
            'message': f'成功借阅《{book.title}》，请在 {due_date.strftime("%Y-%m-%d")} 前归还'
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'借阅失败: {str(e)}'
        })


@borrow_bp.route('/return/<int:borrow_id>', methods=['POST'])
@login_required
def return_book(borrow_id):
    """还书操作"""
    # 查找借阅记录
    borrow_record = BorrowRecord.query.get_or_404(borrow_id)

    # 检查是否是自己的借阅记录或者是管理员
    if borrow_record.user_id != current_user.id and not current_user.has_permission('manage_borrows'):
        return jsonify({
            'success': False,
            'message': '您无权执行此操作'
        })

    # 检查是否已还
    if borrow_record.status != 1:
        return jsonify({
            'success': False,
            'message': '此书已归还，请勿重复操作'
        })

    try:
        book = Book.query.get(borrow_record.book_id)
        now = datetime.datetime.now()

        # 更新借阅记录
        borrow_record.status = 0  # 0表示已归还
        borrow_record.return_date = now
        borrow_record.updated_at = now

        # 更新图书库存
        book.stock += 1
        book.updated_at = now

        db.session.commit()

        # 添加库存变更日志
        inventory_log = InventoryLog(
            book_id=borrow_record.book_id,
            change_type='归还',
            change_amount=1,
            after_stock=book.stock,
            operator_id=current_user.id,
            remark='用户还书',
            changed_at=now
        )
        db.session.add(inventory_log)

        # 添加系统操作日志
        # 判断是否逾期归还
        is_overdue = now > borrow_record.due_date
        overdue_msg = '（逾期归还）' if is_overdue else ''

        Log.add_log(
            action='归还图书',
            user_id=current_user.id,
            target_type='book',
            target_id=borrow_record.book_id,
            ip_address=request.remote_addr,
            description=f'用户归还图书《{book.title}》{overdue_msg}'
        )

        db.session.commit()

        return jsonify({
            'success': True,
            'message': f'成功归还《{book.title}》'
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'归还失败: {str(e)}'
        })


@borrow_bp.route('/renew/<int:borrow_id>', methods=['POST'])
@login_required
def renew_book(borrow_id):
    """续借操作"""
    # 查找借阅记录
    borrow_record = BorrowRecord.query.get_or_404(borrow_id)

    # 检查是否是自己的借阅记录或者是管理员
    if borrow_record.user_id != current_user.id and not current_user.has_permission('manage_borrows'):
        return jsonify({
            'success': False,
            'message': '您无权执行此操作'
        })

    # 检查是否已还
    if borrow_record.status != 1:
        return jsonify({
            'success': False,
            'message': '此书已归还，无法续借'
        })

    # 检查续借次数限制（最多续借2次）
    if borrow_record.renew_count >= 2:
        return jsonify({
            'success': False,
            'message': '此书已达到最大续借次数，无法继续续借'
        })

    try:
        now = datetime.datetime.now()
        book = Book.query.get(borrow_record.book_id)

        # 检查是否已逾期
        if now > borrow_record.due_date:
            return jsonify({
                'success': False,
                'message': '此书已逾期，请先归还并处理逾期情况'
            })

        # 续借14天
        new_due_date = borrow_record.due_date + datetime.timedelta(days=14)

        # 更新借阅记录
        borrow_record.due_date = new_due_date
        borrow_record.renew_count += 1
        borrow_record.updated_at = now

        # 添加系统操作日志
        Log.add_log(
            action='续借图书',
            user_id=current_user.id,
            target_type='book',
            target_id=borrow_record.book_id,
            ip_address=request.remote_addr,
            description=f'用户续借图书《{book.title}》，新归还日期: {new_due_date.strftime("%Y-%m-%d")}'
        )

        db.session.commit()

        return jsonify({
            'success': True,
            'message': f'续借成功，新的归还日期为 {new_due_date.strftime("%Y-%m-%d")}'
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'续借失败: {str(e)}'
        })


@borrow_bp.route('/my_borrows')
@login_required
def my_borrows():
    """用户查看自己的借阅记录"""
    page = request.args.get('page', 1, type=int)
    status = request.args.get('status', default=None, type=int)

    # 构建查询
    query = BorrowRecord.query.filter_by(user_id=current_user.id)

    # 根据状态筛选
    if status is not None:
        query = query.filter_by(status=status)

    # 按借阅日期倒序排列
    query = query.order_by(BorrowRecord.borrow_date.desc())

    # 分页
    pagination = query.paginate(page=page, per_page=10, error_out=False)

    # 获取当前借阅数量和历史借阅数量（用于标签显示）
    current_borrows_count = BorrowRecord.query.filter_by(user_id=current_user.id, status=1).count()
    history_borrows_count = BorrowRecord.query.filter_by(user_id=current_user.id, status=0).count()

    # 记录日志 - 用户查看借阅记录
    Log.add_log(
        action='查看借阅记录',
        user_id=current_user.id,
        ip_address=request.remote_addr,
        description='用户查看个人借阅记录'
    )

    return render_template(
        'borrow/my_borrows.html',
        pagination=pagination,
        current_borrows_count=current_borrows_count,
        history_borrows_count=history_borrows_count,
        status=status,
        now=datetime.datetime.now()  # 添加当前时间变量
    )


@borrow_bp.route('/manage')
@login_required
@permission_required('manage_borrows')  # 替代 @admin_required
def manage_borrows():
    """管理员查看所有借阅记录"""
    page = request.args.get('page', 1, type=int)
    status = request.args.get('status', default=None, type=int)
    user_id = request.args.get('user_id', default=None, type=int)
    book_id = request.args.get('book_id', default=None, type=int)
    search = request.args.get('search', default='')

    # 构建查询
    query = BorrowRecord.query

    # 根据状态筛选
    if status is not None:
        query = query.filter_by(status=status)

    # 根据用户筛选
    if user_id:
        query = query.filter_by(user_id=user_id)

    # 根据图书筛选
    if book_id:
        query = query.filter_by(book_id=book_id)

    # 根据搜索条件筛选（用户名或图书名）
    if search:
        query = query.join(User, BorrowRecord.user_id == User.id) \
            .join(Book, BorrowRecord.book_id == Book.id) \
            .filter((User.username.like(f'%{search}%')) |
                    (Book.title.like(f'%{search}%')))

    # 按借阅日期倒序排列
    query = query.order_by(BorrowRecord.borrow_date.desc())

    # 分页
    pagination = query.paginate(page=page, per_page=10, error_out=False)

    # 获取统计数据
    current_borrows_count = BorrowRecord.query.filter_by(status=1).count()
    history_borrows_count = BorrowRecord.query.filter_by(status=0).count()

    # 获取所有用户（用于筛选）
    users = User.query.all()

    # 记录日志 - 管理员查看借阅记录
    Log.add_log(
        action='管理借阅记录',
        user_id=current_user.id,
        ip_address=request.remote_addr,
        description='管理员查看借阅管理页面'
    )

    return render_template(
        'borrow/borrow_management.html',
        pagination=pagination,
        current_borrows_count=current_borrows_count,
        history_borrows_count=history_borrows_count,
        status=status,
        user_id=user_id,
        book_id=book_id,
        search=search,
        users=users,
        now=datetime.datetime.now()  # 添加当前时间变量
    )


@borrow_bp.route('/admin/add', methods=['POST'])
@login_required
@permission_required('manage_borrows')  # 替代 @admin_required
def admin_add_borrow():
    """管理员为用户添加借阅记录"""
    user_id = request.form.get('user_id', type=int)
    book_id = request.form.get('book_id', type=int)
    borrow_days = request.form.get('borrow_days', type=int, default=14)

    if not user_id or not book_id:
        flash('用户ID和图书ID不能为空', 'danger')
        return redirect(url_for('borrow.manage_borrows'))

    # 验证用户和图书是否存在
    user = User.query.get_or_404(user_id)
    book = Book.query.get_or_404(book_id)

    # 检查库存
    if book.stock <= 0:
        flash(f'《{book.title}》当前无库存，无法借阅', 'danger')
        return redirect(url_for('borrow.manage_borrows'))

    # 检查用户是否已借阅此书
    existing_borrow = BorrowRecord.query.filter_by(
        user_id=user_id,
        book_id=book_id,
        status=1  # 1表示借阅中
    ).first()

    if existing_borrow:
        flash(f'用户 {user.username} 已借阅《{book.title}》，请勿重复借阅', 'warning')
        return redirect(url_for('borrow.manage_borrows'))

    try:
        # 创建借阅记录
        now = datetime.datetime.now()
        due_date = now + datetime.timedelta(days=borrow_days)

        borrow_record = BorrowRecord(
            user_id=user_id,
            book_id=book_id,
            borrow_date=now,
            due_date=due_date,
            status=1,  # 1表示借阅中
            created_at=now,
            updated_at=now
        )

        # 更新图书库存
        book.stock -= 1
        book.updated_at = now

        db.session.add(borrow_record)
        db.session.commit()

        # 添加库存变更日志
        inventory_log = InventoryLog(
            book_id=book_id,
            change_type='借出',
            change_amount=-1,
            after_stock=book.stock,
            operator_id=current_user.id,
            remark=f'管理员 {current_user.username} 为用户 {user.username} 借书',
            changed_at=now
        )
        db.session.add(inventory_log)

        # 添加系统操作日志
        Log.add_log(
            action='管理员借阅操作',
            user_id=current_user.id,
            target_type='book',
            target_id=book_id,
            ip_address=request.remote_addr,
            description=f'管理员为用户 {user.username} 借阅图书《{book.title}》，归还日期: {due_date.strftime("%Y-%m-%d")}'
        )

        db.session.commit()

        flash(f'成功为用户 {user.username} 借阅《{book.title}》，归还日期: {due_date.strftime("%Y-%m-%d")}', 'success')

    except Exception as e:
        db.session.rollback()
        flash(f'借阅失败: {str(e)}', 'danger')

    return redirect(url_for('borrow.manage_borrows'))


@borrow_bp.route('/overdue')
@login_required
@permission_required('manage_overdue')  # 替代 @admin_required
def overdue_borrows():
    """查看逾期借阅"""
    page = request.args.get('page', 1, type=int)
    now = datetime.datetime.now()

    # 查询所有已逾期且未归还的借阅记录
    query = BorrowRecord.query.filter(
        BorrowRecord.status == 1,  # 借阅中
        BorrowRecord.due_date < now  # 已过期
    ).order_by(BorrowRecord.due_date)  # 按到期日期排序，最早到期的排在前面

    pagination = query.paginate(page=page, per_page=10, error_out=False)

    # 计算逾期总数
    overdue_count = query.count()

    # 记录日志 - 管理员查看逾期记录
    Log.add_log(
        action='查看逾期记录',
        user_id=current_user.id,
        ip_address=request.remote_addr,
        description='管理员查看逾期借阅记录'
    )

    return render_template(
        'borrow/overdue.html',
        pagination=pagination,
        overdue_count=overdue_count
    )


@borrow_bp.route('/overdue/notify/<int:borrow_id>', methods=['POST'])
@login_required
@permission_required('manage_overdue')  # 替代 @admin_required
def notify_overdue(borrow_id):
    """发送逾期通知"""
    from app.models.notification import Notification

    borrow_record = BorrowRecord.query.get_or_404(borrow_id)

    # 检查是否已还
    if borrow_record.status != 1:
        return jsonify({
            'success': False,
            'message': '此书已归还，无需发送逾期通知'
        })

    now = datetime.datetime.now()

    # 检查是否确实逾期
    if borrow_record.due_date > now:
        return jsonify({
            'success': False,
            'message': '此借阅记录尚未逾期'
        })

    try:
        book = Book.query.get(borrow_record.book_id)
        user = User.query.get(borrow_record.user_id)

        # 创建通知
        notification = Notification(
            user_id=borrow_record.user_id,
            title='图书逾期提醒',
            content=f'您借阅的《{borrow_record.book.title}》已逾期，请尽快归还。应还日期: {borrow_record.due_date.strftime("%Y-%m-%d")}',
            type='overdue',
            sender_id=current_user.id,
            created_at=now
        )

        db.session.add(notification)

        # 更新借阅记录备注
        borrow_record.remark = f'{borrow_record.remark or ""}[{now.strftime("%Y-%m-%d")} 已发送逾期通知]'
        borrow_record.updated_at = now

        # 添加系统操作日志
        Log.add_log(
            action='发送逾期通知',
            user_id=current_user.id,
            target_type='notification',
            target_id=borrow_record.user_id,
            ip_address=request.remote_addr,
            description=f'管理员向用户 {user.username} 发送图书《{book.title}》逾期通知'
        )

        db.session.commit()

        return jsonify({
            'success': True,
            'message': '已成功发送逾期通知'
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'发送通知失败: {str(e)}'
        })
