import threading
import time
from typing import Dict, Any, List, Optional


class Blackboard:
    """
    RW Whiteboard + Hypercontext (The shared state).
    Provides thread-safe access to session state, tool outputs, and plan status.
    """

    def __init__(self):
        self._lock = threading.Lock()
        self._data = {
            "state": "IDLE",
            "objective": None,
            "plan": [],
            "step_index": 0,
            "tool_outputs": {},
            "metrics": {
                "tokens_spent": 0,
                "cost_total": 0.0,
                "errors": 0,
                "start_time": time.time(),
            },
            "provenance": [],  # History of who wrote what
        }
        self.hypercontext = {}  # Ephemeral working memory

    def write(self, key: str, value: Any, source: str):
        with self._lock:
            self._data[key] = value
            self._data["provenance"].append(
                {"key": key, "source": source, "timestamp": time.time()}
            )

    def read(self, key: str) -> Any:
        with self._lock:
            return self._data.get(key)

    def update_metrics(self, tokens: int, cost: float, error: bool = False):
        with self._lock:
            self._data["metrics"]["tokens_spent"] += tokens
            self._data["metrics"]["cost_total"] += cost
            if error:
                self._data["metrics"]["errors"] += 1

    def increment_step(self):
        with self._lock:
            self._data["step_index"] += 1

    def get_world_state(self) -> Dict[str, Any]:
        """Returns a snapshot for models."""
        with self._lock:
            return {
                "objective": self._data["objective"],
                "step": self._data["step_index"],
                "last_output": list(self._data["tool_outputs"].values())[-1]
                if self._data["tool_outputs"]
                else None,
                "metrics": self._data["metrics"],
            }

    def set_plan(self, steps: List[str], source: str):
        self.write("plan", steps, source)
        self.write("step_index", 0, source)
        self.write("state", "EXECUTING", source)
