# app/models/syndarix/agent_instance.py
"""
AgentInstance model for Syndarix AI consulting platform.

An AgentInstance is a spawned instance of an AgentType, assigned to a
specific project to perform work.
"""

from sqlalchemy import (
    BigInteger,
    Column,
    DateTime,
    Enum,
    ForeignKey,
    Index,
    Integer,
    Numeric,
    String,
    Text,
)
from sqlalchemy.dialects.postgresql import (
    JSONB,
    UUID as PGUUID,
)
from sqlalchemy.orm import relationship

from app.models.base import Base, TimestampMixin, UUIDMixin

from .enums import AgentStatus


class AgentInstance(Base, UUIDMixin, TimestampMixin):
    """
    AgentInstance model representing a spawned agent working on a project.

    Tracks:
    - Current status and task
    - Memory (short-term in DB, long-term reference to vector store)
    - Session information for MCP connections
    - Usage metrics (tasks completed, tokens, cost)
    """

    __tablename__ = "agent_instances"

    # Foreign keys
    agent_type_id = Column(
        PGUUID(as_uuid=True),
        ForeignKey("agent_types.id", ondelete="RESTRICT"),
        nullable=False,
        index=True,
    )

    project_id = Column(
        PGUUID(as_uuid=True),
        ForeignKey("projects.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
    )

    # Agent instance name (e.g., "Dave", "Eve") for personality
    name = Column(String(100), nullable=False, index=True)

    # Status tracking
    status: Column[AgentStatus] = Column(
        Enum(AgentStatus),
        default=AgentStatus.IDLE,
        nullable=False,
        index=True,
    )

    # Current task description (brief summary of what agent is doing)
    current_task = Column(Text, nullable=True)

    # Short-term memory stored in database (conversation context, recent decisions)
    short_term_memory = Column(JSONB, default=dict, nullable=False)

    # Reference to long-term memory in vector store (e.g., "project-123/agent-456")
    long_term_memory_ref = Column(String(500), nullable=True)

    # Session ID for active MCP connections
    session_id = Column(String(255), nullable=True, index=True)

    # Activity tracking
    last_activity_at = Column(DateTime(timezone=True), nullable=True, index=True)
    terminated_at = Column(DateTime(timezone=True), nullable=True, index=True)

    # Usage metrics
    tasks_completed = Column(Integer, default=0, nullable=False)
    tokens_used = Column(BigInteger, default=0, nullable=False)
    cost_incurred = Column(Numeric(precision=10, scale=4), default=0, nullable=False)

    # Relationships
    agent_type = relationship("AgentType", back_populates="instances")
    project = relationship("Project", back_populates="agent_instances")
    assigned_issues = relationship(
        "Issue",
        back_populates="assigned_agent",
        foreign_keys="Issue.assigned_agent_id",
    )

    __table_args__ = (
        Index("ix_agent_instances_project_status", "project_id", "status"),
        Index("ix_agent_instances_type_status", "agent_type_id", "status"),
        Index("ix_agent_instances_project_type", "project_id", "agent_type_id"),
    )

    def __repr__(self) -> str:
        return (
            f"<AgentInstance {self.name} ({self.id}) type={self.agent_type_id} "
            f"project={self.project_id} status={self.status.value}>"
        )
