#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""Heavy interaction processing (background thread): bridge → knowledge routing."""
from concurrent.futures import ThreadPoolExecutor
from pulse.core.brain_analysis import compute_item_salience, compute_item_confidence
from pulse.brain.extraction.wants_parser import parse_full
from concurrent.futures import TimeoutError as _FuturesTimeout

_PARSE_EXECUTOR = ThreadPoolExecutor(max_workers=2, thread_name_prefix="wants_parser")
_LLM_EXECUTOR = ThreadPoolExecutor(max_workers=2, thread_name_prefix="bridge_llm")


def process_interaction(source: str, user_text: str, agent_text: str, verbose: bool = False):
    """Heavy processing runs in background thread — never blocks the bridge loop."""
    if verbose: print(f"[BRIDGE] Parsing interaction from {source}...")
    try:
        _fut = _PARSE_EXECUTOR.submit(parse_full, user_text, agent_text)
        parsed = _fut.result(timeout=5.0)
    except _FuturesTimeout:
        if verbose: print(f"[BRIDGE] wants_parser timed out — using empty parse for {source}")
        parsed = {"timestamp": "", "primary_domain": "general",
                  "wants": [], "dont_wants": [], "emotional_intensity": 0.0}

    from pulse.daemons.bridge.bridge_routing import append_to_evidence, route_knowledge
    append_to_evidence(parsed, user_text=user_text, agent_text=agent_text, verbose=verbose)
    combined_text = f"{user_text}\n{agent_text}" if agent_text else user_text

    try:
        knowledge_items = []
        ts, domain = parsed.get("timestamp", ""), parsed.get("primary_domain", "general")
        emul = 1.0 + parsed.get("emotional_intensity", 0.0)
        for dw in parsed.get("dont_wants", []):
            desc = dw.get("dont_want", "").strip()
            if desc and len(desc) > 15:
                rp = float(dw.get("priority", 1))
                sal = compute_item_salience(desc, priority=rp, emotional_intensity=emul - 1.0)
                sal *= 1.5  # Apply Asymmetric Negativity Bias
                conf = compute_item_confidence(desc, source_type="bridge")
                knowledge_items.append({"type": "FAILURE", "description": desc,
                    "domain": domain, "timestamp": ts, "confidence": conf, "salience": sal,
                    "emotional_intensity": emul - 1.0})
        for want in parsed.get("wants", []):
            desc = want.get("want", "").strip()
            if desc and len(desc) > 15 and want.get("priority", 0) >= 2:
                rp = float(want.get("priority", 1))
                sal = compute_item_salience(desc, priority=rp, emotional_intensity=emul - 1.0)
                conf = compute_item_confidence(desc, source_type="bridge")
                knowledge_items.append({"type": "LEARNING", "description": desc,
                    "domain": domain, "timestamp": ts, "confidence": conf, "salience": sal,
                    "emotional_intensity": emul - 1.0})
        # Route regex-extracted knowledge immediately (fast path)
        if knowledge_items:
            route_knowledge(knowledge_items, source=f"bridge_{source.lower()}", verbose=verbose)
    except Exception as e:
        if verbose: print(f"[BRIDGE] route_knowledge error: {e}")

    try:
        from pulse.brain.capture.auto_capture import capture as auto_capture
        auto_capture(user_text, agent_text, session_id=source.lower())
    except Exception as e:
        if verbose: print(f"[BRIDGE] auto_capture error: {e}")

    try:
        from pulse.brain.session.session_lifecycle import _record_interaction as record_interaction
        record_interaction(source.lower(), user_text, agent_text,
                         domain=parsed.get('primary_domain', 'general'), timestamp=parsed.get('timestamp', ''))
    except Exception as _rec_e:
        if verbose: print(f"[BRIDGE] session recording failed: {_rec_e}")

    # LLM extraction runs in background thread — never blocks the bridge loop
    regex_yield = len(knowledge_items)
    _llm_source = f"bridge_{source.lower()}"

    def _background_llm_extract(text, dom, timestamp, src, verbose, is_fallback):
        try:
            from pulse.daemons.bridge.llm_extraction import extract_with_llm
            items = extract_with_llm(text, dom, timestamp, verbose=verbose)
            if items:
                suffix = "_llm" if is_fallback else ""
                route_knowledge(items, source=f"{src}{suffix}", verbose=verbose)
        except Exception as e:
            if verbose:
                print(f"[BRIDGE] Background LLM extraction failed: {e}")

    if agent_text and len(agent_text) > 100:
        _LLM_EXECUTOR.submit(_background_llm_extract, agent_text, domain, ts, _llm_source, verbose, False)
    if regex_yield < 2 and len(combined_text) > 200:
        _LLM_EXECUTOR.submit(_background_llm_extract, combined_text, domain, ts, _llm_source, verbose, True)

    extracted_facts_count = 0
    try:
        from pulse.brain.extraction.fact_parser import parse_facts
        from pulse.brain.persistence.fact_store import store_facts as _store_facts
        facts = parse_facts(combined_text)
        extracted_facts_count = len(facts)
        if facts:
            _store_facts(facts, source=f"bridge_{source.lower()}")
    except Exception as _fact_e:
        if verbose: print(f"[BRIDGE] fact extraction failed: {_fact_e}")

    extracted_decisions_count = 0
    try:
        from pulse.brain.extraction.decision_parser import parse_decisions
        from pulse.brain.persistence.decision_store import store_decision, check_anti_pattern_conflict
        decisions = parse_decisions(user_text, agent_text)
        for dec in decisions:
            dec.update(participants=[source.lower()], source_session=source.lower())
            dec.setdefault("domain", domain)
            dec["salience"] = compute_item_salience(dec["choice"], priority=2, emotional_intensity=emul - 1.0)
            dec["confidence"] = compute_item_confidence(dec["choice"], source_type="bridge")
            conflict = check_anti_pattern_conflict(dec["choice"])
            if conflict:
                dec["_ap_conflict"] = conflict.get("description", "")[:80]
            if store_decision(dec):
                extracted_decisions_count += 1
        if extracted_decisions_count and verbose:
            print(f"[BRIDGE] Stored {extracted_decisions_count} decisions")
    except Exception as e:
        if verbose: print(f"[BRIDGE] decision_extraction error: {e}")

    try:
        from pulse.brain.index.episodic_index import append_entry
        from pulse.brain.session.context_envelope import get_context_envelope
        append_entry(agent=source.lower(), user_text=user_text, agent_text=agent_text,
                     wants_count=len(parsed.get("wants", [])), facts_count=extracted_facts_count,
                     emotional_intensity=parsed.get("emotional_intensity", 0.0), context=get_context_envelope())
    except Exception:
        pass

    regex_hits = []
    try:
        from pulse.daemons.bridge.reflex_arc import detect_mistakes, check_reflex
        regex_hits = detect_mistakes(combined_text)
        check_reflex(user_text, agent_text, source)
    except Exception as e:
        if verbose: print(f"[BRIDGE] reflex_arc error: {e}")
    try:
        from pulse.daemons.bridge.reflex_llm import enqueue_for_llm
        enqueue_for_llm(user_text, agent_text, source, regex_hits)
    except Exception as e:
        if verbose: print(f"[BRIDGE] reflex_llm error: {e}")
