"""API Keys API endpoints."""

from typing import Annotated, Optional
from uuid import UUID

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

from src.core.database import get_db
from src.schemas.user import UserResponse
from src.schemas.api_key import (
    APIKeyCreate,
    APIKeyUpdate,
    APIKeyResponse,
    APIKeyCreateResponse,
    APIKeyList,
)
from src.api.v1.auth import get_current_user
from src.services.apikey_service import (
    create_api_key,
    list_api_keys,
    revoke_api_key,
    rotate_api_key,
    update_api_key,
    APIKeyNotFoundError,
)

router = APIRouter(prefix="/api-keys", tags=["api-keys"])


@router.post(
    "",
    response_model=APIKeyCreateResponse,
    status_code=status.HTTP_201_CREATED,
)
async def create_new_api_key(
    key_data: APIKeyCreate,
    current_user: Annotated[UserResponse, Depends(get_current_user)],
    session: AsyncSession = Depends(get_db),
):
    """Create a new API key.

    ⚠️ WARNING: The full API key is shown ONLY at creation!
    Make sure to copy and save it immediately.

    Args:
        key_data: API key creation data
        current_user: Current authenticated user
        session: Database session

    Returns:
        APIKeyCreateResponse with full key (shown only once)
    """
    api_key, full_key = await create_api_key(
        session=session,
        user_id=current_user.id,
        name=key_data.name,
        scopes=key_data.scopes,
        expires_days=key_data.expires_days,
    )

    return APIKeyCreateResponse(
        id=api_key.id,
        name=api_key.name,
        key=full_key,  # Full key shown ONLY ONCE!
        key_prefix=api_key.key_prefix,
        scopes=api_key.scopes,
        is_active=api_key.is_active,
        created_at=api_key.created_at,
        expires_at=api_key.expires_at,
        last_used_at=api_key.last_used_at,
    )


@router.get(
    "",
    response_model=APIKeyList,
)
async def list_user_api_keys(
    current_user: Annotated[UserResponse, Depends(get_current_user)],
    session: AsyncSession = Depends(get_db),
):
    """List all API keys for the current user.

    Args:
        current_user: Current authenticated user
        session: Database session

    Returns:
        APIKeyList with user's API keys (without key_hash)
    """
    api_keys = await list_api_keys(session, current_user.id)

    return APIKeyList(
        items=[APIKeyResponse.model_validate(key) for key in api_keys],
        total=len(api_keys),
    )


@router.patch(
    "/{key_id}",
    response_model=APIKeyResponse,
)
async def update_api_key_endpoint(
    key_id: UUID,
    key_data: APIKeyUpdate,
    current_user: Annotated[UserResponse, Depends(get_current_user)],
    session: AsyncSession = Depends(get_db),
):
    """Update an API key (name only).

    Args:
        key_id: API key ID
        key_data: Update data
        current_user: Current authenticated user
        session: Database session

    Returns:
        Updated APIKeyResponse

    Raises:
        HTTPException: If key not found
    """
    try:
        api_key = await update_api_key(
            session=session,
            api_key_id=key_id,
            user_id=current_user.id,
            name=key_data.name,
        )
    except APIKeyNotFoundError:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="API key not found",
        )

    return APIKeyResponse.model_validate(api_key)


@router.delete(
    "/{key_id}",
    status_code=status.HTTP_204_NO_CONTENT,
)
async def revoke_user_api_key(
    key_id: UUID,
    current_user: Annotated[UserResponse, Depends(get_current_user)],
    session: AsyncSession = Depends(get_db),
):
    """Revoke (delete) an API key.

    Args:
        key_id: API key ID
        current_user: Current authenticated user
        session: Database session

    Raises:
        HTTPException: If key not found
    """
    try:
        await revoke_api_key(
            session=session,
            api_key_id=key_id,
            user_id=current_user.id,
        )
    except APIKeyNotFoundError:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="API key not found",
        )

    return None


@router.post(
    "/{key_id}/rotate",
    response_model=APIKeyCreateResponse,
    status_code=status.HTTP_201_CREATED,
)
async def rotate_user_api_key(
    key_id: UUID,
    current_user: Annotated[UserResponse, Depends(get_current_user)],
    session: AsyncSession = Depends(get_db),
):
    """Rotate (regenerate) an API key.

    The old key is revoked and a new key is created with the same settings.

    ⚠️ WARNING: The new full API key is shown ONLY at creation!

    Args:
        key_id: API key ID to rotate
        current_user: Current authenticated user
        session: Database session

    Returns:
        APIKeyCreateResponse with new full key

    Raises:
        HTTPException: If key not found
    """
    try:
        new_key, full_key = await rotate_api_key(
            session=session,
            api_key_id=key_id,
            user_id=current_user.id,
        )
    except APIKeyNotFoundError:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="API key not found",
        )

    return APIKeyCreateResponse(
        id=new_key.id,
        name=new_key.name,
        key=full_key,  # New full key shown ONLY ONCE!
        key_prefix=new_key.key_prefix,
        scopes=new_key.scopes,
        is_active=new_key.is_active,
        created_at=new_key.created_at,
        expires_at=new_key.expires_at,
        last_used_at=new_key.last_used_at,
    )
