"""TemporalTracker: tracks fact changes over time for temporal awareness."""

import uuid
from datetime import datetime, timezone
from typing import Optional

from memotrail.storage import SQLiteStore
from memotrail.utils import get_logger

logger = get_logger("memotrail.core.temporal")

# Schema for fact_history table (added to SQLiteStore)
FACT_HISTORY_SCHEMA = """
CREATE TABLE IF NOT EXISTS fact_history (
    id TEXT PRIMARY KEY,
    fact_type TEXT NOT NULL,
    fact_id TEXT NOT NULL,
    previous_value TEXT,
    new_value TEXT NOT NULL,
    change_type TEXT NOT NULL,
    session_id TEXT REFERENCES sessions(id),
    changed_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_fact_history_fact ON fact_history(fact_id);
CREATE INDEX IF NOT EXISTS idx_fact_history_time ON fact_history(changed_at);
"""


class TemporalTracker:
    """Tracks changes to facts (decisions, memories, entity relations) over time.

    Answers questions like "How did this decision evolve?" and
    "What was the state of knowledge at time X?"
    """

    def __init__(self, sqlite_store: SQLiteStore | None = None):
        self.sqlite = sqlite_store or SQLiteStore()
        self._ensure_schema()

    def _ensure_schema(self) -> None:
        """Create fact_history table if it doesn't exist."""
        try:
            self.sqlite.conn.executescript(FACT_HISTORY_SCHEMA)
        except Exception as e:
            logger.warning(f"Failed to create fact_history table: {e}")

    def record_change(
        self,
        fact_type: str,
        fact_id: str,
        new_value: str,
        change_type: str,
        previous_value: Optional[str] = None,
        session_id: Optional[str] = None,
    ) -> str:
        """Record a change to a fact.

        Args:
            fact_type: "decision", "memory", or "entity_relation"
            fact_id: ID of the fact that changed
            new_value: New text/value
            change_type: "created", "updated", "deleted", "contradicted"
            previous_value: Previous text/value (if applicable)
            session_id: Session that triggered the change

        Returns:
            History entry ID
        """
        entry_id = f"hist_{uuid.uuid4().hex[:12]}"
        now = datetime.now(timezone.utc).isoformat()

        self.sqlite.conn.execute(
            "INSERT INTO fact_history "
            "(id, fact_type, fact_id, previous_value, new_value, change_type, session_id, changed_at) "
            "VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
            (entry_id, fact_type, fact_id, previous_value, new_value, change_type, session_id, now),
        )
        self.sqlite.conn.commit()

        logger.info(f"Recorded {change_type} for {fact_type} {fact_id}")
        return entry_id

    def get_fact_history(self, fact_id: str) -> list[dict]:
        """Get the full change history for a fact.

        Args:
            fact_id: ID of the fact

        Returns:
            List of history entries, oldest first
        """
        rows = self.sqlite.conn.execute(
            "SELECT * FROM fact_history WHERE fact_id = ? ORDER BY changed_at ASC",
            (fact_id,),
        ).fetchall()
        return [dict(r) for r in rows]

    def get_fact_at_time(self, fact_id: str, timestamp: str) -> Optional[dict]:
        """Get the state of a fact at a specific point in time.

        Returns the most recent change entry at or before the given timestamp.

        Args:
            fact_id: ID of the fact
            timestamp: ISO timestamp

        Returns:
            History entry dict or None
        """
        row = self.sqlite.conn.execute(
            "SELECT * FROM fact_history WHERE fact_id = ? AND changed_at <= ? "
            "ORDER BY changed_at DESC LIMIT 1",
            (fact_id, timestamp),
        ).fetchone()
        return dict(row) if row else None

    def get_changes_in_range(
        self,
        start: str,
        end: str,
        fact_type: Optional[str] = None,
    ) -> list[dict]:
        """Get all changes within a time range.

        Args:
            start: Start ISO timestamp
            end: End ISO timestamp
            fact_type: Optional filter by fact type

        Returns:
            List of history entries
        """
        if fact_type:
            rows = self.sqlite.conn.execute(
                "SELECT * FROM fact_history "
                "WHERE changed_at >= ? AND changed_at <= ? AND fact_type = ? "
                "ORDER BY changed_at ASC",
                (start, end, fact_type),
            ).fetchall()
        else:
            rows = self.sqlite.conn.execute(
                "SELECT * FROM fact_history "
                "WHERE changed_at >= ? AND changed_at <= ? "
                "ORDER BY changed_at ASC",
                (start, end),
            ).fetchall()
        return [dict(r) for r in rows]

    def get_recent_changes(self, limit: int = 20) -> list[dict]:
        """Get the most recent changes across all facts.

        Args:
            limit: Max results

        Returns:
            List of history entries, newest first
        """
        rows = self.sqlite.conn.execute(
            "SELECT * FROM fact_history ORDER BY changed_at DESC LIMIT ?",
            (limit,),
        ).fetchall()
        return [dict(r) for r in rows]
