"""
This module provides a client for context engine to publish data to a specified topic.
"""

from typing import TypeVar
import os
import logging
from .component_io import ContextDefinition, ComponentIO
from .typing import ContextType

T = TypeVar("T", bound=ContextType)

logging.basicConfig(level=os.environ.get("LOG_LEVEL", "ERROR"))
logger = logging.getLogger(__name__)


class ContextEngineClient(ComponentIO[T, T]):
    """Client for publishing data to a context engine service.

    This component is designed to be part of a larger pipeline system. It
    automatically constructs a unique NATS topic for publishing results based on the
    pipeline and module IDs inherited from the `ComponentIO` base class.

    This class is generic, allowing it to handle and publish any specified data type.

    Args:
        Generic (T): The type of data that the client will publish.

    Attributes:
        publish_topic (str): The NATS topic where data will be published, formatted as
            '{asset_id}/context-engine/result'.
    """

    context_definition: list[ContextDefinition]

    def __init__(self) -> None:
        """Initializes the ContextEngineClient and sets the publish topic."""
        super().__init__()

        self.publish_topic = f"{self.asset_id}/context-engine/result"
        self._state: T | None = None
        self.context_definition: list[ContextDefinition] = []

    @property
    def context(self) -> T | None:
        """Read-only access to the latest received state."""
        return self._state

    def connect(self) -> None:
        """Connects to the message broker and subscribes to the publish topic."""
        super().connect()
        self._subscribe(self.publish_topic, self._handle_incoming_message)

    def publish_data(self, data: T) -> None:
        """Asynchronously publishes data to the predefined topic.

        This method is a convenience wrapper around the parent's `publish` method,
        sending the data to the topic specified in `self.publish_topic`.

        Args:
            data (T): The data payload to publish. The type is generic and
                should be compatible with the configured message broker's serializer.

        Raises:
            ValueError: If any keys in the data do not correspond to existing channels.
        """
        self._publish(self.publish_topic, data)

    def _handle_incoming_message(self, message: T) -> None:
        """Handle incoming messages from the context engine and update state."""
        logger.info("Received message %s", message)
        self._state = message
