"""
Execution context for automations.

This module provides the ExecutionContext class that gives automations
access to execution metadata and progress reporting capabilities.
"""

from typing import Any, Optional

from torivers_sdk.context.actions import ActionClient
from torivers_sdk.context.progress import ProgressReporterBase


class ExecutionContext:
    """
    Provides execution context to automation nodes.

    Developers use this to:
    - Report progress to users
    - Log events
    - Access execution metadata

    Note: Sensitive data (user_id, wallet info) is NOT exposed
    to third-party automations for security reasons.

    Example:
        def process_data(self, state: MyState) -> dict:
            context = state["context"]

            context.log_progress("Processing data", "Step 1 of 3")
            # ... do work ...

            context.log_success("Data processed", "Processed 100 items")
            return {
                "output_data": {
                    "_version": 1,
                    "_blocks": [
                        {
                            "type": "json_data",
                            "label": "Processing Summary",
                            "data": {"items_processed": 100},
                            "display_hint": "key_value",
                        }
                    ],
                }
            }
    """

    def __init__(
        self,
        execution_id: str,
        progress: ProgressReporterBase,
        actions: Optional[ActionClient] = None,
    ) -> None:
        """
        Initialize execution context.

        Args:
            execution_id: Unique identifier for this execution
            progress: Progress reporter for user-visible logs
        """
        self._execution_id = execution_id
        self._progress = progress
        self._metadata: dict[str, Any] = {}
        self._actions = actions

    @property
    def execution_id(self) -> str:
        """Get the current execution ID."""
        return self._execution_id

    @property
    def progress(self) -> ProgressReporterBase:
        """Get the progress reporter instance."""
        return self._progress

    @property
    def actions(self) -> Optional[ActionClient]:
        """Get the action client (if runtime configured)."""
        return self._actions

    def _log_via_action(
        self,
        level: str,
        title: str,
        description: str,
        metadata: dict[str, Any] | None,
    ) -> None:
        """
        Best-effort real-time log forwarding via unified action proxy.

        Logging remains fail-open; local progress entries are still buffered.
        """
        if self._actions is None:
            return
        try:
            self._actions.execute(
                "log.write",
                {
                    "level": level,
                    "title": title,
                    "description": description,
                    "metadata": metadata or {},
                },
            )
        except Exception:
            # Never fail automation logic due to logging transport issues.
            return

    def log_info(
        self,
        title: str,
        description: str = "",
        metadata: dict[str, Any] | None = None,
    ) -> None:
        """
        Log an informational message visible to the user.

        Use this for general status updates.

        Args:
            title: Short info title (e.g., "Configuration loaded")
            description: Optional detailed description
            metadata: Optional metadata for debugging
        """
        self._progress.log_info(title, description, metadata)
        self._log_via_action("info", title, description, metadata)

    def log_progress(
        self,
        title: str,
        description: str = "",
        metadata: dict[str, Any] | None = None,
    ) -> None:
        """
        Log progress visible to the user.

        Use this to show the user what the automation is currently doing.

        Args:
            title: Short progress title (e.g., "Processing data")
            description: Optional detailed description
            metadata: Optional metadata for debugging
        """
        self._progress.log_action(title, description, metadata)
        self._log_via_action("action", title, description, metadata)

    def log_success(
        self,
        title: str,
        description: str = "",
        metadata: dict[str, Any] | None = None,
    ) -> None:
        """
        Log a success message visible to the user.

        Use this to indicate successful completion of a step.

        Args:
            title: Short success message (e.g., "Data processed")
            description: Optional detailed description
            metadata: Optional metadata for debugging
        """
        self._progress.log_success(title, description, metadata)
        self._log_via_action("success", title, description, metadata)

    def log_warning(
        self,
        title: str,
        description: str = "",
        metadata: dict[str, Any] | None = None,
    ) -> None:
        """
        Log a warning message visible to the user.

        Use this to indicate non-fatal issues that the user should know about.

        Args:
            title: Short warning message (e.g., "Rate limit approaching")
            description: Optional detailed description
            metadata: Optional metadata for debugging
        """
        self._progress.log_warning(title, description, metadata)
        self._log_via_action("warning", title, description, metadata)

    def log_error(
        self,
        title: str,
        description: str = "",
        metadata: dict[str, Any] | None = None,
    ) -> None:
        """
        Log an error message visible to the user.

        Use this to indicate errors that affect the automation.

        Args:
            title: Short error message (e.g., "API request failed")
            description: Optional detailed description
            metadata: Optional metadata for debugging
        """
        self._progress.log_error(title, description, metadata)
        self._log_via_action("error", title, description, metadata)

    def set_metadata(self, key: str, value: Any) -> None:
        """
        Set execution metadata for debugging and analytics.

        This metadata is stored with the execution but not shown to users.

        Args:
            key: Metadata key
            value: Metadata value (must be JSON-serializable)
        """
        self._metadata[key] = value

    def get_metadata(self, key: str, default: Any = None) -> Any:
        """
        Get execution metadata.

        Args:
            key: Metadata key
            default: Default value if key not found

        Returns:
            Metadata value or default
        """
        return self._metadata.get(key, default)

    def get_all_metadata(self) -> dict[str, Any]:
        """
        Get all execution metadata.

        Returns:
            Copy of the metadata dictionary
        """
        return dict(self._metadata)

    def clear_metadata(self) -> None:
        """Clear all execution metadata."""
        self._metadata.clear()
