"""Type definitions for the hooks system."""

from __future__ import annotations

from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Literal


class HookEvent(str, Enum):
    """Events that can trigger hooks."""

    # Session lifecycle
    SESSION_START = "session_start"  # When a new task session begins
    SESSION_END = "session_end"  # When a task session completes

    # Tool execution
    PRE_TOOL_USE = "pre_tool_use"  # Before any tool is executed
    POST_TOOL_USE = "post_tool_use"  # After any tool is executed

    # Step lifecycle
    STEP_START = "step_start"  # Before a plan step begins
    STEP_COMPLETE = "step_complete"  # After a plan step completes

    # Error handling
    ON_ERROR = "on_error"  # When an error occurs


@dataclass
class HookConfig:
    """Configuration for a single hook."""

    event: HookEvent  # Which event triggers this hook
    script: str  # Path to script to execute (Python or shell)
    tool: str | None = None  # Optional: only trigger for specific tool
    enabled: bool = True  # Can be disabled without removing

    @classmethod
    def from_dict(cls, data: dict) -> "HookConfig":
        """Create from dictionary."""
        return cls(
            event=HookEvent(data["event"]),
            script=data["script"],
            tool=data.get("tool"),
            enabled=data.get("enabled", True),
        )

    def to_dict(self) -> dict:
        """Convert to dictionary."""
        return {
            "event": self.event.value,
            "script": self.script,
            "tool": self.tool,
            "enabled": self.enabled,
        }


@dataclass
class HookContext:
    """Context passed to hooks during execution."""

    event: HookEvent
    tool_name: str | None = None
    tool_input: dict | None = None
    tool_result: dict | None = None
    step_id: str | None = None
    step_description: str | None = None
    task: str | None = None
    error: str | None = None
    extra: dict = field(default_factory=dict)

    def to_dict(self) -> dict:
        """Convert to dictionary for passing to scripts."""
        return {
            "event": self.event.value,
            "tool_name": self.tool_name,
            "tool_input": self.tool_input,
            "tool_result": self.tool_result,
            "step_id": self.step_id,
            "step_description": self.step_description,
            "task": self.task,
            "error": self.error,
            **self.extra,
        }


@dataclass
class HookResult:
    """Result from executing a hook."""

    success: bool
    blocked: bool = False  # If True, the operation should be blocked
    message: str | None = None  # Message to show user
    modified_input: dict | None = None  # Modified tool input (for pre_tool_use)
    inject_context: str | None = None  # Context to inject (for session_start)
    error: str | None = None

    @classmethod
    def allow(cls) -> "HookResult":
        """Create a result that allows the operation to proceed."""
        return cls(success=True)

    @classmethod
    def block(cls, message: str) -> "HookResult":
        """Create a result that blocks the operation."""
        return cls(success=True, blocked=True, message=message)

    @classmethod
    def fail(cls, error: str) -> "HookResult":
        """Create a result indicating hook failure."""
        return cls(success=False, error=error)

    @classmethod
    def modify(cls, modified_input: dict) -> "HookResult":
        """Create a result that modifies tool input."""
        return cls(success=True, modified_input=modified_input)

    @classmethod
    def inject(cls, context: str) -> "HookResult":
        """Create a result that injects context."""
        return cls(success=True, inject_context=context)
