"""Authentication routes for user registration, login, and verification."""
from flask import Blueprint, request, jsonify
from app import limiter
from app.services import (
    register_user,
    verify_email,
    login_user,
    resend_verification_code,
    refresh_access_token,
    request_password_reset,
    verify_reset_code,
    reset_password
)
from app.utils import validate_request_body

# Create auth blueprint
auth_bp = Blueprint('auth', __name__, url_prefix='/auth')


@auth_bp.route('/register', methods=['POST'])
@limiter.limit("5 per hour")
def register():
    """
    Register a new user.
    
    Expected JSON:
    {
        "first_name": "John",
        "last_name": "Doe",
        "username": "johndoe",
        "email": "john@example.com",
        "password": "SecurePass123"
    }
    """
    data = request.get_json()
    
    # Validate required fields
    is_valid, error_response = validate_request_body(
        data,
        ['first_name', 'last_name', 'username', 'email', 'password']
    )
    if not is_valid:
        return error_response
    
    # Call service
    result = register_user(
        first_name=data['first_name'],
        last_name=data['last_name'],
        username=data['username'],
        email=data['email'],
        password=data['password']
    )
    
    status_code = 201 if result['success'] else 400
    return jsonify(result), status_code


@auth_bp.route('/verify-email', methods=['POST'])
@limiter.limit("10 per hour")
def verify():
    """
    Verify user email with code.
    
    Expected JSON:
    {
        "email": "john@example.com",
        "code": "123456"
    }
    """
    data = request.get_json()
    
    # Validate required fields
    is_valid, error_response = validate_request_body(data, ['email', 'code'])
    if not is_valid:
        return error_response
    
    # Call service
    result = verify_email(
        email=data['email'],
        code=data['code']
    )
    
    status_code = 200 if result['success'] else 400
    return jsonify(result), status_code


@auth_bp.route('/login', methods=['POST'])
@limiter.limit("10 per hour")
def login():
    """
    Login user with email/username and password.
    
    Expected JSON:
    {
        "email_or_username": "john@example.com",
        "password": "SecurePass123"
    }
    """
    data = request.get_json()
    
    # Validate required fields
    is_valid, error_response = validate_request_body(
        data,
        ['email_or_username', 'password']
    )
    if not is_valid:
        return error_response
    
    # Call service
    result = login_user(
        email_or_username=data['email_or_username'],
        password=data['password']
    )
    
    status_code = 200 if result['success'] else 401
    return jsonify(result), status_code


@auth_bp.route('/resend-code', methods=['POST'])
@limiter.limit("3 per hour")
def resend_code():
    """
    Resend verification code to user email.
    
    Expected JSON:
    {
        "email": "john@example.com"
    }
    """
    data = request.get_json()
    
    # Validate required fields
    is_valid, error_response = validate_request_body(data, ['email'])
    if not is_valid:
        return error_response
    
    # Call service
    result = resend_verification_code(email=data['email'])
    
    status_code = 200 if result['success'] else 400
    return jsonify(result), status_code


@auth_bp.route('/refresh-token', methods=['POST'])
@limiter.limit("20 per hour")
def refresh_token():
    """
    Refresh access token using refresh token.

    Expected JSON:
    {
        "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGc..."
    }
    """
    data = request.get_json()

    # Validate required fields
    is_valid, error_response = validate_request_body(data, ['refresh_token'])
    if not is_valid:
        return error_response

    # Call service
    result = refresh_access_token(refresh_token=data['refresh_token'])

    status_code = 200 if result['success'] else 401
    return jsonify(result), status_code


@auth_bp.route('/forgot-password', methods=['POST'])
@limiter.limit("5 per hour")
def forgot_password():
    """
    Request password reset code.

    Expected JSON:
    {
        "email": "john@example.com"
    }
    """
    data = request.get_json()

    # Validate required fields
    is_valid, error_response = validate_request_body(data, ['email'])
    if not is_valid:
        return error_response

    # Call service
    result = request_password_reset(email=data['email'])

    # Always return 200 to prevent email enumeration
    return jsonify(result), 200


@auth_bp.route('/verify-reset-code', methods=['POST'])
@limiter.limit("10 per hour")
def verify_password_reset_code():
    """
    Verify password reset code and get reset token.

    Expected JSON:
    {
        "email": "john@example.com",
        "code": "123456"
    }
    """
    data = request.get_json()

    # Validate required fields
    is_valid, error_response = validate_request_body(data, ['email', 'code'])
    if not is_valid:
        return error_response

    # Call service
    result = verify_reset_code(
        email=data['email'],
        code=data['code']
    )

    status_code = 200 if result['success'] else 400
    return jsonify(result), status_code


@auth_bp.route('/reset-password', methods=['POST'])
@limiter.limit("5 per hour")
def reset_user_password():
    """
    Reset user password using verified reset token.

    Expected JSON:
    {
        "email": "john@example.com",
        "reset_token": "secure_token_from_verify_step",
        "new_password": "NewSecurePass123"
    }
    """
    data = request.get_json()

    # Validate required fields
    is_valid, error_response = validate_request_body(
        data,
        ['email', 'reset_token', 'new_password']
    )
    if not is_valid:
        return error_response

    # Call service
    result = reset_password(
        email=data['email'],
        reset_token=data['reset_token'],
        new_password=data['new_password']
    )

    status_code = 200 if result['success'] else 400
    return jsonify(result), status_code