from __future__ import annotations

from datetime import datetime
from typing import Any

from pydantic import BaseModel, Field


class ApiMeta(BaseModel):
    generated_at: datetime
    query: dict[str, Any] = Field(default_factory=dict)


class ApiEnvelope(BaseModel):
    data: Any
    meta: ApiMeta
    warnings: list[str] = Field(default_factory=list)


class SignalSummary(BaseModel):
    id: str
    name: str
    symbol: str
    family: str | None = None
    description: str
    available_sources: list[str]
    latest_source: str | None = None
    latest_updated_at: datetime | None = None
    latest_quality: str | None = None
    latest_values: dict[str, float | None] = Field(default_factory=dict)


class SignalSeriesPoint(BaseModel):
    ts: datetime
    source: str
    underlying: str | None = None
    dvol: float | None = None
    vol_index_value: float | None = None
    rvvix_14d: float | None = None
    rvvix_30d: float | None = None
    qvvix_30d: float | None = None
    razor_pnl: float | None = None
    razor_vrp: float | None = None
    razor_pnl_zscore: float | None = None
    razor_vrp_zscore: float | None = None
    trade_band: str | None = None
    long_vol_signal: bool | None = None
    short_vol_signal: bool | None = None
    fit_quality: float | None = None
    gap: bool = False
    quality_flag: str | None = None


class SignalSeriesResponse(BaseModel):
    signal_id: str
    symbol: str
    source: str
    points: list[SignalSeriesPoint]
    latest_values: dict[str, float | None] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)


class DatasetSummary(BaseModel):
    id: str
    name: str
    rows: int
    latest_ts: datetime | None = None
    latest_logical_ts: datetime | None = None
    partition_columns: list[str]
    primary_key: list[str]
    schema_columns: list[str]


class DatasetDetail(DatasetSummary):
    sample_partitions: list[dict[str, Any]] = Field(default_factory=list)


class DatasetRowsResponse(BaseModel):
    dataset_id: str
    rows: list[dict[str, Any]]
    limit: int


class RunRecord(BaseModel):
    run_id: str
    logical_ts: datetime
    run_ts: datetime
    dataset: str
    venue: str
    underlying: str
    status: str
    rows_written_raw: int
    rows_written_normalized: int
    error_message: str | None = None
    duration_ms: int


class RunsSummary(BaseModel):
    total_runs: int
    success_count: int
    failed_count: int
    gap_count: int
    skipped_count: int
    latest_logical_ts: datetime | None = None
    latest_run_lag_hours: float | None = None


class SystemHealth(BaseModel):
    status: str
    api_version: str
    data_root: str
    websocket_enabled: bool
    dataset_count: int
    signal_count: int
    latest_signal_update: datetime | None = None
    latest_run_update: datetime | None = None
    db_enabled: bool = False
    db_status: str | None = None


class EngineSummary(BaseModel):
    id: str
    name: str
    status: str
    detail: str


class StreamEvent(BaseModel):
    event: str
    producer: str
    emitted_at: datetime
    data: dict[str, Any]


class OptionsDashboardSummary(BaseModel):
    id: str
    name: str
    family: str
    description: str
    supported_underlyings: list[str]
    latest_updated_at: datetime | None = None
    latest_quality: str | None = None
    latest_values: dict[str, Any] = Field(default_factory=dict)


class OptionsSeriesPoint(BaseModel):
    ts: datetime
    underlying: str | None = None
    pair_id: str | None = None
    tenor: str | None = None
    tenor_bucket: str | None = None
    moneyness_bucket: str | None = None
    expiry_bucket: str | None = None
    strike_bucket: str | None = None
    values: dict[str, Any] = Field(default_factory=dict)
    quality_flag: str | None = None


class OptionsDashboardResponse(BaseModel):
    dashboard_id: str
    underlying: str | None = None
    points: list[OptionsSeriesPoint]
    latest_values: dict[str, Any] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)


class OptionsSignalSummary(BaseModel):
    id: str
    name: str
    description: str
    supported_underlyings: list[str]
    latest_updated_at: datetime | None = None
    latest_quality: str | None = None
    latest_values: dict[str, Any] = Field(default_factory=dict)


class OptionsSignalSeriesResponse(BaseModel):
    signal_id: str
    underlying: str
    points: list[OptionsSeriesPoint]
    latest_values: dict[str, Any] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)


class PerpsDashboardSummary(BaseModel):
    id: str
    name: str
    family: str
    description: str
    supported_assets: list[str]
    supported_venue_scopes: list[str]
    latest_updated_at: datetime | None = None
    latest_quality: str | None = None
    latest_values: dict[str, Any] = Field(default_factory=dict)


class PerpsSeriesPoint(BaseModel):
    ts: datetime
    asset: str | None = None
    venue_scope: str | None = None
    values: dict[str, Any] = Field(default_factory=dict)
    quality_flag: str | None = None


class PerpsDashboardResponse(BaseModel):
    dashboard_id: str
    asset: str
    venue_scope: str
    points: list[PerpsSeriesPoint]
    latest_values: dict[str, Any] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)


class PerpsSignalSummary(BaseModel):
    id: str
    name: str
    description: str
    supported_assets: list[str]
    supported_venue_scopes: list[str]
    latest_updated_at: datetime | None = None
    latest_quality: str | None = None
    latest_values: dict[str, Any] = Field(default_factory=dict)


class PerpsSignalSeriesResponse(BaseModel):
    signal_id: str
    asset: str
    venue_scope: str
    points: list[PerpsSeriesPoint]
    latest_values: dict[str, Any] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)


class CompositeSignalSummary(BaseModel):
    id: str
    name: str
    description: str
    scope: str
    asset: str
    latest_updated_at: datetime | None = None
    latest_quality: str | None = None
    latest_values: dict[str, Any] = Field(default_factory=dict)


class CompositeSeriesPoint(BaseModel):
    ts: datetime
    scope: str
    asset: str
    values: dict[str, Any] = Field(default_factory=dict)
    quality_flag: str | None = None


class CompositeSignalSeriesResponse(BaseModel):
    signal_id: str
    scope: str
    asset: str
    points: list[CompositeSeriesPoint]
    latest_values: dict[str, Any] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)


class CompositeComponentRecord(BaseModel):
    ts: datetime
    scope: str
    asset: str
    pillar: str
    family: str
    component: str
    raw_value: float | None = None
    normalized_value: float | None = None
    component_weight: float | None = None
    pillar_score: float | None = None
    pillar_weight: float | None = None
    signed_contribution: float | None = None
    quality_flag: str | None = None


class CompositeDecompositionResponse(BaseModel):
    signal_id: str
    scope: str
    asset: str
    records: list[CompositeComponentRecord]
    latest_contributors: list[CompositeComponentRecord] = Field(default_factory=list)
    context: dict[str, Any] = Field(default_factory=dict)


class CompositeTransitionRecord(BaseModel):
    ts: datetime
    scope: str
    asset: str
    index_type: str
    current_regime: str | None = None
    prior_regime: str | None = None
    stay_probability: float | None = None
    upshift_probability: float | None = None
    downshift_probability: float | None = None
    median_regime_duration_hours: float | None = None
    quality_flag: str | None = None


class CompositeTransitionResponse(BaseModel):
    signal_id: str
    scope: str
    asset: str
    records: list[CompositeTransitionRecord]
    context: dict[str, Any] = Field(default_factory=dict)


class MicrostructureSignalSummary(BaseModel):
    id: str
    name: str
    asset: str
    horizon: str
    description: str
    latest_updated_at: datetime | None = None
    latest_quality: str | None = None
    latest_values: dict[str, Any] = Field(default_factory=dict)


class MicrostructureSeriesPoint(BaseModel):
    ts: datetime
    asset: str
    horizon: str
    signal_state: str | None = None
    paper_position: str | None = None
    regime_state: str | None = None
    prob_down: float | None = None
    prob_flat: float | None = None
    prob_up: float | None = None
    expected_move_bps: float | None = None
    expected_edge_bps: float | None = None
    tradability_score: float | None = None
    confidence: float | None = None
    confidence_bucket: str | None = None
    blocked_reason: str | None = None
    model_family: str | None = None
    quality_flag: str | None = None
    values: dict[str, Any] = Field(default_factory=dict)


class MicrostructureSignalSeriesResponse(BaseModel):
    signal_id: str
    asset: str
    horizon: str
    points: list[MicrostructureSeriesPoint]
    latest_values: dict[str, Any] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)


class MicrostructureFeatureResponse(BaseModel):
    asset: str
    horizon: str
    points: list[MicrostructureSeriesPoint]
    latest_values: dict[str, Any] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)


class MicrostructureRegimeResponse(BaseModel):
    asset: str
    points: list[MicrostructureSeriesPoint]
    latest_values: dict[str, Any] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)


class MicrostructureHealth(BaseModel):
    status: str
    engine_status: str
    last_feature_ts: datetime | None = None
    last_prediction_ts: datetime | None = None
    last_training_ts: datetime | None = None
    last_backtest_ts: datetime | None = None
    signals_available: int


class PriceSummary(BaseModel):
    asset: str
    mid_price: float | None = None
    best_bid: float | None = None
    best_ask: float | None = None
    spread_bps: float | None = None
    venue: str | None = None
    ts: datetime | None = None


class PriceCandlePoint(BaseModel):
    ts: datetime
    asset: str
    venue_scope: str
    timeframe: str
    open: float | None = None
    high: float | None = None
    low: float | None = None
    close: float | None = None
    volume: float | None = None
    trade_count: int | None = None


class PriceSeriesResponse(BaseModel):
    asset: str
    venue_scope: str
    timeframe: str
    points: list[PriceCandlePoint]
    latest_values: dict[str, Any] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)


class ExecutionVenueSummary(BaseModel):
    venue: str
    supported_instrument_types: list[str]
    supported_order_types: list[str]
    supports_post_only: bool
    supports_reduce_only: bool
    supports_amend: bool
    supports_mass_cancel: bool
    supports_private_ws: bool
    supports_quote_routing: bool


class ExecutionAccountSummary(BaseModel):
    label: str
    venue: str
    environment: str
    wallet_address: str | None = None
    enabled_assets: list[str]
    enabled_symbols: list[str]
    max_order_notional_usd: float
    max_position_notional_usd: float
    enabled: bool
    kill_switch: bool


class ExecutionMarketSummary(BaseModel):
    ts: datetime
    venue: str
    asset: str
    symbol: str
    instrument_type: str
    status: str
    tick_size: float | None = None
    step_size: float | None = None
    min_size: float | None = None
    min_notional: float | None = None
    best_bid: float | None = None
    best_ask: float | None = None
    mark_price: float | None = None
    index_price: float | None = None
    quality_flag: str | None = None


class ExecutionOrderRecord(BaseModel):
    ts: datetime
    request_id: str
    venue_order_id: str | None = None
    client_order_id: str | None = None
    venue: str
    account: str
    asset: str | None = None
    symbol: str | None = None
    event_type: str
    status: str
    side: str | None = None
    order_type: str | None = None
    time_in_force: str | None = None
    price: float | None = None
    size: float | None = None
    remaining_size: float | None = None
    filled_size: float | None = None
    avg_fill_price: float | None = None
    reason: str | None = None
    quality_flag: str | None = None


class ExecutionFillRecord(BaseModel):
    ts: datetime
    fill_id: str
    request_id: str | None = None
    venue_order_id: str | None = None
    venue: str
    account: str
    asset: str
    symbol: str
    side: str
    price: float | None = None
    size: float | None = None
    fee: float | None = None
    fee_asset: str | None = None
    liquidity: str | None = None
    quality_flag: str | None = None


class ExecutionPositionRecord(BaseModel):
    ts: datetime
    venue: str
    account: str
    asset: str
    symbol: str
    instrument_type: str
    position_side: str | None = None
    quantity: float | None = None
    entry_price: float | None = None
    mark_price: float | None = None
    unrealized_pnl: float | None = None
    realized_pnl: float | None = None
    notional_usd: float | None = None
    leverage: float | None = None
    margin_mode: str | None = None
    quality_flag: str | None = None


class ExecutionBalanceRecord(BaseModel):
    ts: datetime
    venue: str
    account: str
    asset: str
    balance_type: str
    total: float | None = None
    available: float | None = None
    locked: float | None = None
    quality_flag: str | None = None


class ExecutionHealthRecord(BaseModel):
    ts: datetime | None = None
    venue: str
    account: str
    status: str
    ws_connected: bool
    private_ws_connected: bool
    last_heartbeat_ms: int | None = None
    latency_ms: int | None = None
    last_error: str | None = None
    reconnect_count: int = 0
    quality_flag: str | None = None


class ExecutionActionResponse(BaseModel):
    request_id: str
    venue: str
    account: str
    status: str
    mode: str
    message: str
    venue_order_id: str | None = None
    quote_id: str | None = None
    failure_code: str | None = None
    payload: dict[str, Any] = Field(default_factory=dict)
    emitted_at: datetime
