"""Workflow and component models for enterprise AI platform integration.

These models represent the structure of AI workflow chains, their components,
and input variables as discovered from enterprise platform REST APIs.
"""

from __future__ import annotations

from datetime import datetime
from enum import StrEnum
from typing import Any

from pydantic import BaseModel, Field


class ComponentType(StrEnum):
    """Types of components in a workflow chain."""
    LLM = "llm"
    TOOL = "tool"
    VECTOR_DB = "vector_db"
    DATA_CONNECTOR = "data_connector"
    CUSTOM = "custom"


class ComponentFamily(StrEnum):
    """Known component families / transport types."""
    MCP_STREAMABLE_HTTP = "McpStreamableHttp"
    ANTHROPIC = "Anthropic"
    OPENAI = "OpenAI"
    GOOGLE = "Google"
    META = "Meta"
    MISTRAL = "Mistral"
    OPEN_SEARCH = "OpenSearch"
    AWS_S3 = "AwsS3"
    SHAREPOINT = "SharePoint"
    CUSTOM = "Custom"


class ApiType(StrEnum):
    """API protocol types for tool components."""
    MCP = "mcp"
    REST = "rest"
    GRAPHQL = "graphql"
    WEBSOCKET = "websocket"


class AuthType(StrEnum):
    """Authentication methods for tool components."""
    BEARER = "bearer"
    API_KEY = "api_key"
    OAUTH2 = "oauth2"
    BASIC = "basic"
    NONE = "none"


class ParamType(StrEnum):
    """Parameter types for component model_params."""
    TEXT = "text"
    SECRET = "secret"
    NUMBER = "number"
    BOOLEAN = "boolean"
    SELECT = "select"
    MULTISELECT = "multiselect"


class InputVariableType(StrEnum):
    """Types of workflow input variables."""
    TEXT = "text"
    NUMBER = "number"
    SELECT = "select"
    MULTISELECT = "multiselect"
    SECRET = "secret"


# --- Component Configuration ---

class ToolConfig(BaseModel):
    """Configuration for a tool/MCP server component."""
    endpoint: str = Field(default="", description="MCP server endpoint URL")
    auth_type: AuthType = Field(default=AuthType.BEARER, description="Authentication method")
    headers: dict[str, str] = Field(default_factory=dict, description="Additional HTTP headers")


class ComponentParam(BaseModel):
    """A configurable parameter for a component."""
    key: str = Field(description="Parameter key (e.g., 'azure_devops_token')")
    type: ParamType = Field(default=ParamType.TEXT, description="Parameter value type")
    label: str = Field(default="", description="Human-readable label")
    description: str = Field(default="", description="Help text")
    required: bool = Field(default=False, description="Whether this parameter is required")
    default: str | None = Field(default=None, description="Default value")
    options: list[str] | None = Field(default=None, description="Available options for select/multiselect")


class WorkflowComponent(BaseModel):
    """A component within a workflow chain."""
    component_id: str = Field(description="Unique component identifier")
    component_name: str = Field(description="Display name (e.g., 'Azure DevOps MCP Server')")
    component_type: ComponentType = Field(description="Component type category")
    component_family: str = Field(default="", description="Component family (e.g., 'McpStreamableHttp')")
    api_type: str | None = Field(default=None, description="API protocol if tool type")
    position: int = Field(default=0, description="Position in the workflow chain")
    
    # Configuration
    tool_config: ToolConfig | None = Field(default=None, description="Tool endpoint configuration")
    model_params: list[ComponentParam] = Field(
        default_factory=list,
        description="Configurable parameters for this component"
    )
    
    # Runtime state
    is_configured: bool = Field(default=False, description="Whether all required params are set")
    current_values: dict[str, str] = Field(
        default_factory=dict,
        description="Current parameter values (secrets are masked in display)"
    )


class WorkflowInputVariable(BaseModel):
    """An input variable template in a workflow."""
    key: str = Field(description="Variable key (e.g., 'manual_entry_<TS>_<HASH>')")
    label: str = Field(description="Human-readable label (e.g., 'Work Item IDs')")
    type: InputVariableType = Field(default=InputVariableType.TEXT)
    description: str = Field(default="", description="Help text for the user")
    required: bool = Field(default=True, description="Whether this variable must be filled")
    default: str | None = Field(default=None, description="Default value")
    placeholder: str = Field(default="", description="Placeholder text for UI")


class WorkflowDefinition(BaseModel):
    """A complete workflow chain definition from the enterprise platform."""
    workflow_id: str = Field(description="Unique workflow UUID")
    title: str = Field(description="Workflow display title")
    description: str = Field(default="", description="Workflow description")
    system_prompt: str = Field(default="", description="The agent's system prompt (may contain template vars)")
    
    # Components
    components: list[WorkflowComponent] = Field(
        default_factory=list,
        description="Ordered list of components in the chain"
    )
    
    # Input variables
    input_variables: list[WorkflowInputVariable] = Field(
        default_factory=list,
        description="Template variables that the user must fill in"
    )
    
    # Metadata
    owner: str = Field(default="", description="Workflow creator/owner")
    is_owned_by_me: bool = Field(default=False, description="Whether current user owns this")
    created_at: datetime | None = Field(default=None)
    updated_at: datetime | None = Field(default=None)
    
    # Computed
    @property
    def llm_components(self) -> list[WorkflowComponent]:
        """Get LLM components in the chain."""
        return [c for c in self.components if c.component_type == ComponentType.LLM]
    
    @property
    def tool_components(self) -> list[WorkflowComponent]:
        """Get tool/MCP server components in the chain."""
        return [c for c in self.components if c.component_type == ComponentType.TOOL]
    
    @property
    def data_components(self) -> list[WorkflowComponent]:
        """Get data connector/vector DB components."""
        return [c for c in self.components if c.component_type in (ComponentType.VECTOR_DB, ComponentType.DATA_CONNECTOR)]


class WorkflowSummary(BaseModel):
    """Trimmed workflow listing entry (from workflow_trimmed API)."""
    workflow_id: str = Field(description="Workflow UUID")
    title: str = Field(description="Display title")
    description: str = Field(default="")
    owner: str = Field(default="")
    is_owned_by_me: bool = Field(default=False)
    component_count: int = Field(default=0)
    created_at: datetime | None = Field(default=None)
    updated_at: datetime | None = Field(default=None)


class WorkflowListResponse(BaseModel):
    """Response from the workflow listing API."""
    workflows: list[WorkflowSummary] = Field(default_factory=list)
    total_count: int = Field(default=0)
    page_size: int = Field(default=20)
    has_more: bool = Field(default=False)


# --- Platform Connection ---

class PlatformConfig(BaseModel):
    """Configuration for connecting to an enterprise AI platform."""
    platform_id: str = Field(description="Unique identifier for this platform connection")
    name: str = Field(description="Display name (e.g., 'Enterprise AI Platform')")
    base_url: str = Field(description="Platform frontend URL (e.g., 'https://platform.example.com')")
    api_base_url: str = Field(description="REST API base URL (e.g., 'https://api.example.com')")
    websocket_url: str = Field(description="WebSocket gateway URL template (e.g., 'wss://ws.example.com/prod')")
    
    # Auth configuration
    auth_type: str = Field(default="sso_browser", description="Auth method: sso_browser, oauth2, api_key")
    oauth_tenant_id: str | None = Field(default=None, description="Microsoft OAuth tenant ID if needed")
    oauth_client_id: str | None = Field(default=None, description="OAuth client ID")
    ado_resource_id: str = Field(
        default="499b84ac-1321-427f-aa17-267ca6975798",
        description="Azure DevOps resource ID for OAuth scopes (well-known)"
    )
    
    # Heartbeat
    heartbeat_interval_seconds: int = Field(default=27, description="WebSocket heartbeat interval")
    
    # Metadata
    enabled: bool = Field(default=True)
    created_at: datetime = Field(default_factory=datetime.now)


class PlatformConnection(BaseModel):
    """Active connection state for an enterprise platform."""
    config: PlatformConfig = Field(description="Platform configuration")
    is_authenticated: bool = Field(default=False, description="Whether SSO auth is complete")
    is_websocket_connected: bool = Field(default=False, description="Whether WebSocket is open")
    
    # Token state (never persisted to disk)
    platform_token_expires_at: datetime | None = Field(default=None, description="Platform JWT expiry")
    ado_token_expires_at: datetime | None = Field(default=None, description="Azure DevOps token expiry")
    has_github_pat: bool = Field(default=False, description="Whether GitHub PAT is configured")
    
    # Active workflow
    active_workflow_id: str | None = Field(default=None)
    active_conversation_id: str | None = Field(default=None)
