"""Input schemas for CI tools.

Pydantic models for validating tool inputs. Used by both MCP handlers
and SDK tool wrappers.
"""

from __future__ import annotations

from pydantic import BaseModel, Field

from open_agent_kit.features.team.constants import (
    CI_QUERY_DEFAULT_LIMIT,
    DEFAULT_MAX_CONTEXT_TOKENS,
    DEFAULT_SEARCH_LIMIT,
    INCLUDE_NETWORK_DESC_CONTEXT,
    INCLUDE_NETWORK_DESC_MEMORIES,
    INCLUDE_NETWORK_DESC_SEARCH,
    INCLUDE_NETWORK_DESC_SESSIONS,
    INCLUDE_NETWORK_DESC_STATS,
    OBSERVATION_STATUS_ACTIVE,
    SEARCH_TYPE_KNOWLEDGE,
)


class SearchInput(BaseModel):
    """Input for search tool (oak_search / ci_search)."""

    query: str = Field(..., description="Natural language search query")
    search_type: str = Field(
        default=SEARCH_TYPE_KNOWLEDGE,
        description=(
            "Type of search: 'knowledge' (memories+plans+sessions, default), "
            "'code', 'memory', 'plans', 'sessions', or 'all' (includes code)"
        ),
    )
    limit: int = Field(
        default=DEFAULT_SEARCH_LIMIT,
        description="Maximum number of results to return",
        ge=1,
        le=50,
    )
    include_resolved: bool = Field(
        default=False,
        description="If True, include resolved/superseded memories in results",
    )
    include_network: bool = Field(
        default=True,
        description=INCLUDE_NETWORK_DESC_SEARCH,
    )


class RememberInput(BaseModel):
    """Input for remember tool (oak_remember)."""

    observation: str = Field(
        ...,
        description="The observation or learning to remember",
    )
    memory_type: str = Field(
        default="discovery",
        description="Type: 'gotcha', 'bug_fix', 'decision', 'discovery', 'trade_off'",
    )
    context: str | None = Field(
        default=None,
        description="Related file path or context information",
    )


class ContextInput(BaseModel):
    """Input for context tool (oak_context)."""

    task: str = Field(
        ...,
        description="Description of the current task or what you're working on",
    )
    current_files: list[str] = Field(
        default_factory=list,
        description="Files currently being viewed or edited",
    )
    max_tokens: int = Field(
        default=DEFAULT_MAX_CONTEXT_TOKENS,
        description="Maximum tokens of context to return",
    )
    include_network: bool = Field(
        default=True,
        description=INCLUDE_NETWORK_DESC_CONTEXT,
    )


class MemoriesInput(BaseModel):
    """Input for memories listing tool (ci_memories)."""

    memory_type: str | None = Field(
        default=None,
        description="Filter by memory type (optional)",
    )
    limit: int = Field(
        default=20,
        description="Maximum number of results to return",
        ge=1,
        le=100,
    )
    status: str = Field(
        default=OBSERVATION_STATUS_ACTIVE,
        description="Filter by observation status: 'active', 'resolved', or 'superseded'",
    )
    include_resolved: bool = Field(
        default=False,
        description="If True, include all statuses regardless of status filter",
    )
    include_network: bool = Field(
        default=True,
        description=INCLUDE_NETWORK_DESC_MEMORIES,
    )


class SessionsInput(BaseModel):
    """Input for sessions listing tool (ci_sessions)."""

    limit: int = Field(
        default=10,
        description="Maximum number of sessions to return",
        ge=1,
        le=20,
    )
    include_summary: bool = Field(
        default=True,
        description="Include session summaries in output",
    )
    include_network: bool = Field(
        default=True,
        description=INCLUDE_NETWORK_DESC_SESSIONS,
    )


class StatsInput(BaseModel):
    """Input for project stats tool (ci_project_stats)."""

    include_network: bool = Field(
        default=True,
        description=INCLUDE_NETWORK_DESC_STATS,
    )


class QueryInput(BaseModel):
    """Input for SQL query tool (ci_query)."""

    sql: str = Field(..., description="SQL query (SELECT/WITH/EXPLAIN only)")
    limit: int = Field(
        default=CI_QUERY_DEFAULT_LIMIT,
        description="Maximum rows to return",
        ge=1,
        le=500,
    )


class ActivityInput(BaseModel):
    """Input for activity listing tool (oak_activity)."""

    session_id: str = Field(..., description="Session ID to get activities for")
    tool_name: str | None = Field(
        default=None,
        description="Filter by tool name (optional)",
    )
    limit: int = Field(
        default=50,
        description="Maximum number of activities to return",
        ge=1,
        le=200,
    )
    node_id: str | None = Field(
        default=None,
        description=("Target a specific node. Use oak_nodes to discover available nodes."),
    )


class ResolveInput(BaseModel):
    """Input for resolve memory tool (oak_resolve_memory)."""

    id: str = Field(..., description="The observation UUID to resolve")
    status: str = Field(
        default="resolved",
        description="New status - 'resolved' (default) or 'superseded'",
    )
    reason: str | None = Field(
        default=None,
        description="Optional reason for resolution",
    )
    node_id: str | None = Field(
        default=None,
        description=("Target a specific node. Use oak_nodes to discover available nodes."),
    )


class FetchInput(BaseModel):
    """Input for fetch tool (oak_fetch)."""

    ids: list[str] = Field(..., description="List of chunk IDs to fetch full content for")


class ArchiveInput(BaseModel):
    """Input for archive tool (ci_archive / oak_archive_memories)."""

    ids: list[str] | None = Field(
        default=None,
        description="Specific observation IDs to archive",
    )
    status_filter: str | None = Field(
        default=None,
        description="Archive by status: 'resolved', 'superseded', or 'both'",
    )
    older_than_days: int | None = Field(
        default=None,
        description="Only archive observations older than this many days",
        ge=1,
    )
    dry_run: bool = Field(
        default=False,
        description="If True, return count without actually archiving",
    )
    node_id: str | None = Field(
        default=None,
        description=("Target a specific node. Use oak_nodes to discover available nodes."),
    )
