"""Agent mode management tools.

Provides tools for switching between different agent modes
(exploration, planning, coding, etc).
"""

from dataclasses import dataclass
from enum import Enum
from typing import Optional

from .base import BaseTool, ToolResult, ToolCategory


class AgentMode(Enum):
    """Available agent modes."""

    EXPLORATION = "exploration"
    PLANNING = "planning"
    CODING = "coding"
    REVIEW = "review"
    DEBUG = "debug"


@dataclass
class ModeState:
    """Singleton state for agent mode."""

    current_mode: AgentMode = AgentMode.EXPLORATION
    mode_context: dict = None

    _instance: Optional["ModeState"] = None

    def __post_init__(self):
        if self.mode_context is None:
            self.mode_context = {}

    @classmethod
    def get_instance(cls) -> "ModeState":
        """Get the singleton instance."""
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

    @classmethod
    def reset(cls) -> None:
        """Reset the singleton instance."""
        cls._instance = None


class SwitchModeTool(BaseTool):
    """Tool for switching between agent modes."""

    name = "switch_mode"
    description = """Switch the agent to a different operating mode.

Modes:
- exploration: General codebase exploration and understanding
- planning: Feature planning and specification writing
- coding: Active code editing and implementation
- review: Code review and feedback
- debug: Debugging and issue investigation"""
    category = ToolCategory.PLANNING

    def __init__(self, connection=None):
        """Initialize without requiring connection."""
        self.connection = connection

    def execute(
        self,
        mode: str,
        context: Optional[str] = None,
    ) -> ToolResult:
        """Switch to a new mode.

        Args:
            mode: Target mode name
            context: Optional context for the new mode

        Returns:
            ToolResult indicating success
        """
        try:
            new_mode = AgentMode(mode.lower())
        except ValueError:
            valid_modes = [m.value for m in AgentMode]
            return ToolResult.error_result(
                f"Invalid mode: {mode}",
                suggestions=[f"Valid modes: {', '.join(valid_modes)}"],
            )

        state = ModeState.get_instance()
        old_mode = state.current_mode
        state.current_mode = new_mode

        if context:
            state.mode_context[new_mode.value] = context

        return ToolResult.success_result(
            data={
                "previous_mode": old_mode.value,
                "current_mode": new_mode.value,
                "context": context,
            },
        )

    def get_schema(self) -> dict:
        """Get OpenAI function schema."""
        return self._make_schema(
            properties={
                "mode": {
                    "type": "string",
                    "enum": [m.value for m in AgentMode],
                    "description": "Target mode to switch to",
                },
                "context": {
                    "type": "string",
                    "description": "Optional context for the new mode",
                },
            },
            required=["mode"],
        )


class GetModeTool(BaseTool):
    """Tool for getting current agent mode."""

    name = "get_mode"
    description = "Get the current agent operating mode and its context."
    category = ToolCategory.PLANNING

    def __init__(self, connection=None):
        """Initialize without requiring connection."""
        self.connection = connection

    def execute(self) -> ToolResult:
        """Get current mode.

        Returns:
            ToolResult with current mode info
        """
        state = ModeState.get_instance()

        return ToolResult.success_result(
            data={
                "current_mode": state.current_mode.value,
                "context": state.mode_context.get(state.current_mode.value),
                "available_modes": [m.value for m in AgentMode],
            },
        )

    def get_schema(self) -> dict:
        """Get OpenAI function schema."""
        return self._make_schema(properties={}, required=[])
