"""Tenant checks against normbase/eda responses (BFF authorization)."""

from __future__ import annotations

import uuid
from typing import Any

from fastapi import HTTPException, status

from aif_platform.server.infra.upstream import EdaClient, NormbaseClient


def _uuid_str(value: Any) -> str | None:
    if value is None:
        return None
    return str(value)


async def field_belongs_to_org(
    nb: NormbaseClient,
    *,
    field_id: uuid.UUID,
    org_id: uuid.UUID,
) -> bool:
    fields = await nb.list_fields()
    if not isinstance(fields, list):
        return False
    for item in fields:
        if _uuid_str(item.get("id")) != str(field_id):
            continue
        field_org = item.get("org_id")
        if field_org is None:
            return False
        return _uuid_str(field_org) == str(org_id)
    return False


async def require_field_in_org(
    nb: NormbaseClient,
    *,
    field_id: uuid.UUID,
    org_id: uuid.UUID,
) -> None:
    if not await field_belongs_to_org(nb, field_id=field_id, org_id=org_id):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Field not in current organization.",
        )


async def require_norm_in_org(
    nb: NormbaseClient,
    *,
    norm_id: uuid.UUID,
    org_id: uuid.UUID,
) -> dict[str, Any]:
    norm = await nb.get_norm(norm_id)
    if not isinstance(norm, dict):
        raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail="Invalid norm response.")
    fid = norm.get("field_id")
    if fid is None:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Norm has no field context.",
        )
    await require_field_in_org(nb, field_id=uuid.UUID(str(fid)), org_id=org_id)
    return norm


async def require_agent_in_org(
    eda: EdaClient,
    *,
    agent_id: uuid.UUID,
    org_id: uuid.UUID,
) -> dict[str, Any]:
    agent = await eda.get_agent(agent_id)
    if not isinstance(agent, dict):
        raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail="Invalid agent response.")
    aid_org = agent.get("org_id")
    if aid_org is None or _uuid_str(aid_org) != str(org_id):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Agent not in current organization.",
        )
    return agent


async def active_fields_allowed_for_org(
    nb: NormbaseClient,
    *,
    active_field_ids: list[str],
    org_id: uuid.UUID,
) -> bool:
    for raw in active_field_ids:
        try:
            fid = uuid.UUID(str(raw))
        except ValueError:
            return False
        if not await field_belongs_to_org(nb, field_id=fid, org_id=org_id):
            return False
    return True
