"""
API Keys management endpoints
"""

from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional
from uuid import UUID

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

from ...auth import get_current_account
from ...db import get_session
from ...models import APIKey
from ...utils.encryption import encrypt_api_key, decrypt_api_key
from ...utils.api_keys import generate_api_key
import logging

logger = logging.getLogger(__name__)

router = APIRouter(
    prefix="/api/keys", tags=["api_keys"], dependencies=[Depends(get_current_account)]
)


class CreateApiKeyRequest(BaseModel):
    name: str
    description: Optional[str] = None
    expires_in_days: Optional[int] = None
    allowed_ips: Optional[List[str]] = None
    rate_limit_per_minute: Optional[int] = 100


@router.post("")
async def create_api_key(
    request: CreateApiKeyRequest,
    db: AsyncSession = Depends(get_session),
    account_id: UUID = Depends(get_current_account),
) -> Dict[str, Any]:
    """
    Create a new API key for the authenticated account.
    Returns the full key only once - it cannot be retrieved again.
    """
    # Generate the key
    full_key, key_prefix, key_hash = generate_api_key()

    # Calculate expiration
    expires_at = None
    if request.expires_in_days:
        expires_at = datetime.utcnow() + timedelta(days=request.expires_in_days)

    # Create API key record with encrypted key for retrieval
    api_key = APIKey(
        key_prefix=key_prefix,
        key_hash=key_hash,
        key_encrypted=encrypt_api_key(full_key),  # Store encrypted version
        account_id=str(account_id),  # Convert UUID to string
        name=request.name,
        description=request.description,
        expires_at=expires_at,
        allowed_ips=request.allowed_ips,
        rate_limit=request.rate_limit_per_minute,
    )

    db.add(api_key)
    await db.commit()
    await db.refresh(api_key)

    response = {
        "id": str(api_key.id),
        "key": full_key,  # Only returned once!
        "prefix": key_prefix,
        "name": request.name,
        "message": "Store this key securely - it can be retrieved later",
    }

    # Only add expires_at if it's not None
    if expires_at:
        response["expires_at"] = expires_at.isoformat()

    return response


@router.get("")
async def list_api_keys(
    db: AsyncSession = Depends(get_session),
    account_id: UUID = Depends(get_current_account),
) -> Dict[str, Any]:
    """List all API keys for the authenticated account."""
    query = (
        select(APIKey)
        .where(APIKey.account_id == str(account_id), APIKey.is_active == True)
        .order_by(APIKey.created_at.desc())
    )

    result = await db.execute(query)
    keys = result.scalars().all()

    return {
        "keys": [
            {
                "id": str(key.id),
                "name": key.name,
                "description": key.description,
                "key_prefix": key.key_prefix,
                "created_at": key.created_at.isoformat(),
                "last_used_at": key.last_used_at.isoformat()
                if key.last_used_at
                else None,
                "expires_at": key.expires_at.isoformat() if key.expires_at else None,
                "active": key.is_active,  # Frontend expects "active" not "is_active"
                "can_retrieve": key.key_encrypted
                is not None,  # Indicates if full key can be retrieved
                "rate_limit_per_minute": key.rate_limit or 100,
                "total_requests": 0,  # TODO: Track this properly
            }
            for key in keys
        ]
    }


@router.get("/{key_id}/retrieve")
async def retrieve_api_key(
    key_id: str,
    db: AsyncSession = Depends(get_session),
    account_id: UUID = Depends(get_current_account),
) -> Dict[str, Any]:
    """Retrieve the full API key (only works if key was stored encrypted)."""
    import os

    logger.info(f"Attempting to retrieve API key {key_id} for account {account_id}")

    # Check encryption key is available
    encryption_key = os.getenv("ENCRYPTION_KEY")
    if not encryption_key:
        logger.error("ENCRYPTION_KEY environment variable is not set")
        raise HTTPException(
            status_code=500,
            detail="Server configuration error: encryption key not configured",
        )

    query = select(APIKey).where(
        APIKey.id == key_id, APIKey.account_id == str(account_id)
    )

    result = await db.execute(query)
    api_key = result.scalar_one_or_none()

    if not api_key:
        logger.warning(f"API key {key_id} not found for account {account_id}")
        raise HTTPException(status_code=404, detail="API key not found")

    if not api_key.key_encrypted:
        logger.warning(f"API key {key_id} has no encrypted value stored")
        raise HTTPException(
            status_code=400,
            detail="This API key was created before key retrieval was enabled. The full key cannot be retrieved.",
        )

    try:
        logger.debug(
            f"Decrypting API key {key_id}, encrypted value exists: {bool(api_key.key_encrypted)}"
        )
        logger.debug(
            f"Encrypted value length: {len(api_key.key_encrypted) if api_key.key_encrypted else 0}"
        )

        full_key = decrypt_api_key(api_key.key_encrypted)

        logger.info(f"Successfully decrypted API key {key_id}")
        return {
            "id": str(api_key.id),
            "name": api_key.name,
            "key": full_key,
            "key_prefix": api_key.key_prefix,
        }
    except ValueError as ve:
        logger.error(f"Decryption error for API key {key_id}: {ve}")
        raise HTTPException(
            status_code=500,
            detail="Failed to decrypt API key. The key may have been encrypted with a different encryption key.",
        )
    except Exception as e:
        logger.error(
            f"Unexpected error decrypting API key {key_id}: {e}", exc_info=True
        )
        raise HTTPException(
            status_code=500, detail=f"Failed to decrypt API key: {str(e)}"
        )


@router.post("/{key_id}/revoke")
async def revoke_api_key(
    key_id: str,
    db: AsyncSession = Depends(get_session),
    account_id: UUID = Depends(get_current_account),
) -> Dict[str, Any]:
    """Revoke an API key."""
    query = select(APIKey).where(
        APIKey.id == key_id, APIKey.account_id == str(account_id)
    )

    result = await db.execute(query)
    api_key = result.scalar_one_or_none()

    if not api_key:
        raise HTTPException(status_code=404, detail="API key not found")

    api_key.is_active = False
    await db.commit()

    return {"message": "API key revoked successfully"}


@router.delete("/{key_id}")
async def delete_api_key(
    key_id: str,
    db: AsyncSession = Depends(get_session),
    account_id: UUID = Depends(get_current_account),
) -> Dict[str, Any]:
    """Delete an API key (same as revoke)."""
    return await revoke_api_key(key_id, db, account_id)
