#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""Temporal bridging -- Item 137: link items across time gaps (P33).

When saving an item, if a related item exists from >24h ago,
create a TEMPORAL_BRIDGE graph edge to capture long-range temporal associations.

Extracted to keep jsonl_store.py under 300 lines.
"""
import logging
from datetime import datetime, timezone, timedelta

log = logging.getLogger("pulse.brain.save_writers.temporal_bridge")

_TEMPORAL_BRIDGE_GAP_HOURS = 24
_TEMPORAL_BRIDGE_SIMILARITY_THRESHOLD = 0.5
_TEMPORAL_BRIDGE_EDGE_TYPE = "TEMPORAL_BRIDGE"
_TEMPORAL_BRIDGE_CONFIDENCE = 0.5


def maybe_create_temporal_bridge(entry: dict) -> None:
    """If a related item exists from >24h ago, create a TEMPORAL_BRIDGE graph edge.

    Fails open -- any exception is silently swallowed.
    """
    try:
        from pulse.core.brain_db import get_conn
        from pulse.core.brain_utils import text_similarity

        content_text = (entry.get("content") or entry.get("text") or entry.get("title") or "")[:200]
        if not content_text:
            return

        entry_ts_raw = entry.get("timestamp", "")
        if not entry_ts_raw:
            return

        try:
            entry_ts = datetime.fromisoformat(entry_ts_raw.replace("Z", "+00:00"))
            if entry_ts.tzinfo is None:
                entry_ts = entry_ts.replace(tzinfo=timezone.utc)
        except (ValueError, TypeError):
            return

        cutoff = (entry_ts - timedelta(hours=_TEMPORAL_BRIDGE_GAP_HOURS)).isoformat()
        domain = entry.get("domain", "")
        entry_id = entry.get("id", "")
        if not entry_id:
            return

        conn = get_conn()
        candidates = []
        for table in ("lessons", "failures", "patterns"):
            try:
                rows = conn.execute(
                    f"SELECT id, content, title FROM {table} "
                    f"WHERE timestamp <= ? AND validity = 'valid' "
                    + (f"AND domain = ? " if domain else "")
                    + "ORDER BY timestamp DESC LIMIT 5",
                    (cutoff, domain) if domain else (cutoff,)
                ).fetchall()
                candidates.extend(rows)
            except Exception:
                pass

        if not candidates:
            return

        # Find best matching candidate by text similarity
        best_id = None
        best_sim = 0.0
        for row in candidates:
            cand_text = (row[1] or row[2] or "")[:200]
            if not cand_text:
                continue
            try:
                sim = text_similarity(content_text, cand_text)
            except Exception:
                continue
            if sim > best_sim:
                best_sim = sim
                best_id = row[0]

        if best_id and best_sim >= _TEMPORAL_BRIDGE_SIMILARITY_THRESHOLD:
            try:
                conn.execute(
                    "INSERT OR IGNORE INTO graph_edges "
                    "(from_node, to_node, edge_type, confidence) VALUES (?, ?, ?, ?)",
                    (best_id, entry_id, _TEMPORAL_BRIDGE_EDGE_TYPE,
                     round(best_sim * _TEMPORAL_BRIDGE_CONFIDENCE, 4))
                )
                conn.commit()
                log.debug("TEMPORAL_BRIDGE created: %s -> %s (sim=%.2f)", best_id, entry_id, best_sim)
            except Exception as e:
                log.debug("TEMPORAL_BRIDGE insert failed: %s", e)
    except Exception as e:
        log.debug("maybe_create_temporal_bridge failed: %s", e)
