from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
import sqlite3


@dataclass(frozen=True)
class ConversationSummary:
    session_id: str
    title: str


class ChatHistoryStore:
    """SQLite-backed persistence for chat conversations."""

    def __init__(self, db_path: Path) -> None:
        self._db_path = db_path

    def initialize(self) -> None:
        con = sqlite3.connect(self._db_path)
        try:
            con.execute(
                """
                CREATE TABLE IF NOT EXISTS conversations (
                    id TEXT PRIMARY KEY,
                    title TEXT NOT NULL,
                    created_at TEXT NOT NULL,
                    updated_at TEXT NOT NULL
                )
                """
            )
            con.execute(
                """
                CREATE TABLE IF NOT EXISTS messages (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    conversation_id TEXT NOT NULL,
                    role TEXT NOT NULL,
                    content TEXT NOT NULL,
                    ts TEXT NOT NULL
                )
                """
            )
            con.commit()
        finally:
            con.close()

    @staticmethod
    def _title_from_history(history: list[dict]) -> str:
        last_user_content = ""
        for message in history:
            if message.get("role") == "user":
                last_user_content = str(message.get("content", ""))

        normalized = " ".join(last_user_content.split())
        if not normalized:
            return "Untitled"

        words = normalized.split(" ")
        if len(words) <= 10:
            return normalized
        return f"{' '.join(words[:10])}..."

    def save_conversation(self, session_id: str, history: list[dict]) -> None:
        if not session_id or not history:
            return

        now = datetime.now(timezone.utc).isoformat()
        title = self._title_from_history(history)

        con = sqlite3.connect(self._db_path)
        try:
            row = con.execute("SELECT id FROM conversations WHERE id = ?", (session_id,)).fetchone()

            if row:
                con.execute(
                    "UPDATE conversations SET title = ?, updated_at = ? WHERE id = ?",
                    (title, now, session_id),
                )
            else:
                con.execute(
                    "INSERT INTO conversations (id, title, created_at, updated_at) VALUES (?, ?, ?, ?)",
                    (session_id, title, now, now),
                )

            con.execute("DELETE FROM messages WHERE conversation_id = ?", (session_id,))
            con.executemany(
                "INSERT INTO messages (conversation_id, role, content, ts) VALUES (?, ?, ?, ?)",
                [(session_id, m.get("role", ""), m.get("content", ""), now) for m in history],
            )
            con.commit()
        finally:
            con.close()

    def list_conversations(self, limit: int = 100) -> list[ConversationSummary]:
        con = sqlite3.connect(self._db_path)
        try:
            rows = con.execute(
                "SELECT id, title FROM conversations ORDER BY updated_at DESC LIMIT ?",
                (limit,),
            ).fetchall()
            return [ConversationSummary(session_id=row[0], title=row[1]) for row in rows]
        finally:
            con.close()

    def load_conversation(self, session_id: str) -> list[dict]:
        if not session_id:
            return []

        con = sqlite3.connect(self._db_path)
        try:
            rows = con.execute(
                "SELECT role, content FROM messages WHERE conversation_id = ? ORDER BY id",
                (session_id,),
            ).fetchall()
            return [{"role": row[0], "content": row[1]} for row in rows]
        finally:
            con.close()
