"""Authentication decorators for protecting routes."""
from functools import wraps
from flask import request, jsonify, g
import uuid
from app.models import User
from app.services.token_service import verify_access_token


def jwt_required(f):
    """
    Decorator to require valid JWT access token.
    
    - Extracts token from Authorization header
    - Verifies token validity
    - Loads user and checks status (active, email verified)
    - Sets g.current_user for use in route
    
    Usage:
        @app.route('/profile')
        @jwt_required
        def get_profile():
            user = g.current_user
            return user.to_dict_private()
    """
    @wraps(f)
    def decorated_function(*args, **kwargs):
        # Extract token from Authorization header
        auth_header = request.headers.get('Authorization')
        
        if not auth_header:
            return jsonify({
                'success': False,
                'message': 'Authorization header required',
                'data': None
            }), 401
        
        # Check format: "Bearer <token>"
        parts = auth_header.split()
        if len(parts) != 2 or parts[0].lower() != 'bearer':
            return jsonify({
                'success': False,
                'message': 'Invalid authorization header format. Use: Bearer <token>',
                'data': None
            }), 401
        
        token = parts[1]
        
        # Verify token
        payload = verify_access_token(token)
        if not payload:
            return jsonify({
                'success': False,
                'message': 'Invalid or expired token',
                'data': None
            }), 401
        
        # Get user from token payload
        try:
            user_id = uuid.UUID(payload['user_id'])
        except (ValueError, KeyError):
            return jsonify({
                'success': False,
                'message': 'Invalid token payload',
                'data': None
            }), 401
        
        # Convert UUID to string for SQLite compatibility
        user = User.query.get(str(user_id))
        
        if not user:
            return jsonify({
                'success': False,
                'message': 'User not found',
                'data': None
            }), 401
        
        if not user.is_active:
            return jsonify({
                'success': False,
                'message': 'Account is deactivated',
                'data': None
            }), 401
        
        if not user.is_email_verified:
            return jsonify({
                'success': False,
                'message': 'Email verification required',
                'data': None
            }), 401
        
        # Store user in Flask's g object for access in route
        g.current_user = user
        
        return f(*args, **kwargs)
    
    return decorated_function


def role_required(roles):
    """
    Decorator to require specific role(s).
    
    - First applies jwt_required (must be authenticated)
    - Then checks if user has one of the required roles
    - Supports single role or list of roles (OR logic)
    
    Args:
        roles: String or list of strings representing required roles
               Examples: 'admin' or ['admin', 'owner']
    
    Usage:
        @app.route('/admin/dashboard')
        @role_required('admin')
        def admin_dashboard():
            user = g.current_user
            return {'message': 'Admin only'}
        
        @app.route('/properties/create')
        @role_required(['owner', 'admin'])
        def create_property():
            user = g.current_user
            return {'message': 'Owners or admins'}
    """
    # Convert single role to list for uniform handling
    if isinstance(roles, str):
        roles = [roles]
    
    def decorator(f):
        @wraps(f)
        @jwt_required  # First require valid JWT
        def decorated_function(*args, **kwargs):
            user = g.current_user
            
            # Check if user has any of the required roles
            user_role = user.role.value if hasattr(user.role, 'value') else user.role
            
            if user_role not in roles:
                return jsonify({
                    'success': False,
                    'message': f'Insufficient permissions. Required role(s): {", ".join(roles)}',
                    'data': None
                }), 403
            
            return f(*args, **kwargs)
        
        return decorated_function
    
    return decorator