from typing import List, Optional

from ...types._api_version import ApiVersion
from ...types.api.guardrail import Guardrail
from .._request_handler import AsyncRequestHandler
from .base_guardrail import BaseGuardrail


class AsyncGuardrails(BaseGuardrail):
    def __init__(self, request_handler: AsyncRequestHandler):
        super().__init__(request_handler)

    async def get_applicable_guardrails(
        self,
        project_id: str,
        agent_id: Optional[str] = None,
        correlation_id: Optional[str] = None,
    ) -> List[Guardrail]:
        """
        Get guardrails applicable to a specific project and optional agent.

        This method retrieves guardrail definitions that apply to the specified
        context using the same matching logic as pipeline execution. It supports
        hierarchical matching (tenant -> project -> agent) and exclusion mode
        (IsException flag) when the feature flag is enabled.

        Args:
            project_id (str): The unique identifier of the project. This is required
                and must be a valid GUID.
            agent_id (str, optional): The unique identifier of the agent/pipeline.
                When provided, returns guardrails applicable to this specific agent.
                When omitted, returns guardrails applicable at the project level only.
            correlation_id (str, optional): A unique identifier for request tracing
                and logging. If not provided, one will be automatically generated.

        Returns:
            List[Guardrail]: A list of guardrail definitions that apply to the
                specified context. Each guardrail includes its filters, assignments,
                and target configurations.

        Raises:
            AiriaAPIError: If the API request fails, including cases where:
                - The project_id is invalid or doesn't exist (400)
                - Authentication fails (401)
                - Access is forbidden (403)
                - Server errors (5xx)

        Example:
            ```python
            import asyncio
            from airia import AiriaAsyncClient

            async def main():
                client = AiriaAsyncClient(api_key="your_api_key")

                # Get project-level guardrails
                guardrails = await client.guardrail.get_applicable_guardrails(
                    project_id="00000000-0000-0000-0000-000000000000"
                )
                for guardrail in guardrails:
                    print(f"Guardrail: {guardrail.name}")
                    print(f"  Enabled: {guardrail.enabled}")
                    print(f"  Filters: {len(guardrail.filters)}")

                # Get agent-specific guardrails
                guardrails = await client.guardrail.get_applicable_guardrails(
                    project_id="00000000-0000-0000-0000-000000000000",
                    agent_id="11111111-1111-1111-1111-111111111111"
                )
                print(f"Found {len(guardrails)} guardrails for the agent")

            asyncio.run(main())
            ```

        Note:
            Guardrails are matched using hierarchical logic:
            - Tenant-level guardrails apply to all projects and agents
            - Project-level guardrails apply to all agents in that project
            - Agent-level guardrails apply only to that specific agent

            When `isException` is True on a guardrail target, the guardrail applies
            to all entities EXCEPT those in the assignment list.
        """
        request_data = self._pre_get_applicable_guardrails(
            project_id=project_id,
            agent_id=agent_id,
            correlation_id=correlation_id,
            api_version=ApiVersion.V1.value,
        )
        resp = await self._request_handler.make_request("POST", request_data)

        return [Guardrail(**item) for item in resp]
