# #region AdminApiKeyRoutes [C:3] [TYPE Module] [SEMANTICS fastapi, admin, api_key, crud]
# @BRIEF Admin API endpoints for API key management — list, generate (one-time reveal), and revoke.
# @LAYER API
# @RELATION DEPENDS_ON -> [APIKeyModel]
# @RELATION DEPENDS_ON -> [APIKeyUtilities]
# @RELATION DEPENDS_ON -> [EXT:code:has_permission_admin_settings_WRITE]
# @INVARIANT GET /api/admin/api-keys NEVER returns key_hash or raw_key.
# @INVARIANT POST /api/admin/api-keys returns raw_key ONCE — never stored, never retrievable again.
# @INVARIANT DELETE /api/admin/api-keys/{id} soft-deletes (active=False), preserves row for audit.

from datetime import datetime

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, ConfigDict, Field
from sqlalchemy.orm import Session

from ...core.auth.api_key import generate_api_key
from ...core.database import get_db
from ...dependencies import has_permission
from ...models.api_key import APIKey

# #region router [TYPE Variable]
# @BRIEF APIRouter for admin API key management routes.
router = APIRouter(prefix="/api/admin/api-keys", tags=["admin", "api-keys"])
# #endregion router


# ── Pydantic schemas ──────────────────────────────────────────

# #region ApiKeyCreateRequest [C:1] [TYPE Class]
class ApiKeyCreateRequest(BaseModel):
    name: str = Field(..., min_length=1, max_length=255)
    environment_id: str | None = None
    permissions: list[str] = Field(..., min_length=1)
    expires_at: datetime | None = None
# #endregion ApiKeyCreateRequest


# #region ApiKeyCreateResponse [C:1] [TYPE Class]
class ApiKeyCreateResponse(BaseModel):
    id: str
    raw_key: str
    prefix: str
    name: str
    environment_id: str | None
    permissions: list[str]
    active: bool
    created_at: datetime
    expires_at: datetime | None
# #endregion ApiKeyCreateResponse


# #region ApiKeyListItem [C:1] [TYPE Class]
class ApiKeyListItem(BaseModel):
    id: str
    name: str
    prefix: str
    environment_id: str | None
    permissions: list[str]
    active: bool
    created_at: datetime
    expires_at: datetime | None
    last_used_at: datetime | None

    model_config = ConfigDict(from_attributes=True)
# #endregion ApiKeyListItem


# #region ApiKeyRevokeResponse [C:1] [TYPE Class]
class ApiKeyRevokeResponse(BaseModel):
    id: str
    status: str
# #endregion ApiKeyRevokeResponse


# ── Routes ────────────────────────────────────────────────────

# #region list_api_keys [C:2] [TYPE Function]
# @BRIEF List all API keys — NEVER returns key_hash or raw_key.
# @PRE Requires admin:settings WRITE permission.
# @POST Returns list of ApiKeyListItem without sensitive fields.
@router.get("/", response_model=list[ApiKeyListItem])
async def list_api_keys(
    db: Session = Depends(get_db),
    _=Depends(has_permission("admin:settings", "WRITE")),
):
    keys = db.query(APIKey).order_by(APIKey.created_at.desc()).all()
    return [
        ApiKeyListItem(
            id=k.id,
            name=k.name,
            prefix=k.prefix,
            environment_id=k.environment_id,
            permissions=list(k.permissions or []),
            active=k.active,
            created_at=k.created_at,
            expires_at=k.expires_at,
            last_used_at=k.last_used_at,
        )
        for k in keys
    ]
# #endregion list_api_keys


# #region create_api_key [C:3] [TYPE Function]
# @BRIEF Generate a new API key — returns raw key ONCE, never stored or retrievable again.
# @PRE Requires admin:settings WRITE permission. name is required, at least one permission.
# @POST Creates APIKey row with SHA-256 hash. Returns raw key in response.
# @SIDE_EFFECT Generates cryptographically random key, stores hash in DB.
# @RELATION DEPENDS_ON -> [generate_api_key]
@router.post("/", response_model=ApiKeyCreateResponse, status_code=status.HTTP_201_CREATED)
async def create_api_key(
    request: ApiKeyCreateRequest,
    db: Session = Depends(get_db),
    _=Depends(has_permission("admin:settings", "WRITE")),
):
    # Validate
    if not request.name.strip():
        raise HTTPException(status_code=400, detail="Name is required")
    if not request.permissions:
        raise HTTPException(status_code=400, detail="At least one permission is required")

    # Generate key
    raw_key, prefix, key_hash = generate_api_key()

    # Store hash only
    api_key = APIKey(
        key_hash=key_hash,
        prefix=prefix,
        name=request.name.strip(),
        environment_id=request.environment_id,
        permissions=request.permissions,
        active=True,
        expires_at=request.expires_at,
    )
    db.add(api_key)
    db.commit()
    db.refresh(api_key)

    return ApiKeyCreateResponse(
        id=api_key.id,
        raw_key=raw_key,
        prefix=api_key.prefix,
        name=api_key.name,
        environment_id=api_key.environment_id,
        permissions=list(api_key.permissions or []),
        active=api_key.active,
        created_at=api_key.created_at,
        expires_at=api_key.expires_at,
    )
# #endregion create_api_key


# #region revoke_api_key [C:2] [TYPE Function]
# @BRIEF Revoke an API key by setting active=False. Preserves row for audit.
# @PRE Requires admin:settings WRITE permission.
# @POST Sets active=False on the key. Returns 404 if already revoked or not found.
@router.delete("/{key_id}", response_model=ApiKeyRevokeResponse)
async def revoke_api_key(
    key_id: str,
    db: Session = Depends(get_db),
    _=Depends(has_permission("admin:settings", "WRITE")),
):
    api_key = db.query(APIKey).filter(APIKey.id == key_id).first()
    if not api_key:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="API key not found",
        )
    if not api_key.active:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="API key is already revoked",
        )

    api_key.active = False
    db.commit()

    return ApiKeyRevokeResponse(
        id=api_key.id,
        status="revoked",
    )
# #endregion revoke_api_key

# #endregion AdminApiKeyRoutes
