"""ConversationLog — append-only SQLite store for raw conversation capture."""

import json
import sqlite3
import time
from pathlib import Path

from neo_cortex.models import ConversationEntry, ConversationAppendRequest


class ConversationLog:
    """Append-only SQLite log. Every message, every event, nothing lost."""

    def __init__(self, db_path: str):
        Path(db_path).parent.mkdir(parents=True, exist_ok=True)
        self._conn = sqlite3.connect(db_path, check_same_thread=False)
        self._conn.row_factory = sqlite3.Row
        self._conn.execute("PRAGMA journal_mode=WAL")
        self._create_table()

    def _create_table(self):
        self._conn.execute("""
            CREATE TABLE IF NOT EXISTS conversation_log (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp REAL NOT NULL,
                session_id TEXT NOT NULL,
                role TEXT NOT NULL,
                content TEXT NOT NULL,
                event_type TEXT,
                model TEXT,
                metadata TEXT
            )
        """)
        self._conn.execute("""
            CREATE INDEX IF NOT EXISTS idx_log_session
            ON conversation_log(session_id)
        """)
        self._conn.execute("""
            CREATE INDEX IF NOT EXISTS idx_log_timestamp
            ON conversation_log(timestamp DESC)
        """)
        self._conn.commit()

    def append(self, request: ConversationAppendRequest) -> int:
        """Append a single entry. Returns the row ID."""
        ts = request.timestamp or time.time()
        meta_json = json.dumps(request.metadata) if request.metadata else None
        cursor = self._conn.execute(
            """INSERT INTO conversation_log
               (timestamp, session_id, role, content, event_type, model, metadata)
               VALUES (?, ?, ?, ?, ?, ?, ?)""",
            (ts, request.session_id, request.role, request.content,
             request.event_type, request.model, meta_json),
        )
        self._conn.commit()
        return cursor.lastrowid

    def get_session(self, session_id: str) -> list[ConversationEntry]:
        """Get all entries for a session, ordered by timestamp."""
        rows = self._conn.execute(
            """SELECT * FROM conversation_log
               WHERE session_id = ?
               ORDER BY timestamp ASC""",
            (session_id,),
        ).fetchall()
        return [self._row_to_entry(r) for r in rows]

    def get_recent(self, n: int = 50) -> list[ConversationEntry]:
        """Get the N most recent entries across all sessions."""
        rows = self._conn.execute(
            """SELECT * FROM conversation_log
               ORDER BY timestamp DESC LIMIT ?""",
            (n,),
        ).fetchall()
        return [self._row_to_entry(r) for r in reversed(rows)]

    def get_sessions(self) -> list[dict]:
        """List all sessions with entry counts."""
        rows = self._conn.execute(
            """SELECT session_id, COUNT(*) as entries,
                      MIN(timestamp) as first_ts, MAX(timestamp) as last_ts
               FROM conversation_log
               GROUP BY session_id
               ORDER BY last_ts DESC"""
        ).fetchall()
        return [dict(r) for r in rows]

    def count(self) -> int:
        row = self._conn.execute("SELECT COUNT(*) FROM conversation_log").fetchone()
        return row[0]

    def _row_to_entry(self, row: sqlite3.Row) -> ConversationEntry:
        meta = json.loads(row["metadata"]) if row["metadata"] else None
        return ConversationEntry(
            id=row["id"],
            timestamp=row["timestamp"],
            session_id=row["session_id"],
            role=row["role"],
            content=row["content"],
            event_type=row["event_type"],
            model=row["model"],
            metadata=meta,
        )
