#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
# See LICENSE file for details.
"""
Brain Recommender: Synthesize search results into actionable recommendation (V43.12)

Takes brain search results and produces ranked recommendation with:
- Approach suggestion based on wins
- Warnings from anti-patterns and fails
- Confidence score from evidence depth
- Contradiction alerts

Usage:
    python .claude/automation/brain_recommender.py "want description"
    python .claude/automation/brain_recommender.py "want" --json
Dependencies: Python stdlib only (Law 4)
"""

import json
import sys
from datetime import datetime, timezone
from pathlib import Path

# Add Utilities to path for brain_utils

from pulse.core.brain_utils import load_config, load_json_dict, text_similarity, WANTS_FILE
from pulse.brain.brain_search import brain_search


def extract_warnings(search_results: dict) -> list:
    """Extract warnings from anti-patterns and fails."""
    warnings = []
    for hit in search_results.get("results", {}).get("anti_patterns", []):
        if hit.get("salience", 0) > 0.15:
            warnings.append({
                "type": "anti_pattern",
                "title": hit.get("title", "Unknown"),
                "text": hit.get("text", "")[:150],
                "salience": hit.get("salience", 0),
                "severity": "high"
            })
    for hit in search_results.get("results", {}).get("fails", []):
        if hit.get("salience", 0) > 0.15:
            warnings.append({
                "type": "past_failure",
                "title": hit.get("title", "Unknown"),
                "text": hit.get("text", "")[:150],
                "salience": hit.get("salience", 0),
                "severity": "medium"
            })
    return sorted(warnings, key=lambda x: -x["salience"])


def extract_approaches(search_results: dict) -> list:
    """Extract proven approaches from wins and evidence."""
    approaches = []
    for hit in search_results.get("results", {}).get("wins", []):
        if hit.get("salience", 0) > 0.1:
            approaches.append({
                "type": "proven_win",
                "title": hit.get("title", "Unknown"),
                "text": hit.get("text", "")[:200],
                "salience": hit.get("salience", 0),
                "confidence": 0.8
            })
    for hit in search_results.get("results", {}).get("evidence", []):
        if hit.get("salience", 0) > 0.15 and hit.get("type") == "win":
            approaches.append({
                "type": "evidence_win",
                "text": hit.get("text", "")[:200],
                "salience": hit.get("salience", 0),
                "confidence": hit.get("confidence", 0.5)
            })
    return sorted(approaches, key=lambda x: -x["salience"])


def extract_context(search_results: dict) -> list:
    """Extract domain context for enrichment."""
    contexts = []
    for hit in search_results.get("results", {}).get("domains", []):
        if hit.get("salience", 0) > 0.1:
            contexts.append({
                "file": hit.get("file", ""),
                "text": hit.get("text", "")[:200],
                "salience": hit.get("salience", 0)
            })
    return contexts


def detect_contradictions(warnings: list, approaches: list) -> list:
    """Find contradictions between recommended approaches and warnings."""
    contradictions = []
    for w in warnings:
        for a in approaches:
            sim = text_similarity(w.get("text", ""), a.get("text", ""))
            if sim > 0.3:
                contradictions.append({
                    "warning": w.get("title", w.get("text", ""))[:80],
                    "approach": a.get("title", a.get("text", ""))[:80],
                    "similarity": round(sim, 3),
                    "resolution": "Review carefully - past failure overlaps with suggested approach"
                })
    return contradictions


def compute_confidence(approaches: list, warnings: list, evidence_count: int) -> float:
    """Compute overall recommendation confidence (0.0-1.0)."""
    base = 0.5
    if approaches:
        avg_salience = sum(a["salience"] for a in approaches) / len(approaches)
        base += avg_salience * 0.3
    if warnings:
        penalty = min(len(warnings) * 0.1, 0.3)
        base -= penalty
    if evidence_count > 5:
        base += 0.1
    return round(max(0.1, min(1.0, base)), 2)


def generate_recommendation(want: str, config: dict = None) -> dict:
    """Full recommendation pipeline: search -> analyze -> recommend."""
    if config is None:
        config = load_config()

    search_results = brain_search(want, config)

    warnings = extract_warnings(search_results)
    approaches = extract_approaches(search_results)
    context = extract_context(search_results)
    contradictions = detect_contradictions(warnings, approaches)
    evidence_count = len(search_results.get("results", {}).get("evidence", []))
    confidence = compute_confidence(approaches, warnings, evidence_count)

    recommendation = {
        "want": want,
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "confidence": confidence,
        "search_stats": {
            "total_results": search_results.get("total_results", 0),
            "elapsed_ms": search_results.get("elapsed_ms", 0)
        },
        "approach": None,
        "warnings": warnings[:5],
        "context": context[:3],
        "contradictions": contradictions,
        "evidence_depth": evidence_count
    }

    if approaches:
        best = approaches[0]
        recommendation["approach"] = {
            "summary": best.get("text", "")[:200],
            "type": best.get("type", "unknown"),
            "salience": best.get("salience", 0),
            "confidence": best.get("confidence", 0.5),
            "alternatives": len(approaches) - 1
        }

    return recommendation


# === CLI ===

def main():
    if len(sys.argv) < 2:
        print("Usage: brain_recommender.py \"want description\" [--json]")
        return

    want = sys.argv[1]
    as_json = "--json" in sys.argv

    print(f"=== Brain Recommender V43.12: \"{want}\" ===")
    rec = generate_recommendation(want)

    if as_json:
        print(json.dumps(rec, indent=2))
    else:
        print(f"  Confidence: {rec['confidence']:.0%}")
        print(f"  Search: {rec['search_stats']['total_results']} results "
              f"in {rec['search_stats']['elapsed_ms']}ms")

        if rec["approach"]:
            a = rec["approach"]
            print(f"\n  RECOMMENDED APPROACH ({a['type']}, salience={a['salience']:.3f}):")
            print(f"    {a['summary'][:120]}")
            if a["alternatives"]:
                print(f"    ({a['alternatives']} alternative(s) found)")
        else:
            print("\n  No proven approach found. Proceed with caution.")

        if rec["warnings"]:
            print(f"\n  WARNINGS ({len(rec['warnings'])}):")
            for w in rec["warnings"]:
                print(f"    [{w['severity'].upper()}] {w['title']}: {w['text'][:80]}")

        if rec["contradictions"]:
            print(f"\n  CONTRADICTIONS ({len(rec['contradictions'])}):")
            for c in rec["contradictions"]:
                print(f"    {c['warning'][:40]} <-> {c['approach'][:40]}")

        if rec["context"]:
            print(f"\n  CONTEXT ({len(rec['context'])} domains):")
            for ctx in rec["context"]:
                print(f"    {ctx['file']}: {ctx['text'][:80]}")


if __name__ == "__main__":
    main()
