"""Timmy's thinking engine — public façade.

When the server starts, Timmy begins pondering: reflecting on his existence,
recent swarm activity, scripture, creative ideas, or pure stream of
consciousness.  Each thought builds on the previous one, maintaining a
continuous chain of introspection.

Usage::

    from timmy.thinking import thinking_engine

    # Run one thinking cycle (called by the background loop)
    await thinking_engine.think_once()

    # Query the thought stream
    thoughts = thinking_engine.get_recent_thoughts(limit=10)
    chain = thinking_engine.get_thought_chain(thought_id)
"""

import logging
import sqlite3
from datetime import datetime
from pathlib import Path

# Re-export HOT_MEMORY_PATH and SOUL_PATH so existing patch targets continue to work.
# Tests that patch "timmy.thinking.HOT_MEMORY_PATH" or "timmy.thinking.SOUL_PATH"
# should instead patch "timmy.thinking._snapshot.HOT_MEMORY_PATH" etc., but these
# re-exports are kept for any code that reads them from the top-level namespace.
from timmy.memory_system import HOT_MEMORY_PATH, SOUL_PATH  # noqa: F401
from timmy.thinking._db import Thought, _get_conn
from timmy.thinking.engine import ThinkingEngine
from timmy.thinking.seeds import (
    _META_OBSERVATION_PHRASES,
    _SENSITIVE_PATTERNS,
    _THINK_TAG_RE,
    _THINKING_PROMPT,
    SEED_TYPES,
)

logger = logging.getLogger(__name__)

# Module-level singleton
thinking_engine = ThinkingEngine()

__all__ = [
    "ThinkingEngine",
    "Thought",
    "SEED_TYPES",
    "thinking_engine",
    "search_thoughts",
    "_THINKING_PROMPT",
    "_SENSITIVE_PATTERNS",
    "_META_OBSERVATION_PHRASES",
    "_THINK_TAG_RE",
    "HOT_MEMORY_PATH",
    "SOUL_PATH",
]


# ── Search helpers ─────────────────────────────────────────────────────────


def _query_thoughts(
    db_path: Path, query: str, seed_type: str | None, limit: int
) -> list[sqlite3.Row]:
    """Run the thought-search SQL and return matching rows."""
    pattern = f"%{query}%"
    with _get_conn(db_path) as conn:
        if seed_type:
            return conn.execute(
                """
                SELECT id, content, seed_type, created_at
                FROM thoughts
                WHERE content LIKE ? AND seed_type = ?
                ORDER BY created_at DESC
                LIMIT ?
                """,
                (pattern, seed_type, limit),
            ).fetchall()
        return conn.execute(
            """
            SELECT id, content, seed_type, created_at
            FROM thoughts
            WHERE content LIKE ?
            ORDER BY created_at DESC
            LIMIT ?
            """,
            (pattern, limit),
        ).fetchall()


def _format_thought_rows(rows: list[sqlite3.Row], query: str, seed_type: str | None) -> str:
    """Format thought rows into a human-readable string."""
    lines = [f'Found {len(rows)} thought(s) matching "{query}":']
    if seed_type:
        lines[0] += f' [seed_type="{seed_type}"]'
    lines.append("")

    for row in rows:
        ts = datetime.fromisoformat(row["created_at"])
        local_ts = ts.astimezone()
        time_str = local_ts.strftime("%Y-%m-%d %I:%M %p").lstrip("0")
        seed = row["seed_type"]
        content = row["content"].replace("\n", " ")  # Flatten newlines for display
        lines.append(f"[{time_str}] ({seed}) {content[:150]}")

    return "\n".join(lines)


def search_thoughts(query: str, seed_type: str | None = None, limit: int = 10) -> str:
    """Search Timmy's thought history for reflections matching a query.

    Use this tool when Timmy needs to recall his previous thoughts on a topic,
    reflect on past insights, or build upon earlier reflections. This enables
    self-awareness and continuity of thinking across time.

    Args:
        query: Search term to match against thought content (case-insensitive).
        seed_type: Optional filter by thought category (e.g., 'existential',
                   'swarm', 'sovereignty', 'creative', 'memory', 'observation').
        limit: Maximum number of thoughts to return (default 10, max 50).

    Returns:
        Formatted string with matching thoughts, newest first, including
        timestamps and seed types. Returns a helpful message if no matches found.
    """
    limit = max(1, min(limit, 50))

    try:
        rows = _query_thoughts(thinking_engine._db_path, query, seed_type, limit)

        if not rows:
            if seed_type:
                return f'No thoughts found matching "{query}" with seed_type="{seed_type}".'
            return f'No thoughts found matching "{query}".'

        return _format_thought_rows(rows, query, seed_type)

    except Exception as exc:
        logger.warning("Thought search failed: %s", exc)
        return f"Error searching thoughts: {exc}"
