#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""Brain data loaders for agent boot sequence."""
from __future__ import annotations

import re

from pulse.core.brain_utils import (
    HIPPOCAMPUS_DIR, STATE_DIR, load_json_dict
)

ANTI_PATTERNS_FILE = HIPPOCAMPUS_DIR / "Patterns" / "anti_patterns.md"
from pulse.brain.brain_search import brain_search

# --- Private Helpers ---
def _clean_brain_headings(headings: list, limit: int = 10) -> list:
    seen = set()
    clean = []
    for h in headings:
        h = h.strip().lstrip("*").strip()
        if len(h) < 15:
            continue
        if h.startswith("/") or h.startswith("\\") or h.startswith("C:"):
            continue
        key = h.lower()[:40]
        if key not in seen:
            seen.add(key)
            clean.append(h[:80])
    return clean[-limit:]

def _load_md_headings(path, limit: int = 10) -> list[str]:
    if not path.exists():
        return []
    text = path.read_text(encoding="utf-8", errors="replace")
    headings = re.findall(r"^## (.+)$", text, re.MULTILINE)
    return _clean_brain_headings(headings, limit=limit)

def _extract_search_hits(hits, limit: int = 5) -> list:
    out = []
    for h in hits[:limit]:
        text = (h.get("text") or h.get("title", ""))[:80].strip()
        if text and len(text) > 10:
            out.append(text)
    return out

# --- Public Loaders ---
def load_recent_brain() -> dict:
    """Load recent brain data. IMPERATIVE — injected whether agents ask or not."""
    result = {"lessons": [], "failures": [], "anti_patterns": [], "patterns": [], "user_profile": {}}

    # Load User Profile (The distilled "Forgetfulness" Engine output)
    profile_file = STATE_DIR / "user_profile.json"
    if profile_file.exists():
        try:
            profile_data = load_json_dict(profile_file)
            result["user_profile"] = profile_data
        except Exception:
            pass

    result["lessons"] = _load_md_headings(HIPPOCAMPUS_DIR / "Lessons" / "auto_lessons.md", 10)
    result["failures"] = _load_md_headings(HIPPOCAMPUS_DIR / "Failures" / "auto_fails.md", 10)

    # Anti-patterns (table rows)
    if ANTI_PATTERNS_FILE.exists():
        text = ANTI_PATTERNS_FILE.read_text(encoding="utf-8", errors="replace")
        rows = re.findall(r"^\| ([^|âŒ][^|]+)\| ([^|]+)\| ([^|]+)\|", text, re.MULTILINE)
        patterns = [f"{p.strip()} -> {correct.strip()}" for p, why, correct in rows if p.strip() and p.strip() != "Anti-Pattern" and not p.startswith("---")]
        result["anti_patterns"] = patterns[:10]

    result["patterns"] = _load_md_headings(HIPPOCAMPUS_DIR / "Patterns" / "auto_patterns.md", 5)

    return result

def load_relevant_brain(task_query: str) -> dict:
    """Load brain knowledge RELEVANT to the task via brain_search."""
    if not brain_search or not task_query or len(task_query) < 5:
        return load_recent_brain()

    profile_file = STATE_DIR / "user_profile.json"
    user_profile = load_json_dict(profile_file) if profile_file.exists() else {}

    try:
        search_result = brain_search(task_query, max_per_source=5)
        hits = search_result.get("results", {})
        total = search_result.get("total_results", 0)

        if total < 3:
            recent_data = load_recent_brain()
            recent_data["user_profile"] = user_profile
            return recent_data

        return {
            "lessons": _extract_search_hits(hits.get("wins", []), 5),
            "failures": _extract_search_hits(hits.get("fails", []), 5),
            "anti_patterns": _extract_search_hits(hits.get("anti_patterns", []), 5),
            "patterns": _extract_search_hits(hits.get("domains", []), 3),
            "user_profile": user_profile,
        }
    except Exception:
        return load_recent_brain()

def load_agent_procedures(agent_id: str) -> dict:
    """Load agent-specific procedure recommendations. Returns empty if insufficient data."""
    if not agent_id:
        return {}
    try:
        from pulse.brain.agent_procedures import (
            get_agent_profile, match_procedures, get_weak_domains,
        )
        profile = get_agent_profile(agent_id)
        if profile.get("total_tasks", 0) < 3:
            return {}
        return {
            "weak_domains": get_weak_domains(agent_id),
            "procedures": match_procedures(agent_id),
            "profile_summary": profile,
        }
    except Exception:
        return {}


def load_daemon_injections(max_items: int = 5, agent_name: str = "") -> dict:
    """Load D4 constraints + D5 gate feedback + D6 golden paths + U7 cross-agent intel.

    Returns: {"synthetic_constraints": [...], "gate_feedback": [...], "golden_paths": [...], "cross_agent_intel": [...]}
    """
    result: dict = {"synthetic_constraints": [], "gate_feedback": [], "golden_paths": [], "cross_agent_intel": []}

    # D4: Synthetic constraints (precognitive guardrails)
    constraints_file = STATE_DIR / "synthetic_constraints.json"
    if constraints_file.exists():
        try:
            data = load_json_dict(constraints_file)
            active = [c for c in data.get("constraints", [])
                      if c.get("status") == "active"]
            active.sort(key=lambda c: -c.get("confidence", 0))
            result["synthetic_constraints"] = active[:max_items]
        except Exception:
            pass

    # D5: Gate feedback (temporary anti-patterns from swarm failures)
    feedback_file = STATE_DIR / "gate_feedback.json"
    if feedback_file.exists():
        try:
            from datetime import datetime, timezone
            data = load_json_dict(feedback_file)
            now = datetime.now(timezone.utc)
            active = []
            for e in data.get("entries", []):
                if e.get("status") != "active":
                    continue
                try:
                    expires = datetime.fromisoformat(e.get("expires_at", ""))
                    if expires.tzinfo is None:
                        expires = expires.replace(tzinfo=timezone.utc)
                    if expires < now:
                        continue
                except (ValueError, TypeError):
                    pass
                active.append(e)
            result["gate_feedback"] = active[:max_items]
        except Exception:
            pass

    # D6: Golden paths (proven success strategies from pathweaver)
    golden_file = STATE_DIR / "golden_paths.json"
    if golden_file.exists():
        try:
            data = load_json_dict(golden_file)
            active = [p for p in data.get("paths", [])
                      if p.get("status") == "active"]
            active.sort(key=lambda p: -p.get("confidence", 0))
            result["golden_paths"] = active[:max_items]
        except Exception:
            pass

    # U7: Cross-agent learning (Dr. Mirror Neurons)
    result["cross_agent_intel"] = _load_cross_agent_intel(agent_name, max_items)

    return result


def _load_cross_agent_intel(current_agent: str = "", limit: int = 5) -> list:
    """Load lessons/failures from OTHER agents for cross-pollination (U7)."""
    try:
        from pulse.brain.cross_agent import extract_cross_agent_intel
        return extract_cross_agent_intel(current_agent, limit)
    except Exception:
        return []


def load_curriculum(domain: str = "", task_query: str = "") -> dict:
    """Load domain curriculum from D15 Phylogenetic Skill Compiler output.

    Tries direct domain match first, then infers from task_query keywords.
    Returns curriculum dict or {} if unavailable.
    """
    curricula_file = HIPPOCAMPUS_DIR / "Knowledge" / "curricula.json"
    if not curricula_file.exists():
        return {}
    try:
        data = load_json_dict(curricula_file)
        cur = data.get("curricula", {})
        if not cur:
            return {}
        # Direct domain match
        if domain and domain.lower() in cur:
            result = cur[domain.lower()]
            result["_generation"] = data.get("generation", 0)
            return result
        # Infer from task_query keywords
        if task_query:
            query_lower = task_query.lower()
            for d, c in cur.items():
                if d in query_lower:
                    c["_generation"] = data.get("generation", 0)
                    return c
        return {}
    except Exception:
        return {}


def _search_brain_for_task(task_title: str) -> dict:
    """Lightweight brain search for task context."""
    return brain_search(task_title, max_per_source=2) if brain_search else {}
