"""Horizon Fund MCP Server - autonomous fund management tools only.

A separate MCP server that exposes ONLY fund management tools,
isolated from the core trading engine tools. Use this when you want
the LLM to manage a fund without access to raw order submission.

Run: HORIZON_FUND_MODE=1 python -m horizon.mcp_fund

Configuration example (Claude Desktop / claude_desktop_config.json):

    {
        "mcpServers": {
            "horizon-fund": {
                "command": "python",
                "args": ["-m", "horizon.mcp_fund"],
                "env": {
                    "HORIZON_FUND_MODE": "1",
                    "HORIZON_FUND_CAPITAL": "100000",
                    "HORIZON_EXCHANGE": "paper"
                }
            }
        }
    }

This server does NOT include:
- submit_order, cancel_order (raw order management)
- activate_kill_switch (engine-level)
- wallet analysis, discovery, flow analytics
- cloud deployment tools

It ONLY includes fund lifecycle and monitoring tools.
"""

from __future__ import annotations

import os
import logging

from mcp.server.fastmcp import FastMCP

from horizon import tools

logger = logging.getLogger(__name__)

# Force fund mode on when using this server
os.environ["HORIZON_FUND_MODE"] = "1"

mcp = FastMCP(
    "horizon-fund",
    instructions=(
        "Horizon Fund Manager - autonomous multi-strategy fund management. "
        "Use these tools to deploy, stop, pause, resume, and scale strategies, "
        "track NAV and P&L, run stress tests, monitor correlations and execution "
        "quality, and query persistent strategy memory. "
        "This server manages a fund portfolio - it does NOT submit individual "
        "orders or interact with exchanges directly. Strategies handle their "
        "own execution. "
        "Never pass API keys or passwords as tool parameters."
    ),
)


# ---------------------------------------------------------------------------
# Fund lifecycle
# ---------------------------------------------------------------------------

@mcp.tool()
def fund_status() -> dict:
    """Get full fund status: NAV, drawdown, strategy count, kill switch, universe size."""
    return tools.fund_status()


@mcp.tool()
def fund_report() -> dict:
    """Generate a full fund report with NAV, strategies, allocations."""
    return tools.fund_report()


@mcp.tool()
def fund_start() -> dict:
    """Start the fund: deploy queued strategies and begin the oversight loop."""
    try:
        fund = tools._get_fund()
        fund.start()
        return {"started": True, "strategies": fund.controller.running_count()}
    except Exception as e:
        return {"error": str(e)}


@mcp.tool()
def fund_stop() -> dict:
    """Stop the fund: stop oversight loop and all running strategies."""
    try:
        fund = tools._get_fund()
        fund.stop()
        return {"stopped": True}
    except Exception as e:
        return {"error": str(e)}


# ---------------------------------------------------------------------------
# Strategy management
# ---------------------------------------------------------------------------

@mcp.tool()
def deploy_strategy(name: str, markets: list[str], mode: str = "paper") -> dict:
    """Deploy a strategy to the fund. mode: 'paper' or 'live'. Paper mode by default for safety."""
    return tools.fund_deploy_strategy(name, markets, mode)


@mcp.tool()
def stop_strategy(name: str) -> dict:
    """Stop and remove a strategy from the fund. Cancels orders and frees capital."""
    return tools.fund_stop_strategy(name)


@mcp.tool()
def pause_strategy(name: str) -> dict:
    """Pause a running strategy. Keeps state but stops trading."""
    return tools.fund_pause_strategy(name)


@mcp.tool()
def resume_strategy(name: str) -> dict:
    """Resume a paused strategy."""
    return tools.fund_resume_strategy(name)


@mcp.tool()
def list_strategies() -> dict:
    """List all strategies with state, capital allocation, markets, and mode."""
    return tools.fund_list_strategies()


@mcp.tool()
def scale_strategy(name: str, new_capital: float) -> dict:
    """Scale capital allocation for a strategy."""
    return tools.fund_scale_strategy(name, new_capital)


# ---------------------------------------------------------------------------
# Monitoring and analytics
# ---------------------------------------------------------------------------

@mcp.tool()
def nav_history(limit: int = 50) -> dict:
    """Get recent NAV history (time series of fund value, drawdown, HWM)."""
    return tools.fund_nav_history(limit)


@mcp.tool()
def risk_dashboard() -> dict:
    """Consolidated risk dashboard: VaR budget, correlations, execution quality, kill switch."""
    return tools.fund_risk_dashboard()


@mcp.tool()
def stress_test() -> dict:
    """Run fund-level stress scenarios (10%/20% drawdown, correlation spike, liquidity crisis, black swan)."""
    return tools.fund_stress_test()


@mcp.tool()
def pnl_attribution() -> dict:
    """P&L attribution per strategy: realized, unrealized, and daily PnL breakdown."""
    return tools.fund_pnl_attribution()


@mcp.tool()
def correlation_matrix() -> dict:
    """Cross-strategy correlation matrix to detect hidden concentration risk."""
    return tools.fund_correlation_matrix()


@mcp.tool()
def execution_report() -> dict:
    """Execution quality: fill rates, slippage, adverse selection, market impact per strategy."""
    return tools.fund_execution_report()


# ---------------------------------------------------------------------------
# Memory
# ---------------------------------------------------------------------------

@mcp.tool()
def memory_query(category: str | None = None, key_contains: str | None = None, limit: int = 20) -> dict:
    """Query fund strategy memory. Categories: strategy_outcome, market_pattern, regime_mapping, edge_decay, failure_reason."""
    return tools.fund_memory_query(category, key_contains, limit)


@mcp.tool()
def memory_record(category: str, key: str, value: str, confidence: float = 0.5) -> dict:
    """Record a learning to fund memory for future reference across sessions."""
    return tools.fund_memory_record(category, key, value, confidence)


# ---------------------------------------------------------------------------
# Intelligence and analysis
# ---------------------------------------------------------------------------

@mcp.tool()
def fund_explain() -> dict:
    """Full fund state explanation: overview, regime, risk, strategies, decisions, hypotheses, alpha factors, and recent alerts -- all in one call."""
    return tools.fund_explain()


@mcp.tool()
def fund_explain_strategy(name: str) -> dict:
    """Detailed analysis of a single strategy: performance, execution quality, alpha decay, promotion stage, and related hypotheses."""
    return tools.fund_explain_strategy(name)


@mcp.tool()
def fund_explain_risk() -> dict:
    """Full risk analysis: tail risk (VaR/CVaR), portfolio Greeks, correlations, stress test results, VaR budget, dynamic limits, and attribution."""
    return tools.fund_explain_risk()


@mcp.tool()
def fund_hypotheses(limit: int = 20) -> dict:
    """List active trading hypotheses with lifecycle state, confidence, and edge estimates."""
    return tools.fund_hypotheses(limit)


@mcp.tool()
def fund_regime() -> dict:
    """Current market regime (trending/volatile/quiet/etc.) with confidence and recent transitions."""
    return tools.fund_regime()


@mcp.tool()
def fund_alpha_model() -> dict:
    """Alpha model factor report: per-factor information coefficients, significance, and weights."""
    return tools.fund_alpha_model()


@mcp.tool()
def fund_decisions(limit: int = 20) -> dict:
    """Recent autonomous decisions with reasoning, confidence, outcome, and guardrail status."""
    return tools.fund_decisions(limit)


@mcp.tool()
def fund_decay_report() -> dict:
    """Alpha decay tracking: edge erosion alerts, half-life estimates, and retirement recommendations."""
    return tools.fund_decay_report()


@mcp.tool()
def fund_alerts(limit: int = 50) -> dict:
    """Recent fund alerts and notifications with counts by category."""
    return tools.fund_alerts(limit)


@mcp.tool()
def fund_ledger(limit: int = 50) -> dict:
    """Double-entry accounting ledger: recent journal entries, balance sheet, and income statement."""
    return tools.fund_ledger_entries(limit)


@mcp.tool()
def fund_promotion_status() -> dict:
    """Strategy promotion stages (paper/shadow/live) and promotion history."""
    return tools.fund_promotion_status()


@mcp.tool()
def fund_full_snapshot() -> dict:
    """Everything about the fund in one call. Use this when you need a complete picture."""
    return tools.fund_full_snapshot()


# ---------------------------------------------------------------------------
# Entry point
# ---------------------------------------------------------------------------

def main() -> None:
    """Run the fund MCP server on stdio transport."""
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    mcp.run(transport="stdio")


if __name__ == "__main__":
    main()
