"""hypothesis_registry.py — Research hypothesis lifecycle management.

Phase 8: Tracks strategy ideas from conception through validation to deployment.
  pending → sandbox_backtest → validated → paper_trading → promoted
  Any stage can transition to falsified if evidence contradicts.

Usage::

    from src.learning.hypothesis_registry import create_hypothesis, validate_all
    h = create_hypothesis("RSI<30 in RANGING has edge", "rsi_extreme", "RANGING")
    validate_all()  # checks all pending hypotheses against brain data
"""

from __future__ import annotations

import json
import time as _time
from pathlib import Path
from typing import Any

import config_manager


_VALID_STATUSES = {"pending", "sandbox_backtest", "validated", "paper_trading", "promoted", "falsified"}


def _hypotheses_dir() -> Path:
    d = config_manager.get_data_dir().parent / "memory" / "hypotheses"
    d.mkdir(parents=True, exist_ok=True)
    return d


def _state_path() -> Path:
    return _hypotheses_dir() / "_registry.json"


def _load_state() -> dict[str, Any]:
    sp = _state_path()
    if sp.exists():
        try:
            return json.loads(sp.read_text(encoding="utf-8"))
        except Exception:
            pass
    return {"hypotheses": {}}


def _save_state(state: dict[str, Any]) -> None:
    try:
        _state_path().write_text(json.dumps(state, indent=2, ensure_ascii=False), encoding="utf-8")
    except Exception:
        pass


def create_hypothesis(
    claim: str,
    strategy_id: str = "",
    regime: str = "",
    acceptance_criteria: dict[str, Any] | None = None,
) -> dict[str, Any]:
    """Register a new trading hypothesis.

    Args:
        claim: Natural language description of the hypothesis.
        strategy_id: Which strategy this applies to.
        regime: Which market regime this applies to.
        acceptance_criteria: Dict like {"min_win_rate": 0.45, "min_trades": 10, "max_drawdown": 30}
    """
    state = _load_state()
    hid = f"hyp_{int(_time.time())}_{strategy_id or 'general'}"
    criteria = acceptance_criteria or {"min_win_rate": 0.45, "min_trades": 10}

    hypothesis = {
        "id": hid,
        "claim": claim,
        "strategy_id": strategy_id,
        "regime": regime,
        "status": "pending",
        "acceptance_criteria": criteria,
        "evidence": {},
        "created_at": _time.strftime("%Y-%m-%dT%H:%M:%S", _time.gmtime()),
        "validated_at": "",
        "promoted_at": "",
    }
    state["hypotheses"][hid] = hypothesis
    _save_state(state)

    # Generate markdown page
    _write_hypothesis_md(hypothesis)

    return hypothesis


def validate_all() -> list[dict[str, Any]]:
    """Validate all pending/active hypotheses against trading_brain data."""
    state = _load_state()
    results = []

    try:
        from src.learning.trading_brain import get_brain
        brain = get_brain()
    except Exception:
        return results

    for hid, h in list(state["hypotheses"].items()):
        if h["status"] in ("promoted", "falsified"):
            continue

        sid = h.get("strategy_id", "")
        regime = h.get("regime", "")
        if not sid:
            continue

        criteria = h.get("acceptance_criteria", {})
        min_wr = float(criteria.get("min_win_rate", 0.45))
        min_trades = int(criteria.get("min_trades", 10))

        # Query brain for evidence
        query_kwargs = {"strategy_id": sid}
        if regime:
            query_kwargs["regime"] = regime
        stats = brain.query_win_rate(**query_kwargs)

        n = stats.get("n", 0)
        wr = stats.get("win_rate", 0)
        avg_pnl = stats.get("avg_pnl", 0)

        evidence = {"n": n, "win_rate": round(wr, 4), "avg_pnl": round(avg_pnl, 2)}

        if n >= min_trades:
            if wr >= min_wr:
                h["status"] = "validated" if h["status"] == "pending" else h["status"]
                h["validated_at"] = _time.strftime("%Y-%m-%dT%H:%M:%S", _time.gmtime())
            else:
                h["status"] = "falsified"

        h["evidence"] = evidence
        _write_hypothesis_md(h)
        results.append({"id": hid, "status": h["status"], "evidence": evidence})

    _save_state(state)
    return results


def promote_hypothesis(hid: str) -> bool:
    """Promote a validated hypothesis to strategy status."""
    state = _load_state()
    h = state["hypotheses"].get(hid)
    if not h or h["status"] != "validated":
        return False
    h["status"] = "promoted"
    h["promoted_at"] = _time.strftime("%Y-%m-%dT%H:%M:%S", _time.gmtime())
    _save_state(state)
    _write_hypothesis_md(h)
    return True


def _write_hypothesis_md(h: dict[str, Any]) -> None:
    try:
        hid = h["id"]
        fp = _hypotheses_dir() / f"{hid}.md"
        status = h["status"]
        ev = h.get("evidence", {})
        claim = h.get("claim", "")
        sid = h.get("strategy_id", "")
        reg = h.get("regime", "")
        created = h.get("created_at", "")
        validated = h.get("validated_at", "")
        crit = h.get("acceptance_criteria", {})
        min_wr = crit.get("min_win_rate", 0.45)
        min_n = crit.get("min_trades", 10)
        wr = ev.get("win_rate", 0)
        n = ev.get("n", 0)
        avg_pnl = ev.get("avg_pnl", 0)
        content = f"""---
id: {hid}
claim: {claim}
strategy: {sid}
regime: {reg}
status: {status}
win_rate: {wr}
trades: {n}
created: {created}
validated: {validated}
tags: [hypothesis, {status}, {sid or 'general'}]
---

# {claim}

## Status: {status}

## Evidence
- Win rate: {wr*100:.1f}% (n={n})
- Avg PnL: ${avg_pnl:.2f}

## Acceptance Criteria
- Min win rate: {min_wr*100:.0f}%
- Min trades: {min_n}

## Related
- [[strategies/{sid}]] (if promoted)
- Back to [[INDEX]]
"""
        fp.write_text(content, encoding="utf-8")
    except Exception:
        pass
