# app/src/trading/execution/calculations.py

from __future__ import annotations

from datetime import datetime
from typing import Protocol

from src.core.types import NumericLike
from src.trading.position.state import PositionState
from src.trading.execution.position_metrics import build_position_metrics


class _ExecutionCalculationsProtocol(Protocol):
    _position: PositionState


class ExecutionCalculationsMixin(_ExecutionCalculationsProtocol):
    # Единая точка расчёта движения цены позиции.
    # Вся логика вынесена в position_metrics.py,
    # чтобы LONG/SHORT считались одинаково во всех частях execution.
    def _calculate_price_move_percent(
        self,
        current_price: NumericLike | None,
    ) -> float:
        position = type(self)._position

        metrics = build_position_metrics(
            position,
            current_price=current_price,
        )

        return metrics.price_move_percent

    # Единая точка расчёта итогового PnL.
    # Возвращает net PnL:
    # gross PnL - комиссия вход/выход + overnight cashflow.
    def _calculate_pnl(
        self,
        current_price: NumericLike | None,
    ) -> float:
        position = type(self)._position

        metrics = build_position_metrics(
            position,
            current_price=current_price,
        )

        return metrics.net_pnl_usd

    # Gross PnL без комиссии и overnight.
    # Оставляем метод как совместимый wrapper,
    # но сам расчёт теперь берётся из position_metrics.py.
    def _calculate_gross_pnl(
        self,
        current_price: NumericLike | None,
    ) -> float:
        position = type(self)._position

        metrics = build_position_metrics(
            position,
            current_price=current_price,
        )

        return metrics.gross_pnl_usd

    # Комиссия вход + предполагаемый выход.
    # Теперь считается централизованно через position_metrics.py.
    def _calculate_round_trip_commission(
        self,
        current_price: NumericLike | None,
    ) -> float:
        position = type(self)._position

        metrics = build_position_metrics(
            position,
            current_price=current_price,
        )

        return metrics.commission_usd

    # Overnight / leverage cashflow.
    # Может быть отрицательным или положительным,
    # зависит от ставки биржи для LONG/SHORT.
    def _calculate_overnight_cashflow(
        self,
        current_price: NumericLike | None,
    ) -> float:
        position = type(self)._position

        metrics = build_position_metrics(
            position,
            current_price=current_price,
        )

        return metrics.overnight_cashflow_usd

    def _now_time(self) -> str:
        return datetime.now().strftime("%H:%M:%S")