from dataclasses import dataclass, field
from datetime import datetime, timedelta
from typing import Optional, List
from decimal import Decimal
from enum import Enum
import uuid


class TransactionType(Enum):
    REAL_TRADE = "real_trade"      # Реальная сделка
    ORDER_CANCEL = "order_cancel"  # Отмена ордера  
    AMOUNT_INCREASE = "amount_increase"  # Пополнение мерчантом


@dataclass
class DVariable:
    """D variable for tracking order changes"""
    
    id: str
    merchant_id: str
    asset: str
    fiat: str
    trade_type: str
    amount: Decimal
    timestamp: datetime
    expires_at: datetime
    is_matched: bool = False
    matched_with: Optional[str] = None
    # Staged confirmation fields
    confirmation_stage: int = 0  # 0..4, where 4 = fully confirmed
    last_confirmation_at: Optional[datetime] = None
    # Enrichment for confirmation
    price_at_d1: float = 0.0
    merchant_name: str = ""
    
    def is_expired(self) -> bool:
        """Check if D variable has expired (30 minutes)"""
        return datetime.now() > self.expires_at
    
    def matches_cancellation(self, other_amount: Decimal) -> bool:
        """Check if this D variable matches a cancellation (Dn = -D1)"""
        return abs(self.amount + other_amount) < Decimal('0.01')  # Small tolerance for floating point


@dataclass
class LiquidityEvent:
    """Liquidity tracking event"""
    
    event_id: str
    merchant_id: str
    asset: str
    order_id: str
    amount_change: Decimal
    transaction_type: TransactionType
    timestamp: datetime
    d_variable_id: Optional[str] = None
    is_confirmed: bool = False
    
    def __post_init__(self):
        if self.amount_change < 0:
            # Negative change - potential real trade
            self.transaction_type = TransactionType.REAL_TRADE
        elif self.amount_change > 0:
            # Positive change - potential merchant top-up
            self.transaction_type = TransactionType.AMOUNT_INCREASE
    
    def confirm_as_real_trade(self) -> None:
        """Confirm this event as a real trade"""
        self.is_confirmed = True
        self.transaction_type = TransactionType.REAL_TRADE
    
    def mark_as_cancellation(self) -> None:
        """Mark this event as order cancellation"""
        self.transaction_type = TransactionType.ORDER_CANCEL


@dataclass
class IndividualTransaction:
    """Индивидуальная транзакция мерчанта"""
    
    transaction_id: str = field(default_factory=lambda: str(uuid.uuid4()))
    merchant_id: str = ""
    merchant_name: str = ""
    asset: str = ""
    fiat: str = ""
    transaction_type: str = ""  # "real_trade", "top_up", "order_cancellation"
    amount: float = 0.0
    price: float = 0.0
    timestamp: datetime = field(default_factory=datetime.now)
    volume_before: float = 0.0
    volume_after: float = 0.0
    trade_type: str = ""  # "BUY" или "SELL"
    
    def to_dict(self) -> dict:
        """Конвертация в словарь для JSON сериализации"""
        return {
            "transaction_id": self.transaction_id,
            "merchant_id": self.merchant_id,
            "merchant_name": self.merchant_name,
            "asset": self.asset,
            "fiat": self.fiat,
            "transaction_type": self.transaction_type,
            "amount": self.amount,
            "price": self.price,
            "timestamp": self.timestamp.isoformat(),
            "volume_before": self.volume_before,
            "volume_after": self.volume_after,
            "trade_type": self.trade_type
        }


@dataclass
class MerchantLiquidityStats:
    """Liquidity statistics for a merchant"""
    
    merchant_id: str
    merchant_name: str = ""
    asset: str = ""
    total_volume: Decimal = Decimal('0')
    real_trades_count: int = 0
    real_trades_volume: float = 0.0
    order_cancellations_count: int = 0
    order_cancellations_volume: float = 0.0
    top_ups_count: int = 0
    top_ups_volume: float = 0.0
    last_activity: Optional[datetime] = None
    active_d_variables: List[DVariable] = field(default_factory=list)
    # Новые поля для хранения индивидуальных транзакций
    individual_trades: List[IndividualTransaction] = field(default_factory=list)
    individual_top_ups: List[IndividualTransaction] = field(default_factory=list)
    individual_cancellations: List[IndividualTransaction] = field(default_factory=list)
    
    def __post_init__(self):
        if self.active_d_variables is None:
            self.active_d_variables = []
        if self.individual_trades is None:
            self.individual_trades = []
        if self.individual_top_ups is None:
            self.individual_top_ups = []
        if self.individual_cancellations is None:
            self.individual_cancellations = []
    
    def add_confirmed_trade(self, transaction: IndividualTransaction) -> None:
        """Add confirmed trade to statistics"""
        self.total_volume += Decimal(str(abs(transaction.amount)))
        self.real_trades_count += 1
        self.real_trades_volume += abs(transaction.amount)
        self.last_activity = datetime.now()
        self.individual_trades.append(transaction)
    
    def add_cancelled_order(self, transaction: IndividualTransaction) -> None:
        """Add cancelled order to statistics"""
        self.order_cancellations_count += 1
        self.order_cancellations_volume += abs(transaction.amount)
        self.last_activity = datetime.now()
        self.individual_cancellations.append(transaction)
    
    def add_merchant_topup(self, transaction: IndividualTransaction) -> None:
        """Add merchant topup to statistics"""
        self.top_ups_count += 1
        self.top_ups_volume += abs(transaction.amount)
        self.last_activity = datetime.now()
        self.individual_top_ups.append(transaction)
    
    def cleanup_expired_d_variables(self) -> None:
        """Remove expired D variables"""
        current_time = datetime.now()
        self.active_d_variables = [
            d_var for d_var in self.active_d_variables 
            if not d_var.is_expired()
        ] 