"""Strategy execution context providing access to client, store, and state."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Dict, Optional

if TYPE_CHECKING:
    from sd_api.client.base import BaseClient
    from sd_api.storage.base import BaseStore


class StrategyContext:
    """Context object passed to strategy hooks.

    Provides a clean, stable API for strategies to interact with the outside world
    (fetching data, storing results, persisting state) without coupling to the
    runner internals.

    Attributes
    ----------
    client : BaseClient | None
        Reference to the SDClient instance (available after runner.start()).
    store : BaseStore | None
        Optional storage backend for persisting signals and bars.
    state : dict
        In-memory state dict shared across all strategy hooks within one run.
        Survives across quote/bar events; reset when a new run starts.
    metadata : dict
        Static metadata about the current run (symbol, timeframe, etc.).
    """

    def __init__(
        self,
        client: "Optional[BaseClient]" = None,
        store: "Optional[BaseStore]" = None,
        symbol: str = "",
        tf: str = "",
    ) -> None:
        self.client = client
        self.store = store
        self.state: Dict[str, Any] = {}
        self.metadata: Dict[str, Any] = {"symbol": symbol, "tf": tf}

    def set_client(self, client: "BaseClient") -> None:
        self.client = client

    def set_store(self, store: "BaseStore") -> None:
        self.store = store

    def get_state(self, key: str, default: Any = None) -> Any:
        return self.state.get(key, default)

    def set_state(self, key: str, value: Any) -> None:
        self.state[key] = value

    def clear_state(self) -> None:
        self.state.clear()
