from flask import Blueprint, request, jsonify, current_app
from werkzeug.security import generate_password_hash, check_password_hash
from src.models.database import db
from src.models.user import User, Role, Permission, UserRole, SystemLog, NotificationSettings
from datetime import datetime
import jwt

auth_bp = Blueprint('auth', __name__)

@auth_bp.route('/login', methods=['POST'])
def login():
    """Login a user and return a JWT token"""
    data = request.json
    
    if not data or not data.get('username') or not data.get('password'):
        return jsonify({'error': 'Username and password are required'}), 400
    
    user = User.query.filter_by(username=data.get('username')).first()
    
    if not user or not user.check_password(data.get('password')):
        return jsonify({'error': 'Invalid username or password'}), 401
    
    if not user.is_active:
        return jsonify({'error': 'User account is inactive'}), 403
    
    # Update last login time
    user.last_login = datetime.utcnow()
    
    # Log the login action
    log = SystemLog(
        user_id=user.id,
        action='login',
        description='User logged in',
        ip_address=request.remote_addr,
        user_agent=request.headers.get('User-Agent', '')
    )
    
    db.session.add(log)
    db.session.commit()
    
    # Generate JWT token
    token = jwt.encode(
        {
            'user_id': user.id,
            'username': user.username,
            'exp': datetime.utcnow() + current_app.config.get('JWT_EXPIRATION_DELTA', datetime.timedelta(hours=24))
        },
        current_app.config['SECRET_KEY'],
        algorithm='HS256'
    )
    
    return jsonify({
        'token': token,
        'user': user.to_dict(include_roles=True)
    }), 200

@auth_bp.route('/register', methods=['POST'])
def register():
    """Register a new user (admin only)"""
    data = request.json
    
    if not data or not data.get('username') or not data.get('password') or not data.get('email'):
        return jsonify({'error': 'Username, password and email are required'}), 400
    
    # Check if username already exists
    if User.query.filter_by(username=data.get('username')).first():
        return jsonify({'error': 'Username already exists'}), 409
    
    # Check if email already exists
    if User.query.filter_by(email=data.get('email')).first():
        return jsonify({'error': 'Email already exists'}), 409
    
    # Create new user
    user = User(
        username=data.get('username'),
        email=data.get('email'),
        first_name=data.get('first_name'),
        last_name=data.get('last_name'),
        phone=data.get('phone'),
        is_active=data.get('is_active', True)
    )
    
    user.set_password(data.get('password'))
    
    db.session.add(user)
    db.session.flush()  # Get user ID without committing
    
    # Add user roles if provided
    if data.get('roles'):
        for role_id in data.get('roles'):
            user_role = UserRole(user_id=user.id, role_id=role_id)
            db.session.add(user_role)
    
    # Create notification settings
    notification_settings = NotificationSettings(
        user_id=user.id,
        email_notifications=data.get('email_notifications', True),
        sms_notifications=data.get('sms_notifications', False),
        web_notifications=data.get('web_notifications', True),
        blacklist_alerts=data.get('blacklist_alerts', True),
        system_alerts=data.get('system_alerts', False)
    )
    
    db.session.add(notification_settings)
    db.session.commit()
    
    return jsonify(user.to_dict()), 201

@auth_bp.route('/change-password', methods=['POST'])
def change_password():
    """Change user password"""
    data = request.json
    
    if not data or not data.get('user_id') or not data.get('current_password') or not data.get('new_password'):
        return jsonify({'error': 'User ID, current password and new password are required'}), 400
    
    user = User.query.get_or_404(data.get('user_id'))
    
    if not user.check_password(data.get('current_password')):
        return jsonify({'error': 'Current password is incorrect'}), 401
    
    user.set_password(data.get('new_password'))
    
    # Log the password change
    log = SystemLog(
        user_id=user.id,
        action='change_password',
        description='User changed password',
        ip_address=request.remote_addr,
        user_agent=request.headers.get('User-Agent', '')
    )
    
    db.session.add(log)
    db.session.commit()
    
    return jsonify({'message': 'Password changed successfully'}), 200

@auth_bp.route('/reset-password', methods=['POST'])
def reset_password():
    """Reset user password (admin only)"""
    data = request.json
    
    if not data or not data.get('user_id') or not data.get('new_password'):
        return jsonify({'error': 'User ID and new password are required'}), 400
    
    user = User.query.get_or_404(data.get('user_id'))
    
    user.set_password(data.get('new_password'))
    
    # Log the password reset
    log = SystemLog(
        user_id=user.id,
        action='reset_password',
        description=f'Password reset by admin (ID: {data.get("admin_id")})',
        ip_address=request.remote_addr,
        user_agent=request.headers.get('User-Agent', '')
    )
    
    db.session.add(log)
    db.session.commit()
    
    return jsonify({'message': 'Password reset successfully'}), 200
