import logging

from v20.trade import Trade

from algo.constant import Symbol
from algo.trading import OrderType, TradeResult
from algo.data.common import PricePoint
from algo.trading.oanda import RestApi

log = logging.getLogger(__name__)


class CurrentState:
    def __init__(self) -> None:
        self._in_market = False
        self._open_price: float = 0
        self._order_type: OrderType = None
        self._sl_size: float
        self.is_sl_close: bool = False

    @property
    def in_market(self) -> bool:
        return self._in_market

    @property
    def order_type(self) -> OrderType:
        return self._order_type

    def open(self, price_point: PricePoint, order_type: OrderType, sl_size=None):
        """ sl_size set as negative value to easy further computation"""
        self._in_market = True
        self._order_type = order_type
        self._open_price = price_point.bid
        if sl_size is not None:
            self._sl_size = - 1.0 * sl_size

    def is_sl_time(self, price_point: PricePoint):
        """ SL is negative value"""
        return self.current_profit(price_point) < self._sl_size

    def current_profit(self, price_point: PricePoint) -> float:
        profit = self._open_price - price_point.bid
        if self._order_type != OrderType.SELL:
            profit *= -1
        return profit

    def close(self, price_point: PricePoint) -> TradeResult:
        """ close the trade and return profit"""
        self._in_market = False
        return TradeResult(
            self.current_profit(price_point),
            price_point.ask - price_point.bid
        )

    def __str__(self) -> str:
        return f'<State: order: {self.order_type}, open: {self._open_price}>'


class OandaTradingState(CurrentState):
    def __init__(self, default_symbol: Symbol) -> None:
        super().__init__()
        self._api = RestApi(default_symbol)
        # closing all trades for the case when prev run was interrupted
        self._api.close_all_trades()

    @staticmethod
    def _trade_summary(trade: Trade, price: PricePoint):
        profit = trade.currentUnits / abs(trade.initialUnits) * (price.ask - trade.price)
        return {
            'profit': profit,
            'pprofit': profit * (10 ** 2)
        }

    def debug_state(self, price: PricePoint):
        open_trades = self._api.get_open_trades()
        log.info('current-trades', extra={'trades': [trade.dict() for trade in open_trades]})

        log.info('price-diff', extra={'trades': [self._trade_summary(trade, price) for trade in open_trades]})
        # open_positions = self._api.get_open_positions()
        # log.info('current-positions', extra={'positions': [p.dict() for p in open_positions]})

    def open(self, price_point: PricePoint, order_type: OrderType, sl_size=None):
        self._api.open(order_type)
        return super().open(price_point, order_type, sl_size)

    def close(self, price_point: PricePoint) -> TradeResult:
        self.debug_state(price_point)
        self._api.close_all_trades()
        return super().close(price_point)
