from typing import Any

from fastapi.testclient import TestClient

from grantflow.api.app import app

client = TestClient(app)
API_KEY_SECURITY = [{"ApiKeyAuth": []}]
AGENT_CREDENTIAL_SECURITY = [{"ApiKeyAuth": []}, {"BearerAuth": []}]


def openapi_spec() -> dict[str, Any]:
    response = client.get("/openapi.json")
    assert response.status_code == 200
    return dict(response.json())


def operation(spec: dict[str, Any], path: str, method: str) -> dict[str, Any]:
    paths = spec.get("paths") or {}
    return (paths.get(path) or {}).get(method) or {}


def security_for(spec: dict[str, Any], path: str, method: str) -> Any:
    return operation(spec, path, method).get("security")


def response_schema_for(spec: dict[str, Any], path: str, method: str) -> Any:
    return (
        (operation(spec, path, method).get("responses") or {})
        .get("200", {})
        .get("content", {})
        .get("application/json", {})
        .get("schema")
    )


def schemas(spec: dict[str, Any]) -> dict[str, Any]:
    return dict((spec.get("components") or {}).get("schemas") or {})


def parameter_names_for(spec: dict[str, Any], path: str, method: str) -> set[str]:
    parameters = operation(spec, path, method).get("parameters") or []
    return {str(param.get("name") or "") for param in parameters if isinstance(param, dict)}


def schema_props_for(spec: dict[str, Any], schema_name: str) -> set[str]:
    schema = schemas(spec).get(schema_name)
    if not isinstance(schema, dict):
        return set()
    props = schema.get("properties") or {}
    return set(props)
