"""API keys router: create, list, revoke.

Gated under ``members:manage`` (Owner/Admin). The plaintext secret is returned
exactly once, at creation.
"""

from __future__ import annotations

import uuid

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session

from legate.api.deps import Principal, require
from legate.api.schemas import ApiKeyCreate, ApiKeyCreateResponse, ApiKeyOut
from legate.audit.service import record as audit_record
from legate.db.session import get_db
from legate.policy.rbac import Permission, scopes_for_role
from legate.repositories import api_keys as api_keys_repo
from legate.security.api_keys import generate_api_key

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


@router.get("", response_model=list[ApiKeyOut])
def list_api_keys(
    principal: Principal = Depends(require(Permission.MANAGE_MEMBERS)),
    db: Session = Depends(get_db),
) -> list[ApiKeyOut]:
    keys = api_keys_repo.list_for_workspace(db, workspace_id=principal.workspace_id)
    return [ApiKeyOut.model_validate(k) for k in keys]


@router.post("", response_model=ApiKeyCreateResponse, status_code=status.HTTP_201_CREATED)
def create_api_key(
    body: ApiKeyCreate,
    principal: Principal = Depends(require(Permission.MANAGE_MEMBERS)),
    db: Session = Depends(get_db),
) -> ApiKeyCreateResponse:
    if body.scopes is not None:
        scopes = body.scopes
    elif body.role is not None:
        scopes = scopes_for_role(body.role)
    else:
        scopes = [Permission.VIEW.value]

    generated = generate_api_key()
    created_by = principal.user.id if principal.user else None
    key = api_keys_repo.create(
        db,
        workspace_id=principal.workspace_id,
        created_by=created_by,
        name=body.name,
        prefix=generated.prefix,
        hashed_key=generated.hashed_key,
        scopes=scopes,
    )
    audit_record(
        db,
        workspace_id=principal.workspace_id,
        actor=principal.actor,
        action="api_key.create",
        target=str(key.id),
        metadata={"name": key.name, "scopes": scopes},
    )
    db.commit()
    db.refresh(key)
    return ApiKeyCreateResponse(
        api_key=ApiKeyOut.model_validate(key), plaintext=generated.plaintext
    )


@router.delete("/{key_id}", status_code=status.HTTP_204_NO_CONTENT)
def revoke_api_key(
    key_id: uuid.UUID,
    principal: Principal = Depends(require(Permission.MANAGE_MEMBERS)),
    db: Session = Depends(get_db),
) -> None:
    key = api_keys_repo.get_by_id(db, key_id=key_id, workspace_id=principal.workspace_id)
    if key is None:
        raise HTTPException(status.HTTP_404_NOT_FOUND, detail="API key not found")
    if key.revoked_at is None:
        api_keys_repo.revoke(db, key)
        audit_record(
            db,
            workspace_id=principal.workspace_id,
            actor=principal.actor,
            action="api_key.revoke",
            target=str(key.id),
            metadata={"name": key.name},
        )
        db.commit()
