import json
import logging
import threading
from datetime import datetime, timezone

from pulse.core.paths import get_state_dir
from pulse.core import event_bus
from pulse.core.brain_analysis import text_similarity

log = logging.getLogger("pulse.resurrection")

MEMORY_DIR = get_state_dir() / "memory"
PRUNED_ITEMS_FILE = MEMORY_DIR / "pruned_items.jsonl"
MAX_PRUNED = 500

_lock = threading.RLock()
_SUBSCRIBER_REGISTERED = False


# ---------------------------------------------------------------------------
# Item 181: Resurrection event subscriber — boost resurrected item salience
# ---------------------------------------------------------------------------

def _on_resurrection_event(event: dict) -> None:
    """Subscriber: when memory.resurrection fires, apply salience boost in DB."""
    try:
        payload = event.get("payload", {})
        fingerprint = payload.get("fingerprint", "")
        boosted_salience = float(payload.get("boosted_salience", 1.5))
        if not fingerprint:
            return
        from pulse.core.brain_db import get_conn
        conn = get_conn()
        now_iso = datetime.now(timezone.utc).isoformat()
        updated = 0
        for table in ("lessons", "failures", "patterns"):
            try:
                cur = conn.execute(
                    f"UPDATE {table} SET salience = MIN(?, 7.0), "
                    f"last_reinforced = ? WHERE fingerprint = ?",
                    (boosted_salience, now_iso, fingerprint),
                )
                conn.commit()
                updated += cur.rowcount
            except Exception:
                pass
        if updated:
            log.info("Resurrection: boosted salience of fingerprint %s to %.2f (%d rows)",
                     fingerprint, boosted_salience, updated)
        else:
            log.debug("Resurrection: fingerprint %s not found in DB (already pruned or JSONL-only)", fingerprint)
    except Exception as e:
        log.debug("Resurrection subscriber error (fail-open): %s", e)


def register_resurrection_subscriber() -> None:
    """Register the salience-boost subscriber for memory.resurrection events.
    Safe to call multiple times — only registers once.
    """
    global _SUBSCRIBER_REGISTERED
    if _SUBSCRIBER_REGISTERED:
        return
    event_bus.subscribe("memory.resurrection", _on_resurrection_event)
    _SUBSCRIBER_REGISTERED = True
    log.debug("Resurrection subscriber registered")


# Auto-register on import so the subscriber is always active
register_resurrection_subscriber()

def log_pruned(fingerprint: str, title: str, domain: str, salience: float):
    """Log a pruned item so it can potentially be resurrected."""
    with _lock:
        MEMORY_DIR.mkdir(parents=True, exist_ok=True)
        # Read last 500
        lines = []
        if PRUNED_ITEMS_FILE.exists():
            with open(PRUNED_ITEMS_FILE, "r", encoding="utf-8") as f:
                lines = f.readlines()
                
        entry = {
            "fingerprint": fingerprint,
            "title": title,
            "domain": domain,
            "salience": salience,
            "archived_at": datetime.now(timezone.utc).isoformat()
        }
        
        lines.append(json.dumps(entry) + "\n")
        
        if len(lines) > MAX_PRUNED:
            lines = lines[-MAX_PRUNED:]
            
        with open(PRUNED_ITEMS_FILE, "w", encoding="utf-8") as f:
            f.writelines(lines)

def check_resurrection(new_item_text: str) -> bool:
    """Checks if a new item matches a pruned item (Jaccard > 0.7).
    If so, resurrects it with 1.5x salience boost and emits event.
    """
    if not new_item_text or len(new_item_text) < 20:
        return False
        
    with _lock:
        if not PRUNED_ITEMS_FILE.exists():
            return False
            
        best_match = None
        best_salience = -1.0
        lines_to_keep = []
        
        with open(PRUNED_ITEMS_FILE, "r", encoding="utf-8") as f:
            for line in f:
                try:
                    item = json.loads(line.strip())
                    title = item.get("title", "")
                    if title and text_similarity(new_item_text, title) > 0.7:
                        sal = float(item.get("salience", 1.0))
                        if sal > best_salience:
                            best_salience = sal
                            best_match = item
                    else:
                        lines_to_keep.append(line)
                except json.JSONDecodeError:
                    continue
                    
        if best_match:
            # Resurrect! Remove from pruned
            with open(PRUNED_ITEMS_FILE, "w", encoding="utf-8") as f:
                f.writelines(lines_to_keep)
                
            event_bus.publish("memory.resurrection", "resurrection", {
                "fingerprint": best_match["fingerprint"],
                "original_salience": best_salience,
                "boosted_salience": min(best_salience * 1.5, 7.0)
            })
            return True
            
        return False
