# 管理后台蓝图
# 处理管理员界面、用户管理、系统设置、统计信息等功能

from flask import Blueprint, render_template, request, jsonify, redirect, flash, current_app
from flask_login import login_required, current_user
import os

from src.clients import db
from src.models import User, Recording, TranscriptChunk, SystemSetting
from src.services import process_recording_chunks, get_file_monitor_functions

# 创建管理后台蓝图
admin_bp = Blueprint('admin', __name__)

# 全局变量（从 app.py 导入）
limiter = None
csrf = None
bcrypt = None
ENABLE_INQUIRE_MODE = False
EMBEDDINGS_AVAILABLE = False
USE_ASR_ENDPOINT = False
ASR_BASE_URL = None
TEXT_MODEL_BASE_URL = None
TEXT_MODEL_NAME = None
TRANSCRIPTION_BASE_URL = None
VALID_TOKEN = None

def init_admin_bp(
    limiter_instance, csrf_instance, bcrypt_instance,
    enable_inquire_mode, embeddings_available,
    use_asr_endpoint, asr_base_url,
    text_model_base_url, text_model_name,
    transcription_base_url, valid_token
):
    """初始化蓝图所需的全局变量"""
    global limiter, csrf, bcrypt
    global ENABLE_INQUIRE_MODE, EMBEDDINGS_AVAILABLE
    global USE_ASR_ENDPOINT, ASR_BASE_URL
    global TEXT_MODEL_BASE_URL, TEXT_MODEL_NAME
    global TRANSCRIPTION_BASE_URL, VALID_TOKEN
    
    limiter = limiter_instance
    csrf = csrf_instance
    bcrypt = bcrypt_instance
    ENABLE_INQUIRE_MODE = enable_inquire_mode
    EMBEDDINGS_AVAILABLE = embeddings_available
    USE_ASR_ENDPOINT = use_asr_endpoint
    ASR_BASE_URL = asr_base_url
    TEXT_MODEL_BASE_URL = text_model_base_url
    TEXT_MODEL_NAME = text_model_name
    TRANSCRIPTION_BASE_URL = transcription_base_url
    VALID_TOKEN = valid_token


# ==================== 管理员界面路由 ====================

@admin_bp.route('/admin', methods=['GET'])
@login_required
def admin():
    """管理员界面主页"""
    # 检查用户是否为管理员
    if not current_user.is_admin:
        flash('您没有访问管理员页面的权限。', 'danger')
        return redirect('/tool/speakr')
    return render_template('admin.html', title='管理后台', inquire_mode_enabled=ENABLE_INQUIRE_MODE)


# ==================== 用户管理路由 ====================

@admin_bp.route('/admin/users', methods=['GET'])
@login_required
def admin_get_users():
    """获取所有用户列表"""
    # 检查用户是否为管理员
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    users = User.query.all()
    user_data = []
    
    for user in users:
        # 获取录音数量和存储使用量
        recordings_count = len(user.recordings)
        storage_used = sum(r.file_size for r in user.recordings if r.file_size) or 0
        
        user_data.append({
            'id': user.id,
            'username': user.username,
            'email': user.email,
            'is_admin': user.is_admin,
            'recordings_count': recordings_count,
            'storage_used': storage_used
        })
    
    return jsonify(user_data)


@admin_bp.route('/admin/users', methods=['POST'])
@login_required
def admin_add_user():
    """添加新用户"""
    # 检查用户是否为管理员
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    data = request.json
    if not data:
        return jsonify({'error': '未提供数据'}), 400
    
    # 验证必填字段
    required_fields = ['username', 'email', 'password']
    for field in required_fields:
        if field not in data:
            return jsonify({'error': f'缺少必填字段: {field}'}), 400
    
    # 检查用户名或邮箱是否已存在
    if User.query.filter_by(username=data['username']).first():
        return jsonify({'error': '用户名已存在'}), 400
    
    if User.query.filter_by(email=data['email']).first():
        return jsonify({'error': '邮箱已存在'}), 400
    
    # 创建新用户
    hashed_password = bcrypt.generate_password_hash(data['password']).decode('utf-8')
    new_user = User(
        username=data['username'],
        email=data['email'],
        password=hashed_password,
        is_admin=data.get('is_admin', False)
    )
    
    db.session.add(new_user)
    db.session.commit()
    
    return jsonify({
        'id': new_user.id,
        'username': new_user.username,
        'email': new_user.email,
        'is_admin': new_user.is_admin,
        'recordings_count': 0,
        'storage_used': 0
    }), 201


@admin_bp.route('/admin/users/<string:user_id>', methods=['PUT'])
@login_required
def admin_update_user(user_id):
    """更新用户信息"""
    # 检查用户是否为管理员
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    user = db.session.get(User, user_id)
    if not user:
        return jsonify({'error': '用户不存在'}), 404
    
    data = request.json
    if not data:
        return jsonify({'error': '未提供数据'}), 400
    
    # 更新用户字段
    if 'username' in data and data['username'] != user.username:
        # 检查用户名是否已存在
        if User.query.filter_by(username=data['username']).first():
            return jsonify({'error': '用户名已存在'}), 400
        user.username = data['username']
    
    if 'email' in data and data['email'] != user.email:
        # 检查邮箱是否已存在
        if User.query.filter_by(email=data['email']).first():
            return jsonify({'error': '邮箱已存在'}), 400
        user.email = data['email']
    
    if 'password' in data and data['password']:
        user.password = bcrypt.generate_password_hash(data['password']).decode('utf-8')
    
    if 'is_admin' in data:
        user.is_admin = data['is_admin']
    
    db.session.commit()
    
    # 获取录音数量和存储使用量
    recordings_count = len(user.recordings)
    storage_used = sum(r.file_size for r in user.recordings if r.file_size) or 0
    
    return jsonify({
        'id': user.id,
        'username': user.username,
        'email': user.email,
        'is_admin': user.is_admin,
        'recordings_count': recordings_count,
        'storage_used': storage_used
    })


@admin_bp.route('/admin/users/<string:user_id>', methods=['DELETE'])
@login_required
def admin_delete_user(user_id):
    """删除用户"""
    # 检查用户是否为管理员
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    # 防止删除自己
    if user_id == current_user.id:
        return jsonify({'error': '不能删除自己的账户'}), 400
    
    user = db.session.get(User, user_id)
    if not user:
        return jsonify({'error': '用户不存在'}), 404
    
    # 删除用户的录音和音频文件
    total_chunks = 0
    if ENABLE_INQUIRE_MODE:
        total_chunks = TranscriptChunk.query.filter_by(user_id=user_id).count()
        if total_chunks > 0:
            from flask import current_app
            current_app.logger.info(f"正在删除用户 {user_id} 的 {total_chunks} 个转录片段及其嵌入向量")
    
    for recording in user.recordings:
        try:
            if recording.audio_path and os.path.exists(recording.audio_path):
                os.remove(recording.audio_path)
        except Exception as e:
            from flask import current_app
            current_app.logger.error(f"删除音频文件 {recording.audio_path} 时出错: {e}")
    
    # 删除用户（级联删除将处理所有相关数据，包括片段/嵌入向量）
    db.session.delete(user)
    db.session.commit()
    
    if ENABLE_INQUIRE_MODE and total_chunks > 0:
        from flask import current_app
        current_app.logger.info(f"成功删除用户 {user_id} 的 {total_chunks} 个嵌入向量和片段")
    
    return jsonify({'success': True})


@admin_bp.route('/admin/users/<string:user_id>/toggle-admin', methods=['POST'])
@login_required
def admin_toggle_admin(user_id):
    """切换用户管理员权限"""
    # 检查用户是否为管理员
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    # 防止修改自己的管理员状态
    if user_id == current_user.id:
        return jsonify({'error': '不能修改自己的管理员状态'}), 400
    
    user = db.session.get(User, user_id)
    if not user:
        return jsonify({'error': '用户不存在'}), 404
    
    # 切换管理员状态
    user.is_admin = not user.is_admin
    db.session.commit()
    
    return jsonify({'success': True, 'is_admin': user.is_admin})


# ==================== 系统统计路由 ====================

@admin_bp.route('/admin/stats', methods=['GET'])
@login_required
def admin_get_stats():
    """获取系统统计信息"""
    # 检查用户是否为管理员
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    # 获取总用户数
    total_users = User.query.count()
    
    # 获取总录音数
    total_recordings = Recording.query.count()
    
    # 按状态获取录音数
    completed_recordings = Recording.query.filter_by(status='COMPLETED').count()
    processing_recordings = Recording.query.filter(Recording.status.in_(['PROCESSING', 'SUMMARIZING'])).count()
    pending_recordings = Recording.query.filter_by(status='PENDING').count()
    failed_recordings = Recording.query.filter_by(status='FAILED').count()
    
    # 获取总存储使用量
    total_storage = db.session.query(db.func.sum(Recording.file_size)).scalar() or 0
    
    # 获取存储使用量最多的前5个用户
    top_users_query = db.session.query(
        User.id,
        User.username,
        db.func.count(Recording.id).label('recordings_count'),
        db.func.sum(Recording.file_size).label('storage_used')
    ).join(Recording, User.id == Recording.user_id, isouter=True) \
     .group_by(User.id) \
     .order_by(db.func.sum(Recording.file_size).desc()) \
     .limit(5)
    
    top_users = []
    for user_id, username, recordings_count, storage_used in top_users_query:
        top_users.append({
            'id': user_id,
            'username': username,
            'recordings_count': recordings_count or 0,
            'storage_used': storage_used or 0
        })
    
    # 获取总查询数（聊天请求）
    # 这是一个占位符 - 需要在数据库中跟踪此数据
    total_queries = 0
    
    return jsonify({
        'total_users': total_users,
        'total_recordings': total_recordings,
        'completed_recordings': completed_recordings,
        'processing_recordings': processing_recordings,
        'pending_recordings': pending_recordings,
        'failed_recordings': failed_recordings,
        'total_storage': total_storage,
        'top_users': top_users,
        'total_queries': total_queries
    })


# ==================== 系统设置路由 ====================

@admin_bp.route('/admin/settings', methods=['GET'])
@login_required
def admin_get_settings():
    """获取所有系统设置"""
    # 检查用户是否为管理员
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    settings = SystemSetting.query.all()
    return jsonify([setting.to_dict() for setting in settings])


@admin_bp.route('/admin/settings', methods=['POST'])
@login_required
def admin_update_setting():
    """更新系统设置"""
    # 检查用户是否为管理员
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    data = request.json
    if not data:
        return jsonify({'error': '未提供数据'}), 400
    
    key = data.get('key')
    value = data.get('value')
    description = data.get('description')
    setting_type = data.get('setting_type', 'string')
    
    if not key:
        return jsonify({'error': '设置键名是必填的'}), 400
    
    # 验证设置类型
    valid_types = ['string', 'integer', 'boolean', 'float']
    if setting_type not in valid_types:
        return jsonify({'error': f'无效的设置类型。必须是以下之一: {", ".join(valid_types)}'}), 400
    
    # 根据类型验证值
    if setting_type == 'integer':
        try:
            int(value) if value is not None and value != '' else None
        except (ValueError, TypeError):
            return jsonify({'error': '值必须是有效的整数'}), 400
    elif setting_type == 'float':
        try:
            float(value) if value is not None and value != '' else None
        except (ValueError, TypeError):
            return jsonify({'error': '值必须是有效的数字'}), 400
    elif setting_type == 'boolean':
        if value not in ['true', 'false', '1', '0', 'yes', 'no', True, False, 1, 0]:
            return jsonify({'error': '值必须是有效的布尔值 (true/false, 1/0, yes/no)'}), 400
    
    try:
        setting = SystemSetting.set_setting(key, value, description, setting_type)
        return jsonify(setting.to_dict())
    except Exception as e:
        db.session.rollback()
        from flask import current_app
        current_app.logger.error(f"更新设置 {key} 时出错: {e}")
        return jsonify({'error': str(e)}), 500


# ==================== 录音迁移路由 ====================

@admin_bp.route('/api/admin/migrate_recordings', methods=['POST'])
@login_required
def migrate_existing_recordings_api():
    """迁移现有录音以支持询问模式（仅限管理员）"""
    if not current_user.is_admin:
        return jsonify({'error': '未授权。需要管理员权限。'}), 403
    
    try:
        # 统计需要处理的录音
        completed_recordings = Recording.query.filter_by(status='COMPLETED').all()
        recordings_needing_processing = []
        
        for recording in completed_recordings:
            if recording.transcription:  # 有转录文本
                chunk_count = TranscriptChunk.query.filter_by(recording_id=recording.id).count()
                if chunk_count == 0:  # 还没有片段
                    recordings_needing_processing.append(recording)
        
        if len(recordings_needing_processing) == 0:
            return jsonify({
                'success': True,
                'message': '所有录音都已为询问模式处理完成',
                'processed': 0,
                'total': len(completed_recordings)
            })
        
        # 分批处理以避免超时
        batch_size = min(5, len(recordings_needing_processing))  # 每次最多处理5个
        processed = 0
        errors = 0
        
        for i in range(min(batch_size, len(recordings_needing_processing))):
            recording = recordings_needing_processing[i]
            try:
                success = process_recording_chunks(recording.id)
                if success:
                    processed += 1
                else:
                    errors += 1
            except Exception as e:
                from flask import current_app
                current_app.logger.error(f"迁移时处理录音 {recording.id} 出错: {e}")
                errors += 1
        
        remaining = max(0, len(recordings_needing_processing) - batch_size)
        
        return jsonify({
            'success': True,
            'message': f'已处理 {processed} 个录音。剩余 {remaining} 个。',
            'processed': processed,
            'errors': errors,
            'remaining': remaining,
            'total': len(recordings_needing_processing)
        })
        
    except Exception as e:
        from flask import current_app
        current_app.logger.error(f"迁移 API 出错: {e}")
        return jsonify({'error': str(e)}), 500


# ==================== 自动处理路由 ====================

@admin_bp.route('/admin/auto-process/status', methods=['GET'])
@login_required
def admin_get_auto_process_status():
    """获取自动文件处理系统的状态"""
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    try:
        _, _, get_file_monitor_status = get_file_monitor_functions()
        status = get_file_monitor_status()
        
        # 添加配置信息（从 Flask app.config 读取）
        config = {
            'enabled': current_app.config.get('ENABLE_AUTO_PROCESSING', 'false'),
            'watch_directory': current_app.config.get('AUTO_PROCESS_WATCH_DIR', '/data/auto-process'),
            'check_interval': current_app.config.get('AUTO_PROCESS_CHECK_INTERVAL', 30),
            'mode': current_app.config.get('AUTO_PROCESS_MODE', 'admin_only'),
            'default_username': current_app.config.get('AUTO_PROCESS_DEFAULT_USERNAME')
        }
        
        return jsonify({
            'status': status,
            'config': config
        })
        
    except Exception as e:
        from flask import current_app
        current_app.logger.error(f"获取自动处理状态时出错: {e}")
        return jsonify({'error': str(e)}), 500


@admin_bp.route('/admin/auto-process/start', methods=['POST'])
@login_required
def admin_start_auto_process():
    """启动自动文件处理系统"""
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    try:
        start_file_monitor, _, _ = get_file_monitor_functions()
        start_file_monitor()
        return jsonify({'success': True, 'message': '自动处理已启动'})
    except Exception as e:
        from flask import current_app
        current_app.logger.error(f"启动自动处理时出错: {e}")
        return jsonify({'error': str(e)}), 500


@admin_bp.route('/admin/auto-process/stop', methods=['POST'])
@login_required
def admin_stop_auto_process():
    """停止自动文件处理系统"""
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    try:
        _, stop_file_monitor, _ = get_file_monitor_functions()
        stop_file_monitor()
        return jsonify({'success': True, 'message': '自动处理已停止'})
    except Exception as e:
        from flask import current_app
        current_app.logger.error(f"停止自动处理时出错: {e}")
        return jsonify({'error': str(e)}), 500


@admin_bp.route('/admin/auto-process/config', methods=['POST'])
@login_required
def admin_update_auto_process_config():
    """更新自动处理配置（需要重启）"""
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    try:
        data = request.json
        if not data:
            return jsonify({'error': '未提供配置数据'}), 400
        
        # 此端点通常会更新环境变量或配置文件
        # 目前，我们只返回当前配置并说明需要重启
        return jsonify({
            'success': True, 
            'message': '配置已更新。需要重启才能应用更改。',
            'note': '环境变量需要手动更新，并且需要重启应用程序。'
        })
        
    except Exception as e:
        from flask import current_app
        current_app.logger.error(f"更新自动处理配置时出错: {e}")
        return jsonify({'error': str(e)}), 500


# ==================== Inquire 管理路由 ====================

@admin_bp.route('/admin/inquire/process-recordings', methods=['POST'])
@login_required
def admin_process_recordings_for_inquire():
    """处理所有剩余的录音以支持询问模式（对它们进行分块和嵌入）"""
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    try:
        # 从请求中获取可选参数
        data = request.json or {}
        batch_size = data.get('batch_size', 10)
        max_recordings = data.get('max_recordings', None)
        
        # 查找需要处理的录音
        completed_recordings = Recording.query.filter_by(status='COMPLETED').all()
        recordings_needing_processing = []
        
        for recording in completed_recordings:
            if recording.transcription:  # 有转录文本
                chunk_count = TranscriptChunk.query.filter_by(recording_id=recording.id).count()
                if chunk_count == 0:  # 还没有片段
                    recordings_needing_processing.append(recording)
                    if max_recordings and len(recordings_needing_processing) >= max_recordings:
                        break
        
        total_to_process = len(recordings_needing_processing)
        
        if total_to_process == 0:
            return jsonify({
                'success': True,
                'message': '所有录音都已为询问模式处理完成。',
                'processed': 0,
                'total': 0
            })
        
        # 分批处理录音
        processed = 0
        failed = []
        
        for recording in recordings_needing_processing:
            try:
                success = process_recording_chunks(recording.id)
                if success:
                    processed += 1
                    from flask import current_app
                    current_app.logger.info(f"管理员 API: 已处理录音的分块: {recording.title} ({recording.id})")
                else:
                    failed.append({'id': recording.id, 'title': recording.title, 'reason': '处理返回 false'})
            except Exception as e:
                from flask import current_app
                current_app.logger.error(f"管理员 API: 处理录音 {recording.id} 失败: {e}")
                failed.append({'id': recording.id, 'title': recording.title, 'reason': str(e)})
            
            # 每批次后提交
            if processed % batch_size == 0:
                db.session.commit()
        
        # 最终提交
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': f'已处理 {total_to_process} 个录音中的 {processed} 个。',
            'processed': processed,
            'total': total_to_process,
            'failed': failed
        })
        
    except Exception as e:
        from flask import current_app
        current_app.logger.error(f"管理员处理录音端点出错: {e}")
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@admin_bp.route('/admin/inquire/status', methods=['GET'])
@login_required
def admin_inquire_status():
    """获取询问模式的录音状态"""
    if not current_user.is_admin:
        return jsonify({'error': '未授权'}), 403
    
    try:
        # 统计已完成的录音总数
        total_completed = Recording.query.filter_by(status='COMPLETED').count()
        
        # 统计有转录文本的录音数
        recordings_with_transcriptions = Recording.query.filter(
            Recording.status == 'COMPLETED',
            Recording.transcription.isnot(None),
            Recording.transcription != ''
        ).count()
        
        # 统计已为询问模式处理的录音数
        processed_recordings = db.session.query(Recording.id).join(
            TranscriptChunk, Recording.id == TranscriptChunk.recording_id
        ).distinct().count()
        
        # 统计仍需处理的录音数
        completed_recordings = Recording.query.filter_by(status='COMPLETED').all()
        need_processing = 0
        
        for recording in completed_recordings:
            if recording.transcription:  # 有转录文本
                chunk_count = TranscriptChunk.query.filter_by(recording_id=recording.id).count()
                if chunk_count == 0:  # 还没有片段
                    need_processing += 1
        
        # 获取总片段数和嵌入向量数
        total_chunks = TranscriptChunk.query.count()
        
        return jsonify({
            'total_completed_recordings': total_completed,
            'recordings_with_transcriptions': recordings_with_transcriptions,
            'processed_for_inquire': processed_recordings,
            'need_processing': need_processing,
            'total_chunks': total_chunks,
            'embeddings_available': EMBEDDINGS_AVAILABLE
        })
        
    except Exception as e:
        from flask import current_app
        current_app.logger.error(f"获取询问状态时出错: {e}")
        return jsonify({'error': str(e)}), 500


# ==================== 系统信息和用户偏好路由 ====================

@admin_bp.route('/api/user/preferences', methods=['POST'])
@login_required
def save_user_preferences():
    """保存用户偏好设置，包括界面语言"""
    data = request.json
    
    if 'language' in data:
        current_user.ui_language = data['language']
    
    db.session.commit()
    
    return jsonify({
        'success': True,
        'message': '偏好设置保存成功',
        'ui_language': current_user.ui_language
    })


def get_version():
    """获取系统版本号"""
    # 首先尝试读取 VERSION 文件（在 Docker 中有效）
    try:
        with open('VERSION', 'r') as f:
            return f.read().strip()
    except FileNotFoundError:
        pass
    
    # 回退到 git 标签（在开发环境中有效）
    try:
        import subprocess
        return subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0'], 
                                     stderr=subprocess.DEVNULL).decode().strip()
    except:
        pass
    
    # 最终回退
    return "unknown"


@admin_bp.route('/api/system/info', methods=['GET'])
def get_system_info():
    """获取系统信息，包括版本和模型详情"""
    try:
        # 使用与启动时相同的版本检测逻辑
        version = get_version()
        
        return jsonify({
            'version': version,
            'llm_endpoint': TEXT_MODEL_BASE_URL,
            'llm_model': TEXT_MODEL_NAME,
            'whisper_endpoint': os.environ.get('TRANSCRIPTION_BASE_URL', 'https://api.openai.com/v1'),
            'asr_enabled': USE_ASR_ENDPOINT,
            'asr_endpoint': ASR_BASE_URL if USE_ASR_ENDPOINT else None
        })
    except Exception as e:
        from flask import current_app
        current_app.logger.error(f"获取系统信息时出错: {e}")
        return jsonify({'error': '无法获取系统信息'}), 500
