"""
Agent Request Contract - API Contract for Agent Execution Requests.

Derived from: definitions/ai/contracts/agent_request.yaml

This module provides typed requests from the Elixir orchestrator to Django agents.
All agent execution requests must conform to this schema.

Usage:
    from lightwave.schema.pydantic.contracts.ai import AgentRequest

    request = AgentRequest(
        request_id=uuid4(),
        agent_type="v_accountant",
        conversation_id=uuid4(),
        message="Help me with my Q4 taxes",
        user_id=uuid4(),
        tenant_schema="tenant_lightwave",
    )
"""

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import Any
from uuid import UUID

from pydantic import Field, field_validator

from lightwave.schema.pydantic.core.base import LightwaveBaseSchema


class AgentType(str, Enum):
    """
    All valid agent type identifiers.

    Derived from: definitions/ai/agents/registry.yaml
    """

    # Orchestration
    V_CORE = "v_core"

    # Business Domain
    V_ACCOUNTANT = "v_accountant"
    V_LEGAL = "v_legal"
    V_GENERAL_MANAGER = "v_general_manager"

    # Technical
    SOFTWARE_ARCHITECT = "software_architect"
    SCRUM_MASTER = "scrum_master"
    V_DEVOPS = "v_devops"
    EXPLORE = "explore"
    ZEN_CODE_GENERATOR = "zen_code_generator"

    # Creative
    V_CINEMATOGRAPHER = "v_cinematographer"
    V_PHOTOGRAPHER = "v_photographer"
    LIGHTWAVE_COPYWRITER = "lightwave_copywriter"
    V_GURU = "v_guru"

    # Communication
    V_SPEAK = "v_speak"
    V_EMAIL_MANAGER = "v_email_manager"

    # Infrastructure
    INFRASTRUCTURE_OPS_AUDITOR = "infrastructure_ops_auditor"
    DJANGO_FRONTEND_ARCHITECT = "django_frontend_architect"

    # Discovery
    USER_STORY_INTERVIEWER = "user_story_interviewer"


class MessageRole(str, Enum):
    """Message roles in conversation history."""

    USER = "user"
    ASSISTANT = "assistant"
    SYSTEM = "system"


class RequestPriority(str, Enum):
    """Priority levels for agent requests."""

    LOW = "low"
    NORMAL = "normal"
    HIGH = "high"
    URGENT = "urgent"


class HistoryMessage(LightwaveBaseSchema):
    """A message in conversation history."""

    role: MessageRole = Field(
        ...,
        description="Message role",
    )

    content: str = Field(
        ...,
        max_length=32000,
        description="Message content",
    )

    timestamp: datetime | None = Field(
        None,
        description="When the message was sent",
    )

    agent_type: str | None = Field(
        None,
        description="Which agent sent this message (for assistant messages)",
    )


class HandoffContext(LightwaveBaseSchema):
    """Context passed during agent handoff."""

    from_agent: AgentType = Field(
        ...,
        description="Agent that initiated the handoff",
    )

    reason: str = Field(
        ...,
        max_length=500,
        description="Why the handoff occurred",
    )

    partial_result: str | None = Field(
        None,
        max_length=10000,
        description="Any partial work from the previous agent",
    )

    suggested_approach: str | None = Field(
        None,
        max_length=2000,
        description="Suggested approach from previous agent",
    )

    files_touched: list[str] | None = Field(
        None,
        description="Files already examined or modified",
    )


class AgentContext(LightwaveBaseSchema):
    """Context provided to the agent for execution."""

    message_history: list[HistoryMessage] | None = Field(
        None,
        max_length=50,
        description="Previous messages in the conversation",
    )

    system_prompt_additions: list[str] | None = Field(
        None,
        max_length=5,
        description="Additional system prompts to inject",
    )

    tool_restrictions: list[str] | None = Field(
        None,
        description="Restrict agent to specific tools",
    )

    files: list[str] | None = Field(
        None,
        max_length=20,
        description="File paths relevant to the request",
    )

    routing_reason: str | None = Field(
        None,
        max_length=500,
        description="Why this agent was selected",
    )

    handoff_from: HandoffContext | None = Field(
        None,
        description="Handoff context from previous agent",
    )

    task_id: UUID | None = Field(
        None,
        description="createOS task ID if this is task-related work",
    )

    story_id: UUID | None = Field(
        None,
        description="createOS story ID if this is story-related work",
    )


class AgentRequest(LightwaveBaseSchema):
    """
    Request payload for agent execution.

    This is the contract between the Elixir orchestrator and Django agents.
    All requests are validated against this schema before execution.

    Example:
        request = AgentRequest(
            request_id=uuid4(),
            agent_type=AgentType.V_ACCOUNTANT,
            conversation_id=uuid4(),
            message="Help me with my Q4 taxes",
            user_id=uuid4(),
            tenant_schema="tenant_lightwave",
        )

        # Send to Django
        response = await http_client.post("/api/agents/run/", json=request.model_dump())
    """

    request_id: UUID = Field(
        ...,
        description="Unique identifier for this request, used for tracing",
    )

    agent_type: AgentType = Field(
        ...,
        description="The type of agent to invoke",
    )

    conversation_id: UUID = Field(
        ...,
        description="Conversation context identifier for message history",
    )

    message: str = Field(
        ...,
        min_length=1,
        max_length=32000,
        description="The user's message to process",
    )

    context: AgentContext | None = Field(
        None,
        description="Optional context for the agent execution",
    )

    user_id: UUID = Field(
        ...,
        description="The authenticated user making the request",
    )

    tenant_schema: str = Field(
        ...,
        max_length=63,
        pattern=r"^[a-z][a-z0-9_]*$",
        description="PostgreSQL schema name for multi-tenant isolation",
    )

    priority: RequestPriority = Field(
        RequestPriority.NORMAL,
        description="Request priority level",
    )

    timeout_ms: int = Field(
        300000,
        ge=1000,
        le=600000,
        description="Request timeout in milliseconds",
    )

    stream: bool = Field(
        False,
        description="Whether to use streaming response (SSE)",
    )

    metadata: dict[str, Any] | None = Field(
        None,
        description="Additional metadata for logging/tracing",
    )

    @field_validator("message")
    @classmethod
    def message_not_empty(cls, v: str) -> str:
        """Validate message is not just whitespace."""
        if not v.strip():
            raise ValueError("Message cannot be empty or whitespace only")
        return v

    def get_timeout_multiplier(self) -> float:
        """Get timeout multiplier based on priority."""
        multipliers = {
            RequestPriority.LOW: 2.0,
            RequestPriority.NORMAL: 1.0,
            RequestPriority.HIGH: 0.8,
            RequestPriority.URGENT: 0.5,
        }
        return multipliers.get(self.priority, 1.0)

    def get_adjusted_timeout_ms(self) -> int:
        """Get timeout adjusted for priority."""
        return int(self.timeout_ms * self.get_timeout_multiplier())

    def has_history(self) -> bool:
        """Check if request has conversation history."""
        return bool(self.context and self.context.message_history)

    def is_handoff(self) -> bool:
        """Check if this request is from a handoff."""
        return bool(self.context and self.context.handoff_from)
