# bedrock_server_manager/web/routers/auth.py
"""
FastAPI router for user authentication and session management.

This module defines endpoints related to user login and logout for the
Bedrock Server Manager web interface. It handles:

- Processing API login requests (typically form submissions) to authenticate users
  against environment variable credentials and issue JWT access tokens
  (:func:`~.api_login_for_access_token`). Tokens are set as HTTP-only cookies.
- Handling user logout by clearing the authentication cookie
  (:func:`~.logout`).

It uses utilities from :mod:`~bedrock_server_manager.web.auth_utils` for
password verification, token creation, and user retrieval from tokens.
Authentication is required for most parts of the application, and these routes
facilitate that access control.
"""

import logging

from fastapi import APIRouter, Depends, HTTPException
from fastapi import Response as FastAPIResponse
from fastapi import status
from fastapi.responses import RedirectResponse

from ...context import AppContext
from ..auth_utils import (
    authenticate_user,
    create_access_token,
    get_current_user,
)
from ..dependencies import get_app_context
from ..schemas import TokenResponse, UserLoginPayload, UserResponse

logger = logging.getLogger(__name__)

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


# --- API Login Route ---
@router.post("/token", response_model=TokenResponse)
async def api_login_for_access_token(
    payload: UserLoginPayload,
    response: FastAPIResponse,
    app_context: AppContext = Depends(get_app_context),
):
    """
    Handles API user login, creates a JWT, and sets it as an HTTP-only cookie.
    """
    if not payload.username or not payload.password:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail="Username and password cannot be empty.",
        )

    logger.info(f"API login attempt for '{payload.username}'")
    authenticated_username = authenticate_user(
        app_context, payload.username, payload.password
    )

    if not authenticated_username:
        logger.warning(f"Invalid API login attempt for '{payload.username}'.")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    import datetime

    settings = app_context.settings
    if payload.remember_me:
        try:
            jwt_expires_weeks = float(settings.get("web.token_expires_weeks", 4.0))
        except (ValueError, TypeError):
            jwt_expires_weeks = 4.0
        access_token_expire_minutes = jwt_expires_weeks * 7 * 24 * 60
        expires_delta = datetime.timedelta(minutes=access_token_expire_minutes)
        max_age = int(expires_delta.total_seconds())
    else:
        # For session cookies, we still need the JWT to eventually expire (e.g., 24 hours)
        expires_delta = datetime.timedelta(hours=24)
        max_age = None  # None max_age creates a session cookie

    access_token = create_access_token(
        data={"sub": authenticated_username},
        app_context=app_context,
        expires_delta=expires_delta,
    )
    cookie_secure = settings.get("web.jwt_cookie_secure", False)
    cookie_samesite = settings.get("web.jwt_cookie_samesite", "Lax")

    response.set_cookie(
        key="access_token_cookie",
        value=access_token,
        httponly=True,
        secure=cookie_secure,
        samesite=cookie_samesite,
        path="/",
        max_age=max_age,
    )
    logger.info(
        f"API login successful for '{payload.username}'. JWT created and cookie set."
    )
    return TokenResponse(
        access_token=access_token,
        token_type="bearer",
        message="Successfully authenticated. Note: The token in the response body is deprecated. Please use the HTTP-only cookie provided.",
    )


@router.get("/refresh-token", response_model=TokenResponse)
async def refresh_token(
    current_user: UserResponse = Depends(get_current_user),
    app_context: AppContext = Depends(get_app_context),
):
    """
    Refreshes the JWT access token for an authenticated user.

    This endpoint allows a client authenticated via a session cookie to request
    a new JWT access token. This is useful if the client has lost its stored
    token (e.g., cleared localStorage) but still has a valid session.
    """
    access_token = create_access_token(
        data={"sub": current_user.username}, app_context=app_context
    )
    return TokenResponse(
        access_token=access_token,
        token_type="bearer",
        message="Token refreshed successfully.",
    )


# --- Logout Route ---
@router.get("/logout")
async def logout(
    response: FastAPIResponse,
    current_user: UserResponse = Depends(get_current_user),
):
    """
    Logs the current user out by clearing the JWT authentication cookie.
    """
    username = current_user.username
    logger.info(f"UserResponse '{username}' logging out. Clearing JWT cookie.")

    # Create the redirect response first, then operate on it for cookie deletion
    redirect_url_with_message = (
        f"/app/login?message=You%20have%20been%20successfully%20logged%20out."
    )
    final_response = RedirectResponse(
        url=redirect_url_with_message, status_code=status.HTTP_302_FOUND
    )
    # Clear the cookie on the response that will actually be sent to the client
    final_response.delete_cookie(key="access_token_cookie", path="/")

    return final_response
