"""
认证相关 API
登录、退出、修改密码
"""
import hashlib
import secrets
from datetime import datetime, timedelta
from flask import Blueprint, request, jsonify, g
from lib.db import execute_query, execute_update
from lib.logger import log_info, log_error, log_warning

auth_bp = Blueprint('auth', __name__, url_prefix='/api/auth')


def md5_password(password):
    """MD5加密密码"""
    return hashlib.md5(password.encode('utf-8')).hexdigest()


def generate_token():
    """生成登录令牌"""
    return secrets.token_hex(32)


def get_user_by_token(token):
    """根据token获取用户信息"""
    if not token:
        return None
    
    try:
        user = execute_query(
            "SELECT id, username, real_name, token_expire FROM t_daily_report_admin WHERE token = %s",
            (token,)
        )
        if user and user[0]:
            user_info = user[0]
            if user_info.get('token_expire') and user_info['token_expire'] > datetime.now():
                return user_info
    except Exception as e:
        log_warning(f"[认证] 获取用户信息失败: {e}", 'auth')
    
    return None


def get_current_user():
    """获取当前登录用户（从token）"""
    token = request.headers.get('Authorization', '')
    if token.startswith('Bearer '):
        token = token[7:]
    
    if not token:
        return None
    
    try:
        user = execute_query(
            "SELECT id, username, real_name, token_expire FROM t_daily_report_admin WHERE token = %s",
            (token,)
        )
        if user and user[0]:
            user_info = user[0]
            if user_info.get('token_expire') and user_info['token_expire'] > datetime.now():
                return user_info
    except Exception as e:
        log_warning(f"[认证] 获取用户信息失败: {e}", 'auth')
    
    return None


def login_required(f):
    """登录验证装饰器"""
    from functools import wraps
    @wraps(f)
    def decorated_function(*args, **kwargs):
        user = get_current_user()
        if not user:
            return jsonify({'success': False, 'message': '未登录或登录已过期', 'code': 401}), 401
        g.current_user = user
        return f(*args, **kwargs)
    return decorated_function


@auth_bp.route('/login', methods=['POST'])
def login():
    """登录"""
    try:
        data = request.get_json()
        username = data.get('username', '').strip()
        password = data.get('password', '').strip()
        
        if not username or not password:
            return jsonify({'success': False, 'message': '用户名和密码不能为空'})
        
        # 查询用户
        users = execute_query(
            "SELECT id, username, password, real_name FROM t_daily_report_admin WHERE username = %s",
            (username,)
        )
        
        if not users or not users[0]:
            log_warning(f"[登录] 用户不存在: {username}", 'auth')
            return jsonify({'success': False, 'message': '用户名或密码错误'})
        
        user = users[0]
        
        # 验证密码
        password_md5 = md5_password(password)
        if user['password'] != password_md5:
            log_warning(f"[登录] 密码错误: {username}", 'auth')
            return jsonify({'success': False, 'message': '用户名或密码错误'})
        
        # 生成token，有效期7天
        token = generate_token()
        token_expire = datetime.now() + timedelta(days=7)
        
        # 获取客户端IP
        client_ip = request.remote_addr
        
        # 更新用户token和登录信息
        execute_update(
            """UPDATE t_daily_report_admin 
               SET token = %s, token_expire = %s, last_login_time = NOW(), last_login_ip = %s
               WHERE id = %s""",
            (token, token_expire, client_ip, user['id'])
        )
        
        log_info(f"[登录] 登录成功: {username}", 'auth')
        
        return jsonify({
            'success': True,
            'message': '登录成功',
            'data': {
                'token': token,
                'username': user['username'],
                'real_name': user.get('real_name', ''),
                'expires_in': 7 * 24 * 3600
            }
        })
    except Exception as e:
        log_error(f"[登录] 异常: {e}", 'auth', exc_info=True)
        return jsonify({'success': False, 'message': '登录失败: ' + str(e)})


@auth_bp.route('/logout', methods=['POST'])
@login_required
def logout():
    """退出登录"""
    try:
        user = g.current_user
        # 清除token
        execute_update(
            "UPDATE t_daily_report_admin SET token = NULL, token_expire = NULL WHERE id = %s",
            (user['id'],)
        )
        log_info(f"[退出] 用户退出登录: {user['username']}", 'auth')
        return jsonify({'success': True, 'message': '退出成功'})
    except Exception as e:
        log_error(f"[退出] 异常: {e}", 'auth', exc_info=True)
        return jsonify({'success': False, 'message': '退出失败: ' + str(e)})


@auth_bp.route('/info', methods=['GET'])
@login_required
def get_user_info():
    """获取当前用户信息"""
    try:
        user = g.current_user
        return jsonify({
            'success': True,
            'data': {
                'id': user['id'],
                'username': user['username'],
                'real_name': user.get('real_name', '')
            }
        })
    except Exception as e:
        return jsonify({'success': False, 'message': str(e)})


@auth_bp.route('/change-password', methods=['POST'])
@login_required
def change_password():
    """修改密码"""
    try:
        data = request.get_json()
        old_password = data.get('old_password', '').strip()
        new_password = data.get('new_password', '').strip()
        
        if not old_password or not new_password:
            return jsonify({'success': False, 'message': '旧密码和新密码不能为空'})
        
        if len(new_password) < 6:
            return jsonify({'success': False, 'message': '新密码长度不能少于6位'})
        
        user = g.current_user
        
        # 验证旧密码
        users = execute_query(
            "SELECT password FROM t_daily_report_admin WHERE id = %s",
            (user['id'],)
        )
        
        if not users or not users[0]:
            return jsonify({'success': False, 'message': '用户不存在'})
        
        old_password_md5 = md5_password(old_password)
        if users[0]['password'] != old_password_md5:
            return jsonify({'success': False, 'message': '旧密码错误'})
        
        # 更新密码
        new_password_md5 = md5_password(new_password)
        execute_update(
            "UPDATE t_daily_report_admin SET password = %s, token = NULL, token_expire = NULL, update_time = NOW() WHERE id = %s",
            (new_password_md5, user['id'])
        )
        
        log_info(f"[修改密码] 用户 {user['username']} 修改密码成功", 'auth')
        
        return jsonify({'success': True, 'message': '密码修改成功，请重新登录'})
    except Exception as e:
        log_error(f"[修改密码] 异常: {e}", 'auth', exc_info=True)
        return jsonify({'success': False, 'message': '修改失败: ' + str(e)})
