"""The compute tools the research agent is given. Each wraps a platform service; the agent reasons
about WHAT to test, the deterministic services do the testing. The gauntlet stays the truth-keeper —
the agent cannot make anything significant by proposing it."""
from __future__ import annotations

from langchain_core.tools import tool

from fxhnt.application.portfolio_eval import PortfolioEvaluationService
from fxhnt.application.research import ResearchService
from fxhnt.domain.models import AssetClass, Market, StrategySpec
from fxhnt.domain.portfolio import Book, StrategyAllocation
from fxhnt.domain.strategies import available, get_strategy


def build_tools(research: ResearchService, portfolio: PortfolioEvaluationService) -> list:
    @tool
    def list_strategies() -> str:
        """List the available strategy kinds and the structural rationale of each. Call this first."""
        return "; ".join(f"{k}: {get_strategy(k).rationale}" for k in available())

    @tool
    def evaluate_candidate(symbol: str, asset_class: str, kind: str, window: int = 200, n_trials: int = 1) -> str:
        """Backtest ONE (market, strategy) and run it through the gauntlet. asset_class is future|etf|equity.
        Returns Sharpe, out-of-sample Sharpe, deflated-Sharpe (DSR) and PASS/REJECT."""
        try:
            market = Market(symbol=symbol.upper(), asset_class=AssetClass(asset_class.lower()))
            spec = StrategySpec(kind=kind, params={"window": float(window)})
            r = research.evaluate_candidate(market, spec, n_trials=n_trials, persist=False)
            flag = "PASS" if r.verdict.passed else "REJECT"
            return f"{market} {spec.key()}: Sharpe {r.stats.sharpe:+.2f}, OOS {r.verdict.oos_sharpe:+.2f}, DSR {r.verdict.dsr:.3f} -> {flag}"
        except Exception as e:  # surface errors to the agent so it can adjust
            return f"error: {str(e)[:140]}"

    @tool
    def evaluate_book(symbols: str, kind: str, window: int = 200, asset_class: str = "future", n_book_trials: int = 1) -> str:
        """Build a diversified equal-weight BOOK (one strategy across the comma-separated markets) and
        validate it at PORTFOLIO level — the unit of alpha. Returns combined Sharpe, OOS, DSR, maxDD, PASS/REJECT."""
        try:
            markets = [Market(symbol=s.strip().upper(), asset_class=AssetClass(asset_class.lower()))
                       for s in symbols.split(",") if s.strip()]
            weight = 1.0 / len(markets)
            allocs = [StrategyAllocation(spec=StrategySpec(kind=kind, params={"window": float(window)}), market=m, weight=weight)
                      for m in markets]
            ev = portfolio.evaluate_book(Book(name=f"{kind}-book", allocations=allocs), n_book_trials=n_book_trials)
            flag = "PASS" if ev.verdict.passed else "REJECT"
            return (f"BOOK {kind}(w={window}) on [{symbols}]: Sharpe {ev.stats.sharpe:+.2f}, OOS {ev.verdict.oos_sharpe:+.2f}, "
                    f"DSR {ev.verdict.dsr:.3f}, maxDD {100*ev.stats.max_drawdown:.0f}% -> {flag}")
        except Exception as e:
            return f"error: {str(e)[:140]}"

    return [list_strategies, evaluate_candidate, evaluate_book]
