# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""
Serotonin (5-HT) Patience Reserve

Dictates when an agent abandons a failing loop based on a decaying patience scalar.
Replaces hardcoded retry integers.
"""
from __future__ import annotations

from pulse.core.paths import get_state_dir
from pulse.core.brain_io import atomic_update_json
from pulse.core.brain_utils import now_iso
import json

_PATIENCE_FILE = get_state_dir() / "patience_reserve.json"

def get_patience_limit(worker_id: str) -> int:
    """
    Calculate the patience limit (retry threshold) for a given agent.
    Based on Serotonin (5-HT) system.
    Returns an integer representing the maximum number of retries.
    """
    base_patience = 4  # Default retry limit previously was 4
    if not _PATIENCE_FILE.exists():
        return base_patience

    try:
        with open(_PATIENCE_FILE, "r", encoding="utf-8") as f:
            data = json.load(f)
            scalar = data.get(worker_id, {}).get("scalar", 1.0)
            patience = int(base_patience * scalar)
            return max(1, min(8, patience))  # Absolute bounds: min 1 retry, max 8
    except Exception:
        return base_patience

def update_patience(worker_id: str, success: bool):
    """
    Update the agent's patience reserve based on task outcome.
    Success replenishes serotonin (patience).
    Failure depletes serotonin (patience) leading to quicker loop abandonment.
    """
    def _updater(data):
        if not isinstance(data, dict):
            data = {}
        
        agent_data = data.get(worker_id, {"scalar": 1.0, "last_updated": now_iso()})
        scalar = float(agent_data.get("scalar", 1.0))
        
        if success:
            scalar = min(1.5, scalar + 0.25)  # Replenish
        else:
            scalar = max(0.25, scalar - 0.25)  # Deplete
            
        data[worker_id] = {
            "scalar": round(scalar, 2),
            "last_updated": now_iso()
        }
        return data

    try:
        atomic_update_json(_PATIENCE_FILE, _updater, default={})
    except Exception:
        pass
