"""Base classes for block construction."""

from __future__ import annotations

from typing import ClassVar

from yera.agents import get_agent_context
from yera.events.models import (
    ActionData,
    BarChartData,
    ButtonsData,
    ColumnsData,
    ContainerData,
    DatePickerData,
    ExitEventData,
    InputRequestData,
    LayoutEndData,
    LineChartData,
    MarkdownData,
    OutputEvent,
    SliderData,
    SpinnerData,
    TableData,
)
from yera.events.models.in_event import InputEvent


def get_parent_block_id(exclude_block_id: str | None = None) -> str | None:
    """Get parent block ID from layout context if available."""
    # Import here to avoid circular import
    from yera.events.blocks.base.layout import _current_layout

    layout_context = _current_layout.get()
    if layout_context and layout_context.block_id != exclude_block_id:
        return layout_context.block_id
    return None


def create_event(
    block_type: str,
    block_id: str,
    data: (
        MarkdownData
        | ButtonsData
        | ActionData
        | SpinnerData
        | DatePickerData
        | SliderData
        | TableData
        | ContainerData
        | ColumnsData
        | BarChartData
        | LineChartData
        | LayoutEndData
    ),
    message_type: str,
    chunk_id: int,
    parent_block_id: str | None = None,
) -> OutputEvent:
    """Create an event with automatic layout context detection."""
    agent_ctx = get_agent_context()

    if parent_block_id is None:
        parent_block_id = get_parent_block_id(exclude_block_id=block_id)
    return OutputEvent(
        message_type=message_type,
        block_type=block_type,
        block_id=block_id,
        data=data,
        chunk_id=chunk_id,
        agent_instance=agent_ctx.metadata.make_instance_id(0),
        parent_block_id=parent_block_id,
    )


class _StreamHandle:
    """Base class for streamable block handles."""

    def __init__(self, block_id: str, block_type: str):
        self.block_id = block_id
        self.block_type = block_type
        self.chunk_counter = 0

    def _create_chunk_event(
        self,
        data: (
            MarkdownData
            | ActionData
            | SpinnerData
            | TableData
            | ContainerData
            | ColumnsData
        ),
        message_type: str = "informational",
        parent_block_id: str | None = None,
    ) -> OutputEvent:
        """Create a chunk event (for stream handles)."""
        self.chunk_counter += 1
        return create_event(
            block_type=self.block_type,
            block_id=self.block_id,
            data=data,
            message_type=message_type,
            chunk_id=self.chunk_counter,
            parent_block_id=parent_block_id,
        )


class _BlockFactory:
    """Base class for block construction factories."""

    _registry: ClassVar[list[_BlockFactory]] = []  # Track all factory instances

    def __init__(self, block_type: str):
        self.block_type = block_type
        self._block_counter = 0
        _BlockFactory._registry.append(self)  # Auto-register instance

    def reset(self) -> None:
        """Reset the block counter to 0."""
        self._block_counter = 0

    @classmethod
    def reset_all(cls) -> None:
        """Reset all registered factory instances."""
        for factory in cls._registry:
            factory.reset()

    def _generate_block_id(self) -> str:
        """Generate a block_id."""
        self._block_counter += 1
        return f"{self.block_type}-{self._block_counter}"

    def _create_block_input_event(self) -> InputEvent:
        pass

    def _create_block_output_event(
        self,
        data: (
            MarkdownData
            | ButtonsData
            | ActionData
            | SpinnerData
            | DatePickerData
            | SliderData
            | TableData
            | ContainerData
            | ColumnsData
            | BarChartData
            | LineChartData
            | InputRequestData
            | ExitEventData
        ),
        message_type: str,
    ) -> OutputEvent:
        """Create a block event (for factory methods)."""
        return create_event(
            block_type=self.block_type,
            block_id=self._generate_block_id(),
            data=data,
            message_type=message_type,
            chunk_id=1,  # Block events are always single chunks
        )


__all__ = ["_BlockFactory", "_StreamHandle"]
