"""
P8s Auth Router - Authentication endpoints.
"""

from datetime import datetime

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from p8s.auth.dependencies import require_auth
from p8s.auth.models import (
    LoginRequest,
    TokenResponse,
    User,
    UserCreate,
    UserResponse,
)
from p8s.auth.security import (
    create_access_token,
    create_refresh_token,
    decode_token,
    get_password_hash,
    verify_password,
)
from p8s.core.settings import get_settings
from p8s.db.session import get_session

router = APIRouter(prefix="/auth", tags=["auth"])


@router.post("/register", response_model=UserResponse, status_code=201)
async def register(
    user_in: UserCreate,
    session: AsyncSession = Depends(get_session),
) -> User:
    """
    Register a new user.

    Args:
        user_in: User registration data.
        session: Database session.

    Returns:
        Created user.

    Raises:
        400: Email already registered.
    """
    # Check if email exists
    result = await session.execute(select(User).where(User.email == user_in.email))

    if result.scalar_one_or_none():
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Email already registered",
        )

    # Check if username exists (if provided)
    if user_in.username:
        result = await session.execute(
            select(User).where(User.username == user_in.username)
        )

        if result.scalar_one_or_none():
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Username already taken",
            )

    # Create user
    user = User(
        email=user_in.email,
        password_hash=get_password_hash(user_in.password),
        username=user_in.username,
        first_name=user_in.first_name,
        last_name=user_in.last_name,
    )

    session.add(user)
    await session.flush()
    await session.refresh(user)

    return user


@router.post("/login", response_model=TokenResponse)
async def login(
    login_data: LoginRequest,
    session: AsyncSession = Depends(get_session),
) -> TokenResponse:
    """
    Login with email and password.

    Args:
        login_data: Login credentials.
        session: Database session.

    Returns:
        Access and refresh tokens.

    Raises:
        401: Invalid credentials.
    """
    # Find user
    result = await session.execute(select(User).where(User.email == login_data.email))
    user = result.scalar_one_or_none()

    if not user or not verify_password(login_data.password, user.password_hash):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid email or password",
        )

    if not user.is_active:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Account is disabled",
        )

    # Update last login
    user.last_login = datetime.utcnow()
    session.add(user)

    # Create tokens
    settings = get_settings()

    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,
        expires_in=settings.auth.access_token_expire_minutes * 60,
    )


@router.post("/refresh", response_model=TokenResponse)
async def refresh_token(
    refresh_token: str,
    session: AsyncSession = Depends(get_session),
) -> TokenResponse:
    """
    Refresh access token.

    Args:
        refresh_token: Valid refresh token.
        session: Database session.

    Returns:
        New access and refresh tokens.

    Raises:
        401: Invalid refresh token.
    """
    payload = decode_token(refresh_token)

    if not payload or payload.get("type") != "refresh":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid refresh token",
        )

    user_id = payload.get("sub")

    from uuid import UUID

    result = await session.execute(select(User).where(User.id == UUID(user_id)))
    user = result.scalar_one_or_none()

    if not user or not user.is_active:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="User not found or inactive",
        )

    settings = get_settings()

    new_access_token = create_access_token({"sub": str(user.id)})
    new_refresh_token = create_refresh_token({"sub": str(user.id)})

    return TokenResponse(
        access_token=new_access_token,
        refresh_token=new_refresh_token,
        expires_in=settings.auth.access_token_expire_minutes * 60,
    )


@router.get("/me", response_model=UserResponse)
async def get_me(
    user: User = Depends(require_auth),
) -> User:
    """
    Get current user profile.

    Args:
        user: Authenticated user.

    Returns:
        User profile.
    """
    return user


@router.post("/logout")
async def logout(
    user: User = Depends(require_auth),
) -> dict:
    """
    Logout current user.

    Note: This is a client-side operation. The token should be
    deleted from client storage.

    Returns:
        Success message.
    """
    # In a real implementation, you might want to:
    # - Blacklist the token
    # - Clear server-side sessions
    # - Log the logout event

    return {"message": "Successfully logged out"}
