from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum, auto
from typing import Optional, Dict, List
import logging

logger = logging.getLogger(__name__)

class PositionStatus(Enum):
    OPEN = auto()
    CLOSED = auto()
    STOPPED = auto()
    TAKEN = auto()

class PositionSide(Enum):
    LONG = 'BUY'
    SHORT = 'SELL'

@dataclass
class Position:
    id: str
    instrument: str
    timeframe: str
    side: PositionSide
    entry_price: float
    size: float
    stop_loss: float
    take_profit: float
    atr_at_entry: float
    risk_amount: float
    opened_at: datetime
    status: PositionStatus = PositionStatus.OPEN
    trail_activated: bool = False
    highest_price: float = field(init=False)
    lowest_price: float = field(init=False)
    exit_price: Optional[float] = None
    exit_time: Optional[datetime] = None
    exit_reason: Optional[str] = None
    pnl: float = 0.0
    entry_bar_idx: int = -1
    wave_progress_pct: float = 0.0

    def __post_init__(self):
        if self.side == PositionSide.LONG:
            self.highest_price = self.entry_price
            self.lowest_price = float('inf')
        else:
            self.highest_price = float('-inf')
            self.lowest_price = self.entry_price

    def update_extremes(self, high: float, low: float):
        if self.side == PositionSide.LONG:
            self.highest_price = max(self.highest_price, high)
        else:
            self.lowest_price = min(self.lowest_price, low)

    def to_dict(self) -> Dict:
        return {
            'id': self.id, 'instrument': self.instrument, 'timeframe': self.timeframe,
            'side': self.side.value, 'entry_price': self.entry_price, 'size': self.size,
            'stop_loss': self.stop_loss, 'take_profit': self.take_profit,
            'atr_at_entry': self.atr_at_entry, 'risk_amount': self.risk_amount,
            'opened_at': self.opened_at.isoformat(), 'status': self.status.name,
            'trail_activated': self.trail_activated, 'pnl': self.pnl, 'exit_reason': self.exit_reason
        }

class PositionManager:
    def __init__(self, config):
        self.config = config
        self.positions: Dict[str, Position] = {}
        self.closed_positions: List[Position] = []

    def add_position(self, position: Position):
        self.positions[position.id] = position
        logger.info(f"📊 Позиция: {position.id} {position.side.value} {position.instrument} @ {position.entry_price}")

    def get_position(self, instrument: str, timeframe: str, side: PositionSide) -> Optional[Position]:
        for pos in self.positions.values():
            if (pos.instrument == instrument and pos.timeframe == timeframe and
                pos.side == side and pos.status == PositionStatus.OPEN):
                return pos
        return None

    def get_open_positions(self) -> List[Position]:
        return [p for p in self.positions.values() if p.status == PositionStatus.OPEN]

    def close_position(self, position: Position, price: float, reason: str, commission: float = 0.0) -> float:
        pnl = (price - position.entry_price) * position.size if position.side == PositionSide.LONG else (position.entry_price - price) * position.size
        pnl -= position.entry_price * position.size * commission * 2
        position.exit_price = price
        position.exit_time = datetime.now()
        position.exit_reason = reason
        position.pnl = pnl
        position.status = PositionStatus.CLOSED
        self.closed_positions.append(position)
        del self.positions[position.id]
        logger.info(f"💰 Закрыто: {position.id} | {reason} | P&L: {pnl:+.2f}")
        return pnl