"""Propose User Model connection facts after successful cross-thread recall preflight."""

from __future__ import annotations

import logging
import re
from typing import TYPE_CHECKING

from utils.connections_journal import append_connections_journal, extract_related_topics
from utils.recall_signals import MUGI_THREAD_PREFIX_RE

if TYPE_CHECKING:
    from tools.session_search_tools import RecallPreflightResult

_log = logging.getLogger(__name__)

_UUID_IN_TEXT_RE = re.compile(
    r"\b([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\b",
    re.IGNORECASE,
)

_IDENTITY_ONLY_USER_CUES = re.compile(
    r"\b(lives in|based in|located in|my timezone|my job is|i work at|employer is)\b",
    re.IGNORECASE,
)

_MIN_RESULT_CHARS = 200

_BROWSE_THREAD_COUNT_REASONS = frozenset({"browse_recent", "browse_after_empty_fts"})


def _personal_noticing_enabled() -> bool:
    try:
        from core.config import get_consolidation_config

        return bool(get_consolidation_config().get("personal_noticing_enabled", True))
    except Exception:
        return True


def _norm_thread_id(raw: str | None) -> str:
    return (raw or "").strip().lower()


def _referenced_other_thread_id(user_query: str, current_thread_id: str | None) -> str | None:
    """Return a thread UUID from the query that differs from the active thread, if any."""
    cur = _norm_thread_id(current_thread_id)
    m = MUGI_THREAD_PREFIX_RE.search(user_query or "")
    if m:
        tid = _norm_thread_id(m.group(1))
        if tid and tid != cur:
            return tid
    for match in _UUID_IN_TEXT_RE.finditer(user_query or ""):
        tid = _norm_thread_id(match.group(1))
        if tid and tid != cur:
            return tid
    return None


def is_cross_thread_recall(
    result: RecallPreflightResult,
    *,
    current_thread_id: str | None,
    user_query: str,
) -> bool:
    """True when preflight evidence links the active thread to a different prior thread."""
    if _referenced_other_thread_id(user_query, current_thread_id) is not None:
        return True
    reason = str(getattr(result, "reason", "") or "").strip().lower()
    # Browse paths report how many recent threads were listed, not cross-thread linkage.
    if reason in _BROWSE_THREAD_COUNT_REASONS:
        return False
    if int(getattr(result, "thread_count", 0) or 0) >= 2:
        return True
    return False


def _compose_connection_fact(excerpt: str) -> str:
    from utils.noticing_plaintext import sanitize_noticing_plaintext

    topics = extract_related_topics(excerpt, max_topics=4)
    topic_hint = ", ".join(topics[:3]) if topics else "earlier conversations"
    snippet = sanitize_noticing_plaintext(excerpt, max_len=120)
    if snippet:
        return (
            f"Cross-thread link: while continuing the current conversation, "
            f"you connected this thread to prior work on {topic_hint} "
            f"(recall: {snippet})."
        )[:400]
    return (
        f"Cross-thread link: while continuing the current conversation, "
        f"you connected this thread to prior work on {topic_hint}."
    )[:400]


def maybe_propose_from_recall_preflight(
    workspace: str,
    result: RecallPreflightResult,
    *,
    current_thread_id: str | None,
    user_query: str,
) -> str:
    """Maybe create a connections proposal from recall preflight. Returns outcome label."""
    if not (workspace or "").strip():
        return "skipped:no_workspace"
    if not _personal_noticing_enabled():
        return "skipped:personal_noticing_disabled"
    if str(getattr(result, "status", "") or "") != "ran":
        return "skipped:not_ran"
    if int(getattr(result, "result_chars", 0) or 0) < _MIN_RESULT_CHARS:
        return "skipped:thin_result"
    excerpt = str(getattr(result, "text", "") or "").strip()
    if not excerpt:
        return "skipped:empty_text"
    if not is_cross_thread_recall(result, current_thread_id=current_thread_id, user_query=user_query):
        return "skipped:not_cross_thread"
    if _IDENTITY_ONLY_USER_CUES.search(user_query or "") and not MUGI_THREAD_PREFIX_RE.search(
        user_query or ""
    ) and not _UUID_IN_TEXT_RE.search(user_query or ""):
        return "skipped:identity_statement"

    fact = _compose_connection_fact(excerpt)
    from utils.noticing_plaintext import sanitize_noticing_plaintext

    excerpt_hint = sanitize_noticing_plaintext(excerpt, max_len=160)
    rationale_prefix = "Cross-thread recall detected"
    if excerpt_hint:
        rationale_prefix = f"Cross-thread recall: {excerpt_hint}"
    from utils.user_model import BackgroundProposalBudget, propose_background_fact

    budget = BackgroundProposalBudget(max_proposals=1)
    outcome = propose_background_fact(
        workspace,
        fact,
        source="recall_preflight",
        rationale_prefix=rationale_prefix,
        budget=budget,
        section_hint="connections",
    )
    if outcome == "proposal":
        try:
            append_connections_journal(
                workspace,
                [fact],
                source="recall_preflight",
            )
        except Exception:
            _log.debug("recall preflight journal append failed (non-fatal)", exc_info=True)
        return "proposal"
    return f"skipped:{outcome}"
