"""Persistent history manager — saves AI interactions to disk."""

from __future__ import annotations

import logging
import os
import threading
import time
from typing import TypedDict, cast

from .utils.atomic_io import atomic_write_json, safe_load_json

log = logging.getLogger(__name__)


class HistoryEntry(TypedDict, total=False):
    """Type definition for history entry."""

    timestamp: float
    time: str
    text: str
    template: str
    result: str
    provider: str
    tokens: int


class HistoryManager:
    """Thread-safe persistent history manager with batched autosave."""

    def __init__(
        self,
        data_dir: str | None = None,
        max_entries: int = 1000,
        autosave_interval: int = 10,
    ) -> None:
        self.max_entries: int = max_entries
        self.autosave_interval: int = autosave_interval
        self.data_dir: str = data_dir or os.path.expanduser("~/.muravey-china")
        os.makedirs(self.data_dir, exist_ok=True)
        self.history_path: str = os.path.join(self.data_dir, "history.json")
        self._lock: threading.Lock = threading.Lock()
        self._entries: list[HistoryEntry] = self._load()
        self._pending_saves: int = 0

    def _load(self) -> list[HistoryEntry]:
        data = safe_load_json(self.history_path, default=[])
        if isinstance(data, list):
            log.info("Loaded %d history entries", len(data))
            return cast(list[HistoryEntry], data)
        log.warning("Invalid history format, using empty list")
        return []

    def _save(self) -> None:
        try:
            atomic_write_json(self.history_path, self._entries)
        except OSError as e:
            log.warning("Failed to save history: %s", e)

    def add(
        self,
        text: str,
        template: str,
        result: str,
        provider: str = "",
        tokens: int = 0,
    ) -> HistoryEntry:
        """Add a history entry. Auto-saves every N adds."""
        entry: HistoryEntry = {
            "timestamp": time.time(),
            "time": time.strftime("%Y-%m-%d %H:%M:%S"),
            "text": text[:500],
            "template": template,
            "result": result[:2000],
            "provider": provider,
            "tokens": tokens,
        }
        with self._lock:
            self._entries.append(entry)
            if len(self._entries) > self.max_entries:
                self._entries = self._entries[-self.max_entries :]
            self._pending_saves += 1
            if self._pending_saves >= self.autosave_interval:
                self._save()
                self._pending_saves = 0
        return entry

    def get_recent(self, n: int = 10) -> list[HistoryEntry]:
        """Get the N most recent entries."""
        with self._lock:
            return list(self._entries[-n:])

    def search(self, query: str) -> list[HistoryEntry]:
        """Full-text search in text and result fields."""
        q = query.lower()
        with self._lock:
            return [
                e
                for e in self._entries
                if q in e.get("text", "").lower() or q in e.get("result", "").lower()
            ]

    def clear(self) -> None:
        """Clear all history entries."""
        with self._lock:
            self._entries = []
            self._pending_saves = 0
            self._save()
        log.info("History cleared")

    def flush(self) -> None:
        """Force save pending changes immediately."""
        with self._lock:
            if self._pending_saves > 0:
                self._save()
                self._pending_saves = 0

    def get_all(self) -> list[HistoryEntry]:
        """Return a copy of all history entries."""
        with self._lock:
            return list(self._entries)

    @property
    def count(self) -> int:
        with self._lock:
            return len(self._entries)
