"""Lead-Lag Detection pipeline functions.

Pipeline functions:
    lead_lag_detector - Detect lead-lag relationships across feeds
"""

from __future__ import annotations

from collections import deque
from typing import Any, Callable

from horizon._horizon import cross_correlation_lags
from horizon.context import Context


def lead_lag_detector(
    feeds: list[str],
    max_lag: int = 10,
    window: int = 100,
) -> Callable[[Context], dict[str, Any]]:
    """Create a lead-lag detection pipeline function.

    Monitors cross-correlations across multiple feeds to identify
    which markets lead and which lag.

    Args:
        feeds: List of feed names to monitor.
        max_lag: Maximum lag to test.
        window: Rolling window for correlation estimation.

    Returns:
        Pipeline function: (Context) -> dict with keys:
            leader, lagger, lag, correlation, pairs
    """
    from horizon._horizon import auth_require_pro
    auth_require_pro()

    price_histories: dict[str, deque] = {}

    def _lead_lag_detector(ctx: Context) -> dict[str, Any]:
        for feed in feeds:
            if feed not in price_histories:
                price_histories[feed] = deque(maxlen=window)
            fd = ctx.feeds.get(feed)
            if fd is not None and fd.price > 0:
                price_histories[feed].append(fd.price)

        result = {
            "leader": "",
            "lagger": "",
            "lag": 0,
            "correlation": 0.0,
            "pairs": [],
        }

        # Need enough data
        min_len = min(
            (len(price_histories[f]) for f in feeds if f in price_histories),
            default=0,
        )
        if min_len < max_lag + 5:
            return result

        best_corr = 0.0
        best_pair = ("", "", 0)
        pairs = []

        for i, feed_a in enumerate(feeds):
            for feed_b in feeds[i + 1:]:
                prices_a = list(price_histories[feed_a])[-min_len:]
                prices_b = list(price_histories[feed_b])[-min_len:]

                # Compute returns
                returns_a = [
                    (prices_a[k] - prices_a[k - 1]) / prices_a[k - 1]
                    for k in range(1, len(prices_a))
                    if prices_a[k - 1] > 0
                ]
                returns_b = [
                    (prices_b[k] - prices_b[k - 1]) / prices_b[k - 1]
                    for k in range(1, len(prices_b))
                    if prices_b[k - 1] > 0
                ]

                if len(returns_a) >= max_lag + 3 and len(returns_b) >= max_lag + 3:
                    n = min(len(returns_a), len(returns_b))
                    lags = cross_correlation_lags(
                        returns_a[:n], returns_b[:n], max_lag
                    )

                    # Find strongest cross-correlation
                    for lag_val, corr_val in lags:
                        if abs(corr_val) > abs(best_corr):
                            best_corr = corr_val
                            if lag_val > 0:
                                best_pair = (feed_a, feed_b, lag_val)
                            else:
                                best_pair = (feed_b, feed_a, -lag_val)

                    pairs.append({
                        "feed_a": feed_a,
                        "feed_b": feed_b,
                        "lags": [(l, round(c, 4)) for l, c in lags],
                    })

        if abs(best_corr) > 0.1:
            result["leader"] = best_pair[0]
            result["lagger"] = best_pair[1]
            result["lag"] = best_pair[2]
            result["correlation"] = round(best_corr, 4)
        result["pairs"] = pairs

        return result

    _lead_lag_detector.__name__ = "lead_lag_detector"
    return _lead_lag_detector
