"""
Pairs Trading NautilusTrader strategy.

BTC/ETH ratio Z-score mean reversion. Computes the rolling ratio spread
between BTC and ETH prices and enters when Z-score exceeds threshold.

Entry: Z-score < -1.5 (buy ETH relative to BTC) or Z-score > 1.5 (sell ETH)
Exit:  Z-score reverts to 0 or crossing signal in opposite direction

This is the #1 performing live strategy (67% win rate, +$0.74).
"""
from __future__ import annotations

import logging
import math
from collections import deque

import numpy as np

from nautilus_trader.model.data import Bar
from nautilus_trader.model.enums import OrderSide

from framework.base_strategy import BaseHlStrategy
from framework.config import StrategyConfig

logger = logging.getLogger(__name__)


class PairsTradingNT(BaseHlStrategy):
    """BTC/ETH pairs trading with Z-score entry/exit rules."""

    def __init__(self, config: StrategyConfig):
        super().__init__(config)

        # Ratio tracking
        self._btc_prices: deque[float] = deque(maxlen=100)
        self._eth_prices: deque[float] = deque(maxlen=100)
        self._ratios: deque[float] = deque(maxlen=100)

        # Configurable params
        self._z_entry = config.params.get("z_entry", 1.5)
        self._z_exit = config.params.get("z_exit", 0.5)
        self._lookback = config.params.get("lookback", 20)

        # State
        self._in_trade = False
        self._trade_direction: str | None = None  # "long_eth" or "short_eth"

    def on_bar(self, bar: Bar):
        """Track both BTC and ETH prices. Signal on ETH bars."""
        symbol = str(bar.bar_type.instrument_id.symbol) if hasattr(bar, 'bar_type') else ""
        price = float(bar.close)

        if "BTC" in symbol.upper():
            self._btc_prices.append(price)
        elif "ETH" in symbol.upper():
            self._eth_prices.append(price)
            self._check_signal()

    def compute_signal(self, price: float | None = None) -> dict | None:
        """Alternative: compute signal from price feed (for paper trading)."""
        if price is not None:
            self._eth_prices.append(price)
            # Use last known BTC price from cached data
            if not self._btc_prices:
                return None
        return self._check_signal()

    def _check_signal(self) -> dict | None:
        if len(self._btc_prices) < self._lookback or len(self._eth_prices) < self._lookback:
            return None

        btc_list = list(self._btc_prices)
        eth_list = list(self._eth_prices)

        # Align BTC/ETH on common window
        ratios = []
        for i in range(-min(len(btc_list), len(eth_list)), 0):
            if eth_list[i] > 0:
                ratios.append(btc_list[i] / eth_list[i])

        if len(ratios) < self._lookback:
            return None

        self._ratios.append(ratios[-1])

        recent = ratios[-self._lookback:]
        mu = np.mean(recent)
        std = np.std(recent, ddof=1)
        if std <= 0:
            return None

        z = (ratios[-1] - mu) / std

        # Exit logic
        if self._in_trade:
            # Exit when Z-score reverts toward zero
            if abs(z) < self._z_exit:
                self._in_trade = False
                sig = "BUY_ETH" if self._trade_direction == "short_eth" else "SELL_ETH"
                self._trade_direction = None
                return {"signal": sig, "strength": abs(z), "reason": "exit_reversion"}

            # Exit on crossing
            if self._trade_direction == "long_eth" and z > self._z_entry:
                self._in_trade = False
                self._trade_direction = None
                return {"signal": "SELL_ETH", "strength": abs(z), "reason": "exit_crossing"}
            elif self._trade_direction == "short_eth" and z < -self._z_entry:
                self._in_trade = False
                self._trade_direction = None
                return {"signal": "BUY_ETH", "strength": abs(z), "reason": "exit_crossing"}
            return None

        # Entry logic
        if z < -self._z_entry:
            # BTC/ETH ratio is low → ETH is relatively expensive → buy ETH vs BTC
            self._in_trade = True
            self._trade_direction = "long_eth"
            return {"signal": "BUY_ETH", "strength": abs(z) / self._z_entry, "z_score": round(z, 3), "reason": "entry_zscore"}

        if z > self._z_entry:
            # BTC/ETH ratio is high → ETH is relatively cheap → sell ETH vs BTC
            self._in_trade = True
            self._trade_direction = "short_eth"
            return {"signal": "SELL_ETH", "strength": abs(z) / self._z_entry, "z_score": round(z, 3), "reason": "entry_zscore"}

        return None

    def handle_signal(self, signal: dict):
        side_str = signal["signal"]
        if "BUY" in side_str:
            self._submit_order(OrderSide.BUY)
        elif "SELL" in side_str:
            self._submit_order(OrderSide.SELL)
