"""Workspace agent registry models."""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any, Literal

from beaver.coordinator.models import AgentDescriptor


AgentRegistryStatus = Literal["active", "disabled"]
AgentRegistrySource = Literal["builtin", "workspace", "learned"]


@dataclass(slots=True)
class RegisteredAgent:
    agent_id: str
    name: str
    display_name: str
    role: str
    description: str
    system_prompt: str
    capabilities: list[str] = field(default_factory=list)
    skill_names: list[str] = field(default_factory=list)
    tool_hints: list[str] = field(default_factory=list)
    model: str | None = None
    provider_name: str | None = None
    tags: list[str] = field(default_factory=list)
    priority: int = 0
    status: AgentRegistryStatus = "active"
    source: AgentRegistrySource = "workspace"
    metadata: dict[str, Any] = field(default_factory=dict)
    created_at: str = field(default_factory=lambda: _utc_now())
    updated_at: str = field(default_factory=lambda: _utc_now())

    def to_descriptor(self) -> AgentDescriptor:
        return AgentDescriptor(
            name=self.name,
            role=self.role,
            system_prompt=self.system_prompt,
            model=self.model,
            provider_name=self.provider_name,
            metadata={
                **self.metadata,
                "agent_id": self.agent_id,
                "display_name": self.display_name,
                "description": self.description,
                "capabilities": list(self.capabilities),
                "skill_names": list(self.skill_names),
                "tool_hints": list(self.tool_hints),
                "tags": list(self.tags),
                "source": self.source,
                "resolution": "registered",
            },
        )

    def to_dict(self) -> dict[str, Any]:
        return {
            "agent_id": self.agent_id,
            "name": self.name,
            "display_name": self.display_name,
            "role": self.role,
            "description": self.description,
            "system_prompt": self.system_prompt,
            "capabilities": list(self.capabilities),
            "skill_names": list(self.skill_names),
            "tool_hints": list(self.tool_hints),
            "model": self.model,
            "provider_name": self.provider_name,
            "tags": list(self.tags),
            "priority": self.priority,
            "status": self.status,
            "source": self.source,
            "metadata": dict(self.metadata),
            "created_at": self.created_at,
            "updated_at": self.updated_at,
        }

    @classmethod
    def from_dict(cls, payload: dict[str, Any]) -> "RegisteredAgent":
        now = _utc_now()
        agent_id = str(payload.get("agent_id") or payload.get("id") or payload.get("name") or "").strip()
        if not agent_id:
            raise ValueError("RegisteredAgent requires agent_id")
        name = str(payload.get("name") or agent_id).strip()
        return cls(
            agent_id=agent_id,
            name=name,
            display_name=str(payload.get("display_name") or payload.get("displayName") or name).strip(),
            role=str(payload.get("role") or "").strip(),
            description=str(payload.get("description") or "").strip(),
            system_prompt=str(payload.get("system_prompt") or payload.get("systemPrompt") or "").strip(),
            capabilities=_string_list(payload.get("capabilities")),
            skill_names=_string_list(payload.get("skill_names") or payload.get("skillNames")),
            tool_hints=_string_list(payload.get("tool_hints") or payload.get("toolHints")),
            model=_optional_str(payload.get("model")),
            provider_name=_optional_str(payload.get("provider_name") or payload.get("providerName")),
            tags=_string_list(payload.get("tags")),
            priority=int(payload.get("priority", 0) or 0),
            status="disabled" if str(payload.get("status") or "active") == "disabled" else "active",
            source=_source(payload.get("source")),
            metadata=dict(payload.get("metadata") or {}),
            created_at=str(payload.get("created_at") or payload.get("createdAt") or now),
            updated_at=str(payload.get("updated_at") or payload.get("updatedAt") or now),
        )


@dataclass(slots=True)
class AgentMatch:
    agent_id: str
    score: float
    reasons: list[str]
    matched_capabilities: list[str]
    resolved_descriptor: AgentDescriptor

    def to_dict(self) -> dict[str, Any]:
        return {
            "agent_id": self.agent_id,
            "score": self.score,
            "reasons": list(self.reasons),
            "matched_capabilities": list(self.matched_capabilities),
            "resolved_descriptor": {
                "name": self.resolved_descriptor.name,
                "role": self.resolved_descriptor.role,
                "model": self.resolved_descriptor.model,
                "provider_name": self.resolved_descriptor.provider_name,
                "metadata": dict(self.resolved_descriptor.metadata),
            },
        }


@dataclass(slots=True)
class TargetResolutionReport:
    node_id: str
    requested_role: str
    requested_capabilities: list[str]
    selected_agent_id: str | None
    fallback_used: bool
    score: float
    reason: str

    def to_dict(self) -> dict[str, Any]:
        return {
            "node_id": self.node_id,
            "requested_role": self.requested_role,
            "requested_capabilities": list(self.requested_capabilities),
            "selected_agent_id": self.selected_agent_id,
            "fallback_used": self.fallback_used,
            "score": self.score,
            "reason": self.reason,
        }


def _utc_now() -> str:
    return datetime.now(timezone.utc).isoformat()


def _optional_str(value: Any) -> str | None:
    if value in (None, ""):
        return None
    text = str(value).strip()
    return text or None


def _string_list(value: Any) -> list[str]:
    if not isinstance(value, list):
        if isinstance(value, str):
            value = [item.strip() for item in value.split(",")]
        else:
            return []
    result: list[str] = []
    for item in value:
        text = str(item).strip()
        if text and text not in result:
            result.append(text)
    return result


def _source(value: Any) -> AgentRegistrySource:
    text = str(value or "workspace").strip()
    if text in {"builtin", "workspace", "learned"}:
        return text  # type: ignore[return-value]
    return "workspace"
