"""Phase 5B: Prospective Memory — deferred intentions with time/event triggers."""
import json
import uuid
from datetime import datetime, timezone, timedelta
from pathlib import Path
from pulse.core.paths import get_state_dir
from pulse.core import event_bus
from pulse.core.brain_io import _acquire

INTENTION_QUEUE = get_state_dir() / "intention_queue.json"
INTENTION_LOG = get_state_dir() / "intention_log.jsonl"
DEFAULT_TTL_DAYS = 7


def _load_intentions() -> dict:
    if not INTENTION_QUEUE.exists():
        return {"intentions": []}
    try:
        return json.loads(INTENTION_QUEUE.read_text(encoding="utf-8"))
    except Exception:
        return {"intentions": []}


def _save_intentions(data: dict):
    INTENTION_QUEUE.parent.mkdir(parents=True, exist_ok=True)
    with _acquire(INTENTION_QUEUE):
        INTENTION_QUEUE.write_text(json.dumps(data, indent=2), encoding="utf-8")


def create_intention(
    description: str,
    trigger_type: str = "time_triggered",
    trigger_time: str = None,
    trigger_pattern: str = None,
    action: str = "investigate",
    context_snapshot: dict = None,
) -> str:
    """
    Create a deferred intention.
    trigger_type: "time_triggered" or "event_triggered"
    trigger_time: ISO timestamp (for time_triggered)
    trigger_pattern: regex pattern (for event_triggered)
    Returns intention ID.
    """
    now = datetime.now(timezone.utc)
    intention = {
        "id": f"intent_{uuid.uuid4().hex[:8]}",
        "type": trigger_type,
        "description": description,
        "trigger_time": trigger_time,
        "trigger_pattern": trigger_pattern,
        "action": action,
        "created_at": now.isoformat(),
        "expires_at": (now + timedelta(days=DEFAULT_TTL_DAYS)).isoformat(),
        "status": "pending",
        "context_snapshot": context_snapshot or {},
    }
    data = _load_intentions()
    data["intentions"].append(intention)
    _save_intentions(data)
    event_bus.publish("prospective.created", "prospective_memory", {"id": intention["id"]})
    return intention["id"]


def check_intentions(verbose=False) -> dict:
    """
    Check all pending intentions against current time.
    Called by orchestrator heartbeat.
    Time-triggered: fires if trigger_time <= now
    Expired: auto-expire after TTL
    Returns: {"fired": int, "expired": int}
    """
    data = _load_intentions()
    now = datetime.now(timezone.utc)
    fired = 0
    expired = 0
    changed = False

    for intention in data["intentions"]:
        if intention["status"] != "pending":
            continue

        # Check expiry
        expires_at = datetime.fromisoformat(intention["expires_at"])
        if expires_at < now:
            intention["status"] = "expired"
            expired += 1
            changed = True
            continue

        # Check time trigger
        if intention["type"] == "time_triggered" and intention.get("trigger_time"):
            trigger_time = datetime.fromisoformat(intention["trigger_time"])
            if trigger_time <= now:
                intention["status"] = "fired"
                fired += 1
                changed = True
                _log_intention(intention, "fired")
                event_bus.publish(
                    "prospective.fired", "prospective_memory",
                    {"id": intention["id"], "description": intention["description"]},
                )
                if verbose:
                    print(f"  [PROSPECTIVE] Fired: {intention['description'][:60]}")

    if changed:
        _save_intentions(data)

    return {"fired": fired, "expired": expired}


def _log_intention(intention: dict, event: str):
    """Append to audit trail."""
    INTENTION_LOG.parent.mkdir(parents=True, exist_ok=True)
    entry = {
        "event": event,
        "intention_id": intention["id"],
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "description": intention["description"],
    }
    with open(INTENTION_LOG, "a", encoding="utf-8") as f:
        f.write(json.dumps(entry) + "\n")


def get_pending_intentions() -> list:
    """Return all pending intentions for boot briefing."""
    data = _load_intentions()
    return [i for i in data["intentions"] if i["status"] == "pending"]
