# 认证蓝图
# 处理用户注册、登录、登出、账户管理等认证相关功能

from flask import Blueprint, render_template, request, redirect, flash, session, make_response, jsonify
from flask_login import login_required, current_user, logout_user
from wtforms import ValidationError
import os

from src.clients import db
from src.models import User, SystemSetting, password_check
from src.services import auto_login

# 创建认证蓝图
auth_bp = Blueprint('auth', __name__)

# 全局变量（从 app.py 导入）
limiter = None
csrf = None
bcrypt = None
USE_ASR_ENDPOINT = None
ASR_DIARIZE = None

def init_auth_bp(limiter_instance, csrf_instance, bcrypt_instance, use_asr_endpoint, asr_diarize):
    """初始化蓝图所需的全局变量"""
    global limiter, csrf, bcrypt, USE_ASR_ENDPOINT, ASR_DIARIZE
    limiter = limiter_instance
    csrf = csrf_instance
    bcrypt = bcrypt_instance
    USE_ASR_ENDPOINT = use_asr_endpoint
    ASR_DIARIZE = asr_diarize
    
    # 应用路由级限流（在 init 中应用，避免模块导入时 limiter 为 None）
    # 注册限流：每分钟最多5次，防止恶意注册
    auth_bp.view_functions['register'] = limiter.limit("5 per minute")(register)
    # 登录限流：每分钟最多10次，暴力破解防护
    auth_bp.view_functions['login'] = limiter.limit("10 per minute")(login)
    # 修改密码限流：每分钟最多3次
    auth_bp.view_functions['change_password'] = limiter.limit("3 per minute")(change_password)

@auth_bp.route('/register', methods=['GET', 'POST'])
def register():
    """用户注册路由"""
    # 如果已认证，重定向到首页
    if current_user.is_authenticated:
        return redirect('/tool/speakr')
    
    # 自动登录并重定向
    auto_login()
    return redirect('/tool/speakr')

@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
    """用户登录路由"""
    # 如果已认证，重定向到首页
    if current_user.is_authenticated:
        return redirect('/tool/speakr')
    
    # 自动登录并重定向
    auto_login()
    return redirect('/tool/speakr')

@auth_bp.route('/logout')
def logout():
    """用户登出路由"""
    # 清除 Flask-Login 会话
    logout_user()
    
    # 清除 Flask 会话
    session.clear()
    
    # 创建响应
    response = make_response('''
    <!DOCTYPE html>
    <html>
    <head>
        <title>退出成功</title>
        <meta charset="utf-8">
        <style>
            body {
                font-family: Arial, sans-serif;
                text-align: center;
                padding: 50px;
                background-color: #f5f5f5;
            }
            .container {
                background: white;
                padding: 40px;
                border-radius: 10px;
                box-shadow: 0 2px 10px rgba(0,0,0,0.1);
                max-width: 500px;
                margin: 0 auto;
            }
            h1 {
                color: #4CAF50;
            }
            .message {
                margin: 20px 0;
                font-size: 18px;
                color: #333;
            }
            .login-link {
                display: inline-block;
                margin-top: 20px;
                padding: 10px 20px;
                background-color: #007bff;
                color: white;
                text-decoration: none;
                border-radius: 5px;
            }
            .login-link:hover {
                background-color: #0056b3;
            }
        </style>
        <script>
            // 清除本地存储和会话存储
            localStorage.clear();
            sessionStorage.clear();
            
            // 防止浏览器缓存
            window.history.forward();
        </script>
    </head>
    <body>
        <div class="container">
            <h1>✓ 退出成功</h1>
            <div class="message">您已成功退出系统</div>
            <p>感谢使用我们的服务！</p>
        </div>
    </body>
    </html>
    ''')
    
    # 设置响应头，防止缓存
    response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
    response.headers['Pragma'] = 'no-cache'
    response.headers['Expires'] = '0'
    
    return response

@auth_bp.route('/account', methods=['GET', 'POST'])
@login_required
def account():
    """账户管理路由"""
    if request.method == 'POST':
        # 只更新表单中存在的字段
        # 这可以防止在切换标签页时清除数据
        
        # 检查是否是账户信息表单（包含 user_name 字段）
        if 'user_name' in request.form:
            # 处理个人信息更新
            user_name = request.form.get('user_name')
            user_job_title = request.form.get('user_job_title')
            user_company = request.form.get('user_company')
            ui_lang = request.form.get('ui_language')
            transcription_lang = request.form.get('transcription_language')
            output_lang = request.form.get('output_language')
            
            current_user.name = user_name if user_name else None
            current_user.job_title = user_job_title if user_job_title else None
            current_user.company = user_company if user_company else None
            current_user.ui_language = ui_lang if ui_lang else 'en'
            current_user.transcription_language = transcription_lang if transcription_lang else None
            current_user.output_language = output_lang if output_lang else None
        
        # 检查是否是自定义提示词表单（包含 summary_prompt 字段）
        elif 'summary_prompt' in request.form:
            # 处理自定义提示词更新
            summary_prompt_text = request.form.get('summary_prompt')
            current_user.summary_prompt = summary_prompt_text if summary_prompt_text else None
            # 处理事件提取设置
            current_user.extract_events = 'extract_events' in request.form
        
        # 只有在环境变量中没有设置 ASR_DIARIZE 时才更新
        if 'ASR_DIARIZE' not in os.environ:
            current_user.diarize = 'diarize' in request.form
        
        db.session.commit()
        
        # 为 AJAX 请求返回 JSON 响应
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest' or request.accept_mimetypes.best == 'application/json':
            return jsonify({'success': True, 'message': '账户信息更新成功！'})
        
        # 常规表单提交并重定向
        flash('账户信息更新成功！', 'success')
        
        # 重定向时保留活动标签
        if 'summary_prompt' in request.form:
            return redirect('/tool/speakr/account' + '#prompts')
        else:
            return redirect('/tool/speakr/account')
        
    # 从系统设置中获取管理员默认提示词
    admin_default_prompt = SystemSetting.get_setting('admin_default_summary_prompt', None)
    if admin_default_prompt:
        default_summary_prompt_text = admin_default_prompt
    else:
        # 如果管理员没有设置，则使用硬编码的默认值
        default_summary_prompt_text = """生成一份全面的摘要，包括以下部分：
- **讨论的关键问题**：主要主题的要点列表
- **做出的关键决定**：达成的任何决定的要点列表
- **行动项**：分配的任务的要点列表，包括提到的负责人"""
    
    asr_diarize_locked = 'ASR_DIARIZE' in os.environ
    
    return render_template('account.html', 
                           title='账户', 
                           default_summary_prompt_text=default_summary_prompt_text,
                           use_asr_endpoint=USE_ASR_ENDPOINT,
                           asr_diarize_locked=asr_diarize_locked,
                           asr_diarize_env_value=ASR_DIARIZE)

@auth_bp.route('/change_password', methods=['POST'])
@login_required
def change_password():
    """修改密码路由"""
    current_password = request.form.get('current_password')
    new_password = request.form.get('new_password')
    confirm_password = request.form.get('confirm_password')
    
    # 验证表单数据
    if not current_password or not new_password or not confirm_password:
        flash('所有字段都是必填的。', 'danger')
        return redirect('/tool/speakr/account')
    
    if new_password != confirm_password:
        flash('新密码和确认密码不匹配。', 'danger')
        return redirect('/tool/speakr/account')
        
    # 自定义验证新密码
    try:
        password_check(None, type('obj', (object,), {'data': new_password}))
    except ValidationError as e:
        flash(str(e), 'danger')
        return redirect('/tool/speakr/account')
    
    # 检查当前密码是否正确
    if not bcrypt.check_password_hash(current_user.password, current_password):
        flash('当前密码不正确。', 'danger')
        return redirect('/tool/speakr/account')
    
    # 更新密码
    current_user.password = bcrypt.generate_password_hash(new_password).decode('utf-8')
    db.session.commit()
    
    flash('您的密码已成功更新。', 'success')
    return redirect('/tool/speakr/account')
