from __future__ import annotations

import datetime as dt
from typing import Any, Callable, Iterable

from nexuscore.core.message import Event, Request, Response
from nexuscore.core.uuid import UUID4
from nexuscore.model.identifiers import TraderId
from nexuscore.serialization.base import Serializer


class Clock:
    @property
    def timer_names(self) -> list[str]: ...
    @property
    def timer_count(self) -> int: ...
    def timestamp(self) -> float: ...
    def timestamp_ms(self) -> int: ...
    def timestamp_us(self) -> int: ...
    def timestamp_ns(self) -> int: ...
    def utc_now(self) -> dt.datetime: ...
    def local_now(self, tz: dt.tzinfo | None = ...) -> dt.datetime: ...
    def register_default_handler(self, handler: Callable[[TimeEvent], None]) -> None: ...
    def next_time_ns(self, name: str) -> int: ...
    def set_time_alert(
        self,
        name: str,
        alert_time: dt.datetime | int,
        callback: Callable[[TimeEvent], None] | None = ...,
        override: bool = ...,
        allow_past: bool = ...,
    ) -> None: ...
    def set_time_alert_ns(
        self,
        name: str,
        alert_time_ns: int,
        callback: Callable[[TimeEvent], None] | None = ...,
        allow_past: bool = ...,
    ) -> None: ...
    def set_timer(
        self,
        name: str,
        interval: dt.timedelta,
        start_time: dt.datetime | None = ...,
        stop_time: dt.datetime | None = ...,
        callback: Callable[[TimeEvent], None] | None = ...,
        allow_past: bool = ...,
        fire_immediately: bool = ...,
    ) -> None: ...
    def set_timer_ns(
        self,
        name: str,
        interval_ns: int,
        start_time_ns: int,
        stop_time_ns: int,
        callback: Callable[[TimeEvent], None] | None = ...,
        allow_past: bool = ...,
        fire_immediately: bool = ...,
    ) -> None: ...
    def cancel_timer(self, name: str) -> None: ...
    def cancel_timers(self) -> None: ...


def register_component_clock(instance_id: UUID4, clock: Clock) -> None: ...
def deregister_component_clock(instance_id: UUID4, clock: Clock) -> None: ...
def remove_instance_component_clocks(instance_id: UUID4) -> None: ...
def set_backtest_force_stop(value: bool) -> None: ...
def is_backtest_force_stop() -> bool: ...


class TestClock(Clock):
    def __init__(self) -> None: ...
    def set_time(self, to_time_ns: int) -> None: ...
    def advance_time(self, to_time_ns: int, set_time: bool = ...) -> list[TimeEventHandler]: ...


class LiveClock(Clock):
    def __init__(self) -> None: ...


class TimeEvent(Event):
    def __init__(self, name: str, event_id: UUID4, ts_event: int, ts_init: int) -> None: ...
    @property
    def name(self) -> str: ...
    @property
    def id(self) -> UUID4: ...
    @property
    def ts_event(self) -> int: ...
    @property
    def ts_init(self) -> int: ...


class TimeEventHandler:
    event: TimeEvent
    def __init__(self, event: TimeEvent, handler: Callable[[TimeEvent], None]) -> None: ...
    def handle(self) -> None: ...


class MessageBus:
    def __init__(
        self,
        trader_id: TraderId,
        clock: Clock,
        instance_id: UUID4 | None = ...,
        name: str | None = ...,
        serializer: Serializer | None = ...,
        config: Any | None = ...,
    ) -> None: ...
    def endpoints(self) -> list[str]: ...
    def topics(self) -> list[str]: ...
    def subscriptions(self, pattern: str | None = ...) -> list[Subscription]: ...
    def streaming_types(self) -> set[type]: ...
    def has_subscribers(self, pattern: str | None = ...) -> bool: ...
    def is_subscribed(self, topic: str, handler: Callable[[Any], None]) -> bool: ...
    def is_pending_request(self, request_id: UUID4) -> bool: ...
    def is_streaming_type(self, cls: type) -> bool: ...
    def dispose(self) -> None: ...
    def register(self, endpoint: str, handler: Callable[[Any], None]) -> None: ...
    def deregister(self, endpoint: str, handler: Callable[[Any], None]) -> None: ...
    def add_streaming_type(self, cls: type) -> None: ...
    def send(self, endpoint: str, msg: Any) -> None: ...
    def request(self, endpoint: str, request: Request) -> None: ...
    def response(self, response: Response) -> None: ...
    def subscribe(self, topic: str, handler: Callable[[Any], None], priority: int = ...) -> None: ...
    def unsubscribe(self, topic: str, handler: Callable[[Any], None]) -> None: ...
    def publish(self, topic: str, msg: Any, external_pub: bool = ...) -> None: ...


def is_matching_py(topic: str, pattern: str) -> bool: ...


class Subscription:
    topic: str
    handler: Callable[[Any], None]
    priority: int
    def __init__(self, topic: str, handler: Callable[[Any], None], priority: int = ...) -> None: ...
