from __future__ import annotations

from collections.abc import AsyncIterator
from datetime import datetime
from typing import Protocol

from uforia.api.models import (
    CompositeDecompositionResponse,
    CompositeSignalSeriesResponse,
    CompositeSignalSummary,
    CompositeTransitionResponse,
    DatasetDetail,
    DatasetRowsResponse,
    DatasetSummary,
    EngineSummary,
    ExecutionAccountSummary,
    ExecutionActionResponse,
    ExecutionBalanceRecord,
    ExecutionFillRecord,
    ExecutionHealthRecord,
    ExecutionMarketSummary,
    ExecutionOrderRecord,
    ExecutionPositionRecord,
    ExecutionVenueSummary,
    MicrostructureFeatureResponse,
    MicrostructureHealth,
    MicrostructureRegimeResponse,
    MicrostructureSignalSeriesResponse,
    MicrostructureSignalSummary,
    OptionsDashboardResponse,
    OptionsDashboardSummary,
    OptionsSignalSeriesResponse,
    OptionsSignalSummary,
    PerpsDashboardResponse,
    PerpsDashboardSummary,
    PerpsSignalSeriesResponse,
    PerpsSignalSummary,
    RunRecord,
    RunsSummary,
    SignalSeriesResponse,
    SignalSummary,
    StreamEvent,
    SystemHealth,
)


class SignalProvider(Protocol):
    def list_signals(self) -> list[SignalSummary]: ...
    def get_latest(self, signal_id: str, source: str | None = None) -> SignalSummary: ...
    def get_series(
        self,
        signal_id: str,
        *,
        source: str,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
    ) -> SignalSeriesResponse: ...


class DatasetProvider(Protocol):
    def list_datasets(self) -> list[DatasetSummary]: ...
    def get_dataset(self, dataset_id: str) -> DatasetDetail: ...
    def get_rows(
        self,
        dataset_id: str,
        *,
        source: str | None,
        symbol: str | None,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
        limit: int,
    ) -> DatasetRowsResponse: ...


class RunStatusProvider(Protocol):
    def list_runs(
        self,
        *,
        start: datetime | None,
        end: datetime | None,
        limit: int,
        quality: str | None,
    ) -> list[RunRecord]: ...
    def get_summary(self) -> RunsSummary: ...
    def list_engines(self) -> list[EngineSummary]: ...
    def get_health(self) -> SystemHealth: ...


class StreamProvider(Protocol):
    async def stream(self) -> AsyncIterator[StreamEvent]: ...


class OptionsDashboardProvider(Protocol):
    def list_dashboards(self) -> list[OptionsDashboardSummary]: ...
    def get_latest(
        self,
        dashboard_id: str,
        *,
        underlying: str | None,
    ) -> OptionsDashboardSummary: ...
    def get_series(
        self,
        dashboard_id: str,
        *,
        underlying: str | None,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
        max_points: int | None,
    ) -> OptionsDashboardResponse: ...


class OptionsSignalProvider(Protocol):
    def list_signals(self) -> list[OptionsSignalSummary]: ...
    def get_latest(self, signal_id: str, *, underlying: str) -> OptionsSignalSummary: ...
    def get_series(
        self,
        signal_id: str,
        *,
        underlying: str,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
        max_points: int | None,
    ) -> OptionsSignalSeriesResponse: ...


class PerpsDashboardProvider(Protocol):
    def list_dashboards(self) -> list[PerpsDashboardSummary]: ...
    def get_latest(
        self,
        dashboard_id: str,
        *,
        asset: str,
        venue_scope: str,
    ) -> PerpsDashboardSummary: ...
    def get_series(
        self,
        dashboard_id: str,
        *,
        asset: str,
        venue_scope: str,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
        max_points: int | None,
    ) -> PerpsDashboardResponse: ...


class PerpsSignalProvider(Protocol):
    def list_signals(self) -> list[PerpsSignalSummary]: ...
    def get_latest(self, signal_id: str, *, asset: str, venue_scope: str) -> PerpsSignalSummary: ...
    def get_series(
        self,
        signal_id: str,
        *,
        asset: str,
        venue_scope: str,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
        max_points: int | None,
    ) -> PerpsSignalSeriesResponse: ...


class CompositeProvider(Protocol):
    def list_signals(self) -> list[CompositeSignalSummary]: ...
    def get_latest(self, signal_id: str) -> CompositeSignalSummary: ...
    def get_series(
        self,
        signal_id: str,
        *,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
        max_points: int | None,
    ) -> CompositeSignalSeriesResponse: ...
    def get_decomposition(
        self,
        signal_id: str,
        *,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
        max_points: int | None,
    ) -> CompositeDecompositionResponse: ...
    def get_transitions(
        self,
        signal_id: str,
        *,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
        max_points: int | None,
    ) -> CompositeTransitionResponse: ...


class MicrostructureProvider(Protocol):
    def list_signals(self) -> list[MicrostructureSignalSummary]: ...
    def get_latest(self, signal_id: str) -> MicrostructureSignalSummary: ...
    def get_series(
        self,
        signal_id: str,
        *,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
    ) -> MicrostructureSignalSeriesResponse: ...
    def get_features(
        self,
        asset: str,
        *,
        horizon: str,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
        max_points: int | None,
    ) -> MicrostructureFeatureResponse: ...
    def get_regime(
        self,
        asset: str,
        *,
        start: datetime | None,
        end: datetime | None,
        quality: str | None,
        max_points: int | None,
    ) -> MicrostructureRegimeResponse: ...
    def get_health(self) -> MicrostructureHealth: ...


class ExecutionProvider(Protocol):
    def list_venues(self) -> list[ExecutionVenueSummary]: ...
    def list_markets(
        self,
        *,
        venue: str | None,
        asset: str | None,
    ) -> list[ExecutionMarketSummary]: ...
    def list_accounts(self) -> list[ExecutionAccountSummary]: ...
    def list_orders(
        self,
        *,
        venue: str | None,
        account: str | None,
        asset: str | None,
        status: str | None,
        limit: int,
    ) -> list[ExecutionOrderRecord]: ...
    def list_fills(
        self,
        *,
        venue: str | None,
        account: str | None,
        asset: str | None,
        limit: int,
    ) -> list[ExecutionFillRecord]: ...
    def list_positions(
        self,
        *,
        venue: str | None,
        account: str | None,
        asset: str | None,
    ) -> list[ExecutionPositionRecord]: ...
    def list_balances(
        self,
        *,
        venue: str | None,
        account: str | None,
    ) -> list[ExecutionBalanceRecord]: ...
    def get_health(self) -> list[ExecutionHealthRecord]: ...
    def request_quote(self, request: object) -> ExecutionActionResponse: ...
    def place_order(self, request: object) -> ExecutionActionResponse: ...
    def cancel(self, request: object) -> ExecutionActionResponse: ...
    def cancel_all(self, request: object) -> ExecutionActionResponse: ...
