from __future__ import annotations

from typing import Dict, Optional

from backend.app.core.security import (
    create_access_token,
    get_password_hash,
    verify_password,
)
from backend.app.models import AuthResponse, UserInDB, UserPublic

_DEMO_USER = UserInDB(
    username="demo",
    full_name="Demo Engineer",
    hashed_password=get_password_hash("railgame123"),
)

_FAKE_USERS: Dict[str, UserInDB] = {_DEMO_USER.username: _DEMO_USER}


def get_user(username: str) -> Optional[UserInDB]:
    return _FAKE_USERS.get(username)


def authenticate_user(username: str, password: str) -> Optional[UserInDB]:
    user = get_user(username)
    if not user:
        return None
    if not verify_password(password, user.hashed_password):
        return None
    return user


def issue_token_for_user(user: UserInDB) -> AuthResponse:
    return AuthResponse(
        access_token=create_access_token(subject=user.username),
        token_type="bearer",
        user=to_public_user(user),
    )


def to_public_user(user: UserInDB) -> UserPublic:
    return UserPublic(username=user.username, full_name=user.full_name)


def register_user(
    username: str, password: str, full_name: Optional[str] = None
) -> UserInDB:
    normalized_username = username.strip()
    if not normalized_username:
        raise ValueError("Username must not be empty")
    if normalized_username in _FAKE_USERS:
        raise ValueError("Username already exists")

    user = UserInDB(
        username=normalized_username,
        full_name=full_name.strip() if full_name else None,
        hashed_password=get_password_hash(password),
    )
    _FAKE_USERS[normalized_username] = user
    return user
