"""Admin endpoints to manage API keys issued for the public v1 surface.

POST   /api/admin/api-keys           — generate a new key (returns full
                                        token ONCE in the response body)
GET    /api/admin/api-keys           — list all keys (no secret)
DELETE /api/admin/api-keys/{id}      — revoke (soft-delete; active=false)
"""
from typing import Annotated
from uuid import UUID

from fastapi import APIRouter, Depends, HTTPException, Path, status
from pydantic import BaseModel, Field
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession

from app.auth.api_key_auth import generate_key
from app.auth.deps import CurrentUser, require_admin
from app.db import get_session

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


class CreateApiKeyReq(BaseModel):
    label: str = Field(min_length=1, max_length=200)


class CreateApiKeyResp(BaseModel):
    id: str
    label: str
    key: str
    prefix: str
    created_at: str


class ApiKeyOut(BaseModel):
    id: str
    label: str
    prefix: str
    active: bool
    created_at: str
    last_used_at: str | None
    use_count: int


@router.post("/api-keys", response_model=CreateApiKeyResp, status_code=status.HTTP_201_CREATED)
async def create_api_key(
    payload: CreateApiKeyReq,
    session: Annotated[AsyncSession, Depends(get_session)],
    admin: Annotated[CurrentUser, Depends(require_admin)],
) -> CreateApiKeyResp:
    raw, prefix, digest = generate_key()
    row = (
        await session.execute(
            text(
                """
                INSERT INTO api_keys (label, key_hash, key_prefix, created_by)
                VALUES (:label, :h, :p, :cb)
                RETURNING id::text, created_at
                """
            ),
            {"label": payload.label, "h": digest, "p": prefix, "cb": admin.id},
        )
    ).first()
    await session.commit()
    return CreateApiKeyResp(
        id=row[0], label=payload.label, key=raw, prefix=prefix,
        created_at=row[1].isoformat(),
    )


@router.get("/api-keys", response_model=list[ApiKeyOut])
async def list_api_keys(
    session: Annotated[AsyncSession, Depends(get_session)],
    _admin: Annotated[CurrentUser, Depends(require_admin)],
) -> list[ApiKeyOut]:
    rows = (
        await session.execute(
            text(
                """
                SELECT id::text, label, key_prefix, active,
                       created_at, last_used_at, use_count
                FROM api_keys
                ORDER BY created_at DESC
                """
            )
        )
    ).all()
    return [
        ApiKeyOut(
            id=r[0], label=r[1], prefix=r[2], active=bool(r[3]),
            created_at=r[4].isoformat(),
            last_used_at=r[5].isoformat() if r[5] else None,
            use_count=int(r[6] or 0),
        )
        for r in rows
    ]


@router.delete("/api-keys/{key_id}", status_code=status.HTTP_204_NO_CONTENT)
async def revoke_api_key(
    key_id: Annotated[UUID, Path()],
    session: Annotated[AsyncSession, Depends(get_session)],
    _admin: Annotated[CurrentUser, Depends(require_admin)],
) -> None:
    res = await session.execute(
        text("UPDATE api_keys SET active = false WHERE id = :id"),
        {"id": str(key_id)},
    )
    await session.commit()
    if res.rowcount == 0:
        raise HTTPException(status.HTTP_404_NOT_FOUND, "api key not found")
