from sqlalchemy.ext.asyncio import AsyncSession
from app.models import User
from app.schemas.user import UserCreate, UserLogin, TokenResponse
from app.crud.user import create_user, get_user_by_email, get_user_by_username
from app.utils.security import verify_password, create_access_token, create_refresh_token
from app.utils.exceptions import InvalidCredentialsError, UserAlreadyExistsError


async def register_user(db: AsyncSession, user_data: UserCreate) -> TokenResponse:
    # Check if user already exists
    existing_user = await get_user_by_email(db, user_data.email)
    if existing_user:
        raise UserAlreadyExistsError("Email already registered")

    existing_username = await get_user_by_username(db, user_data.username)
    if existing_username:
        raise UserAlreadyExistsError("Username already taken")

    # Create user
    user = await create_user(db, user_data)
    await db.commit()

    # Generate tokens
    access_token = create_access_token({"sub": str(user.id)})
    refresh_token = create_refresh_token({"sub": str(user.id)})

    return TokenResponse(
        access_token=access_token,
        refresh_token=refresh_token,
    )


async def login_user(db: AsyncSession, login_data: UserLogin) -> TokenResponse:
    # Get user by email
    user = await get_user_by_email(db, login_data.email)
    if not user:
        raise InvalidCredentialsError()

    # Verify password
    if not verify_password(login_data.password, user.password_hash):
        raise InvalidCredentialsError()

    # Generate tokens
    access_token = create_access_token({"sub": str(user.id)})
    refresh_token = create_refresh_token({"sub": str(user.id)})

    return TokenResponse(
        access_token=access_token,
        refresh_token=refresh_token,
    )
