from __future__ import annotations

from typing import Any, Iterable


class Callback:
    """Minimal training callback interface."""

    def __init__(self) -> None:
        self.model = None
        self.stop_training = False

    def set_model(self, model: Any) -> None:
        self.model = model

    def set_context(self, **context: Any) -> None:
        self.context = context

    def on_train_begin(self, logs: dict[str, Any] | None = None) -> None:
        pass

    def on_epoch_begin(self, epoch: int, logs: dict[str, Any] | None = None) -> None:
        pass

    def on_epoch_end(self, epoch: int, logs: dict[str, Any] | None = None) -> None:
        pass

    def on_train_end(self, logs: dict[str, Any] | None = None) -> None:
        pass


class CallbackList:
    """Thin wrapper that dispatches callback hooks safely in order."""

    def __init__(self, callbacks: Iterable[Callback] | None = None) -> None:
        self.callbacks = list(callbacks or [])

    @property
    def stop_training(self) -> bool:
        return any(bool(getattr(cb, "stop_training", False)) for cb in self.callbacks)

    def set_model(self, model: Any) -> None:
        for cb in self.callbacks:
            cb.set_model(model)

    def set_context(self, **context: Any) -> None:
        for cb in self.callbacks:
            cb.set_context(**context)

    def on_train_begin(self, logs: dict[str, Any] | None = None) -> None:
        for cb in self.callbacks:
            cb.on_train_begin(logs=logs)

    def on_epoch_begin(self, epoch: int, logs: dict[str, Any] | None = None) -> None:
        for cb in self.callbacks:
            cb.on_epoch_begin(epoch, logs=logs)

    def on_epoch_end(self, epoch: int, logs: dict[str, Any] | None = None) -> None:
        for cb in self.callbacks:
            cb.on_epoch_end(epoch, logs=logs)

    def on_train_end(self, logs: dict[str, Any] | None = None) -> None:
        for cb in self.callbacks:
            cb.on_train_end(logs=logs)

