"""Authentication service."""
from models.user import User, db
from sqlalchemy import func
from typing import Optional


def _normalize_username(username: str) -> str:
    return (username or '').strip()

def authenticate_user(username: str, password: str) -> Optional[User]:
    """Authenticate a user by username and password."""
    normalized_username = _normalize_username(username)
    if not normalized_username or not password:
        return None

    user = User.query.filter(func.lower(User.username) == normalized_username.lower()).first()
    if user and user.check_password(password):
        return user
    return None

def get_user_by_id(user_id: int) -> Optional[User]:
    """Get user by ID."""
    return User.query.get(user_id)

def get_user_by_username(username: str) -> Optional[User]:
    """Get user by username."""
    normalized_username = _normalize_username(username)
    if not normalized_username:
        return None
    return User.query.filter(func.lower(User.username) == normalized_username.lower()).first()


def register_user(username: str, password: str, email: Optional[str] = None) -> User:
    """Register a new user with basic defaults for public SUT usage."""
    normalized_username = _normalize_username(username)
    normalized_password = (password or '').strip()

    if not normalized_username or not normalized_password:
        raise ValueError('Username and password are required')

    if len(normalized_username) < 3:
        raise ValueError('Username must be at least 3 characters long')

    if len(normalized_password) < 8 or not any(char.isdigit() for char in normalized_password):
        raise ValueError('Password must be at least 8 characters and contain at least one number')

    if get_user_by_username(normalized_username):
        raise ValueError('Username already exists')

    normalized_email = (email or '').strip().lower() or f'{normalized_username.lower()}@testingfantasy.local'
    existing_email = User.query.filter_by(email=normalized_email).first()
    if existing_email:
        raise ValueError('Email is already in use')

    user = User(
        username=normalized_username,
        email=normalized_email,
        role=normalized_username,  # Use username as role/character name
        gold=500,
    )
    user.set_password(normalized_password)

    db.session.add(user)
    db.session.commit()
    return user
