"""
API Key management routes for Pro users
Story 3.1: Modèle API Key & Génération
"""

import hashlib
import logging
import secrets
from datetime import datetime, timezone
from typing import Optional

logger = logging.getLogger(__name__)

from fastapi import APIRouter, Depends, Request
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field

from routes.deps import ProUser, require_pro_user
from database.connection import get_sync_session
from database.models import ApiKey

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

MAX_API_KEYS_PER_USER = 10


class ApiKeyCreateRequest(BaseModel):
    name: Optional[str] = Field(default="Default API Key", max_length=100)


class ApiKeyResponse(BaseModel):
    id: str
    key: str
    name: str
    key_prefix: str
    created_at: str


def _generate_api_key() -> tuple[str, str, str]:
    """
    Generate a secure API key with sk_live_ prefix.

    Returns:
        tuple: (raw_key, key_hash, key_prefix)
    """
    raw_random = secrets.token_urlsafe(32)
    raw_key = f"sk_live_{raw_random}"
    key_hash = hashlib.sha256(raw_key.encode()).hexdigest()
    key_prefix = raw_key[:8]

    return raw_key, key_hash, key_prefix


@router.post("")
async def create_api_key(
    request: Request,
    body: Optional[ApiKeyCreateRequest] = None,
    user: ProUser = Depends(require_pro_user),
):
    """
    Create a new API key for the authenticated Pro user.

    Returns:
        201: API key created successfully (key shown ONCE)
        401: Authentication required
        403: Pro subscription required
        429: Maximum API keys reached
    """
    key_name = body.name if body and body.name else "Default API Key"

    raw_key, key_hash, key_prefix = _generate_api_key()

    with get_sync_session() as session:
        existing_count = (
            session.query(ApiKey)
            .filter(
                ApiKey.user_id == user.id,
                ApiKey.is_active == True,
            )
            .count()
        )

        if existing_count >= MAX_API_KEYS_PER_USER:
            return JSONResponse(
                status_code=429,
                content={
                    "error": "API_KEY_LIMIT_REACHED",
                    "message": f"Maximum de {MAX_API_KEYS_PER_USER} clés API atteint. Supprimez une clé existante.",
                },
            )

        api_key = ApiKey(
            user_id=user.id,
            name=key_name,
            key_hash=key_hash,
            key_prefix=key_prefix,
            is_active=True,
            scopes=["translate"],
            created_at=datetime.now(timezone.utc),
        )
        session.add(api_key)
        session.commit()
        session.refresh(api_key)

        return JSONResponse(
            status_code=201,
            content={
                "data": {
                    "id": api_key.id,
                    "key": raw_key,
                    "name": api_key.name,
                    "key_prefix": api_key.key_prefix,
                    "created_at": api_key.created_at.isoformat()
                    if api_key.created_at
                    else None,
                },
                "meta": {},
            },
        )


@router.get("")
async def list_api_keys(
    request: Request,
    user: ProUser = Depends(require_pro_user),
):
    """
    List all API keys for the authenticated Pro user.

    Note: Keys are returned without the secret (only prefix visible).

    Returns:
        200: List of API keys
        401: Authentication required
        403: Pro subscription required
    """
    with get_sync_session() as session:
        keys = (
            session.query(ApiKey)
            .filter(ApiKey.user_id == user.id)
            .order_by(ApiKey.created_at.desc())
            .all()
        )

        return JSONResponse(
            status_code=200,
            content={
                "data": [
                    {
                        "id": key.id,
                        "name": key.name,
                        "key_prefix": key.key_prefix,
                        "is_active": key.is_active,
                        "last_used_at": key.last_used_at.isoformat()
                        if key.last_used_at
                        else None,
                        "usage_count": key.usage_count,
                        "created_at": key.created_at.isoformat()
                        if key.created_at
                        else None,
                    }
                    for key in keys
                ],
                "meta": {"total": len(keys)},
            },
        )


@router.delete("/{key_id}")
async def revoke_api_key(
    key_id: str,
    user: ProUser = Depends(require_pro_user),
):
    """
    Revoke an API key for the authenticated Pro user.

    This performs a soft delete by setting is_active=False.
    Only the owner of the key can revoke it.
    Only active keys can be revoked.

    Returns:
        200: API key revoked successfully
        401: Authentication required
        403: Pro subscription required
        404: API key not found or already revoked
    """
    # Validate key_id format (UUID)
    try:
        import uuid as uuid_module
        uuid_module.UUID(key_id)
    except ValueError:
        return JSONResponse(
            status_code=400,
            content={
                "error": "INVALID_KEY_ID",
                "message": "Format d'identifiant de clé API invalide.",
            },
        )

    with get_sync_session() as session:
        # Security: Filter by user_id AND is_active so only the owner can revoke active keys
        api_key = (
            session.query(ApiKey)
            .filter(
                ApiKey.id == key_id,
                ApiKey.user_id == user.id,
                ApiKey.is_active == True,  # Only active keys can be revoked
            )
            .first()
        )

        if not api_key:
            return JSONResponse(
                status_code=404,
                content={
                    "error": "API_KEY_NOT_FOUND",
                    "message": "Clé API non trouvée, n'appartient pas à l'utilisateur ou déjà révoquée.",
                },
            )

        # Soft delete - mark as inactive and record revocation timestamp
        revoked_at = datetime.now(timezone.utc)
        api_key.is_active = False
        api_key.revoked_at = revoked_at
        session.commit()

        logger.info(f"API key {key_id} revoked by user {user.id}")

        return JSONResponse(
            status_code=200,
            content={
                "data": {
                    "id": api_key.id,
                    "revoked": True,
                    "revoked_at": revoked_at.isoformat(),
                },
                "meta": {},
            },
        )
