import pytest
import json
from pathlib import Path
from unittest.mock import patch, MagicMock
from datetime import datetime, timezone

# --- Phase A Imports ---
from pulse.admin.audit.agent_trust import get_trust
from pulse.daemons.bridge.pulse_bridge import PulseBridge

# --- Phase B Imports ---
from pulse.brain.workspace.specialists import get_specialist, Coalition
from pulse.daemons.neural.neuromodulation import get_patience_limit, update_patience, _PATIENCE_FILE
from pulse.core.autonomy_state import update_drives, _load_state as load_autonomy_state, _save_state as save_autonomy_state
from pulse.brain.workspace.attention import AttentionCompetition
from pulse.brain.brain_search.search_scoring_core import _score_item
import pulse.core.interoception as interoception

def test_experiential_trust_bootstrapping():
    """Phase A: Ensure new agents start with cautious trust (0.1)."""
    # Using an unseen agent name
    trust = get_trust("brand_new_agent_99")
    assert trust == 0.1, f"Expected 0.1 cautious trust, got {trust}"

def test_persistent_specialist_state():
    """Phase B: Specialists must be persistent singletons."""
    coal1 = get_specialist("memory")
    coal2 = get_specialist("memory")
    assert coal1 is coal2, "Specialist should be a singleton"
    
    # Test reentrant strengthening
    initial_weight = getattr(coal1, "reentrant_weight", 1.0)
    coal1.receive_reentrant({"mock": "data"})
    new_weight = getattr(coal1, "reentrant_weight", 1.0)
    assert new_weight > initial_weight, "Reentrant broadcast should increase synaptic weight"

def test_serotonin_patience_reserve():
    """Phase B: Patience should deplete on failure and replenish on success."""
    worker_id = "test_serotonin_worker"
    if _PATIENCE_FILE.exists():
        _PATIENCE_FILE.unlink()
        
    initial_patience = get_patience_limit(worker_id)
    assert initial_patience == 4, "Default patience should be 4"
    
    # Deplete
    update_patience(worker_id, success=False)
    depleted_patience = get_patience_limit(worker_id)
    assert depleted_patience < initial_patience, "Patience should drop after failure"
    
    # Replenish
    update_patience(worker_id, success=True)
    update_patience(worker_id, success=True)
    replenished_patience = get_patience_limit(worker_id)
    assert replenished_patience > depleted_patience, "Patience should recover after success"

def test_item_level_competitive_suppression():
    """Phase B: Semantic redundancy should be actively suppressed."""
    comp = AttentionCompetition(similarity_threshold=0.5)
    items = [
        {"description": "The system should use absolute imports", "salience": 5.0},
        {"description": "Always use absolute imports in the system", "salience": 4.5}, # Redundant
        {"description": "Ensure variable names are descriptive", "salience": 4.0} # Unique
    ]
    
    filtered = comp.suppress_redundant(items)
    assert len(filtered) == 2, "Redundant item should be suppressed"
    assert "descriptive" in filtered[1]["description"], "Unique item should be kept"
    
    # Check reentrant strengthening on the accepted item
    assert filtered[0].get("salience", 0) > 5.0, "Accepted item should receive lateral excitation (boost)"

def test_affective_retrieval():
    """Phase B: High stress should massively boost retrieval of past failures."""
    from unittest.mock import patch
    
    now = datetime.now(timezone.utc).isoformat()
    item = {"id": "fail_1", "confidence": 0.8, "salience": 1.0, "validity": "valid", "type": "failure", "content": "A very long detailed string over 50 chars to pass the fragment check and also it must pass quality gates.", "timestamp": now}

    tc_fn = lambda c, ec: c
    ts_fn = lambda s, ts: s
    wilson_fn = lambda c, ec: (max(0.0, c-0.1), min(1.0, c+0.1))

    with patch('pulse.core.interoception.load_signals') as mock_load:
        import pulse.core.interoception as interoception
        interoception._signals = {
            "error_rate": {"current_value": 0.20}, # > 0.15 threshold
            "agent_load": {"current_value": 2.0}
        }
        
        res = _score_item(
            item, "failures", "test query", "general", set(),
            None, {}, {}, tc_fn, ts_fn, wilson_fn
        )

    assert res is not None
    assert res.get("_affective_salience") == 5.0, "Stressed agent should trigger affective salience multiplier"
    assert res.get("salience") == 5.0, "Salience should be multiplied by 5.0"
