"""Market making strategy models for ZenOTC SDK."""

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, Field


class QuotingStrategy(str, Enum):
    """Quoting strategy types."""
    FIXED_SPREAD = "fixed_spread"
    DYNAMIC_SPREAD = "dynamic_spread"
    INVENTORY_SKEW = "inventory_skew"
    MARKET_ADAPTIVE = "market_adaptive"


class InventoryMode(str, Enum):
    """Inventory management modes."""
    PASSIVE = "passive"
    ACTIVE_REBALANCE = "active_rebalance"
    HEDGE = "hedge"
    LIMIT_AND_ALERT = "limit_and_alert"


class MarketMakerStatus(str, Enum):
    """Market maker status."""
    ACTIVE = "active"
    PAUSED = "paused"
    STOPPED = "stopped"
    ERROR = "error"


class PricingSource(str, Enum):
    """Pricing source types."""
    INTERNAL = "internal"
    EXTERNAL = "external"
    COMPOSITE = "composite"
    BEST_BID_ASK = "best_bid_ask"


class SpreadConfig(BaseModel):
    """Spread configuration."""
    base_spread_bps: float = Field(alias="baseSpreadBps")
    min_spread_bps: float = Field(alias="minSpreadBps")
    max_spread_bps: float = Field(alias="maxSpreadBps")
    volatility_multiplier: Optional[float] = Field(default=None, alias="volatilityMultiplier")
    inventory_skew_factor: Optional[float] = Field(default=None, alias="inventorySkewFactor")
    time_decay_enabled: Optional[bool] = Field(default=None, alias="timeDecayEnabled")

    class Config:
        populate_by_name = True


class QuoteSizeConfig(BaseModel):
    """Quote size configuration."""
    base_size: float = Field(alias="baseSize")
    min_size: float = Field(alias="minSize")
    max_size: float = Field(alias="maxSize")
    size_increment_percent: Optional[float] = Field(default=None, alias="sizeIncrementPercent")
    max_total_exposure: float = Field(alias="maxTotalExposure")

    class Config:
        populate_by_name = True


class InventoryConfig(BaseModel):
    """Inventory configuration."""
    target_position: float = Field(alias="targetPosition")
    max_long_position: float = Field(alias="maxLongPosition")
    max_short_position: float = Field(alias="maxShortPosition")
    rebalance_threshold: float = Field(alias="rebalanceThreshold")
    rebalance_target: float = Field(alias="rebalanceTarget")
    soft_limit_percent: float = Field(alias="softLimitPercent")

    class Config:
        populate_by_name = True


class MMRiskConfig(BaseModel):
    """Market maker risk configuration."""
    max_daily_loss: float = Field(alias="maxDailyLoss")
    max_daily_volume: float = Field(alias="maxDailyVolume")
    max_orders_per_minute: int = Field(alias="maxOrdersPerMinute")
    max_spread_widening: float = Field(alias="maxSpreadWidening")
    stop_on_error: bool = Field(alias="stopOnError")
    max_consecutive_errors: int = Field(alias="maxConsecutiveErrors")

    class Config:
        populate_by_name = True


class PricingConfig(BaseModel):
    """Pricing configuration."""
    source: PricingSource
    external_sources: Optional[List[str]] = Field(default=None, alias="externalSources")
    composite_weights: Optional[Dict[str, float]] = Field(default=None, alias="compositeWeights")
    stale_threshold_ms: int = Field(alias="staleThresholdMs")
    max_deviation_percent: float = Field(alias="maxDeviationPercent")

    class Config:
        populate_by_name = True


class RefreshConfig(BaseModel):
    """Quote refresh configuration."""
    interval_ms: int = Field(alias="intervalMs")
    on_fill_refresh: bool = Field(alias="onFillRefresh")
    on_price_change_refresh: bool = Field(alias="onPriceChangeRefresh")
    price_change_threshold_bps: float = Field(alias="priceChangeThresholdBps")
    jitter_ms: Optional[int] = Field(default=None, alias="jitterMs")

    class Config:
        populate_by_name = True


class MarketMakerState(BaseModel):
    """Current state of a market maker."""
    current_position: str = Field(alias="currentPosition")
    current_pnl: str = Field(alias="currentPnL")
    daily_volume: str = Field(alias="dailyVolume")
    daily_pnl: str = Field(alias="dailyPnL")
    current_bid: Optional[Dict[str, str]] = Field(default=None, alias="currentBid")
    current_ask: Optional[Dict[str, str]] = Field(default=None, alias="currentAsk")

    class Config:
        populate_by_name = True


class MarketMakerMetrics(BaseModel):
    """Performance metrics for a market maker."""
    total_fills: int = Field(alias="totalFills")
    total_volume: str = Field(alias="totalVolume")
    total_pnl: str = Field(alias="totalPnL")
    fill_rate: str = Field(alias="fillRate")
    avg_spread_capture: str = Field(alias="avgSpreadCapture")

    class Config:
        populate_by_name = True


class MarketMaker(BaseModel):
    """Market maker strategy model."""
    id: str
    config_id: str = Field(alias="configId")
    asset: str
    name: Optional[str] = None
    status: MarketMakerStatus
    quoting_strategy: QuotingStrategy = Field(alias="quotingStrategy")
    inventory_mode: InventoryMode = Field(alias="inventoryMode")
    state: MarketMakerState
    metrics: MarketMakerMetrics
    created_at: datetime = Field(alias="createdAt")
    updated_at: datetime = Field(alias="updatedAt")

    class Config:
        populate_by_name = True


class MarketMakerEvent(BaseModel):
    """Market maker event."""
    id: str
    event_type: str = Field(alias="eventType")
    timestamp: datetime
    data: Dict[str, Any]

    class Config:
        populate_by_name = True


class CreateMarketMakerParams(BaseModel):
    """Parameters for creating a market maker."""
    asset: str
    name: Optional[str] = None
    description: Optional[str] = None
    quoting_strategy: QuotingStrategy = Field(alias="quotingStrategy")
    inventory_mode: InventoryMode = Field(alias="inventoryMode")
    spread_config: SpreadConfig = Field(alias="spreadConfig")
    quote_size_config: QuoteSizeConfig = Field(alias="quoteSizeConfig")
    inventory_config: InventoryConfig = Field(alias="inventoryConfig")
    risk_config: MMRiskConfig = Field(alias="riskConfig")
    pricing_config: PricingConfig = Field(alias="pricingConfig")
    refresh_config: RefreshConfig = Field(alias="refreshConfig")
    metadata: Optional[Dict[str, Any]] = None

    class Config:
        populate_by_name = True
