"""ScopedMemoryManager: memory scopes for multi-project isolation."""

import json
from enum import Enum
from typing import Optional

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

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


class MemoryScope(Enum):
    """Memory visibility scope."""
    USER = "user"          # Visible across all projects
    PROJECT = "project"    # Visible only within a specific project
    SESSION = "session"    # Visible only within the originating session


class ScopedMemoryManager:
    """Manages memory access based on scope and project context.

    Memories can be scoped to:
    - user: Global, visible everywhere
    - project: Only visible within a specific project
    - session: Only visible within the session that created them
    """

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

    def _ensure_scope_column(self) -> None:
        """Ensure the scope column exists on the memories table."""
        try:
            self.sqlite.conn.execute("SELECT scope FROM memories LIMIT 1")
        except Exception:
            try:
                self.sqlite.conn.execute(
                    "ALTER TABLE memories ADD COLUMN scope TEXT DEFAULT 'user'"
                )
                self.sqlite.conn.execute(
                    "ALTER TABLE memories ADD COLUMN project TEXT"
                )
                self.sqlite.conn.commit()
            except Exception:
                pass  # Columns may already exist

    def save_memory(
        self,
        content: str,
        tags: Optional[list[str]] = None,
        scope: MemoryScope = MemoryScope.USER,
        project: Optional[str] = None,
    ) -> str:
        """Save a memory with scope.

        Args:
            content: Memory text
            tags: Optional tags
            scope: Visibility scope
            project: Required if scope is PROJECT

        Returns:
            Memory ID
        """
        if scope == MemoryScope.PROJECT and not project:
            raise ValueError("Project is required for PROJECT scope")

        memory_id = self.sqlite.save_memory(content, tags)

        # Update scope and project
        self.sqlite.conn.execute(
            "UPDATE memories SET scope = ?, project = ? WHERE id = ?",
            (scope.value, project, memory_id),
        )
        self.sqlite.conn.commit()

        logger.info(f"Saved memory {memory_id} with scope={scope.value}, project={project}")
        return memory_id

    def get_memories(
        self,
        scope: Optional[MemoryScope] = None,
        project: Optional[str] = None,
    ) -> list[dict]:
        """Get memories filtered by scope and project.

        If no scope is specified, returns all visible memories for the given
        project context (user-scoped + project-scoped for that project).

        Args:
            scope: Optional scope filter
            project: Optional project context

        Returns:
            List of memory dicts
        """
        if scope:
            if scope == MemoryScope.PROJECT and project:
                rows = self.sqlite.conn.execute(
                    "SELECT * FROM memories WHERE scope = 'project' AND project = ? "
                    "ORDER BY updated_at DESC",
                    (project,),
                ).fetchall()
            elif scope == MemoryScope.USER:
                rows = self.sqlite.conn.execute(
                    "SELECT * FROM memories WHERE scope = 'user' ORDER BY updated_at DESC"
                ).fetchall()
            else:
                rows = self.sqlite.conn.execute(
                    "SELECT * FROM memories WHERE scope = ? ORDER BY updated_at DESC",
                    (scope.value,),
                ).fetchall()
        elif project:
            # Return user-scoped + project-scoped for this project
            rows = self.sqlite.conn.execute(
                "SELECT * FROM memories WHERE scope = 'user' "
                "OR (scope = 'project' AND project = ?) "
                "ORDER BY updated_at DESC",
                (project,),
            ).fetchall()
        else:
            rows = self.sqlite.conn.execute(
                "SELECT * FROM memories ORDER BY updated_at DESC"
            ).fetchall()

        return [
            {
                "id": r["id"],
                "content": r["content"],
                "tags": json.loads(r["tags"]),
                "scope": r["scope"] if "scope" in r.keys() else "user",
                "project": r["project"] if "project" in r.keys() else None,
                "created_at": r["created_at"],
                "updated_at": r["updated_at"],
            }
            for r in rows
        ]

    def update_scope(
        self,
        memory_id: str,
        scope: MemoryScope,
        project: Optional[str] = None,
    ) -> None:
        """Change the scope of an existing memory.

        Args:
            memory_id: Memory ID to update
            scope: New scope
            project: Required if scope is PROJECT
        """
        if scope == MemoryScope.PROJECT and not project:
            raise ValueError("Project is required for PROJECT scope")

        self.sqlite.conn.execute(
            "UPDATE memories SET scope = ?, project = ? WHERE id = ?",
            (scope.value, project, memory_id),
        )
        self.sqlite.conn.commit()
        logger.info(f"Updated memory {memory_id} scope to {scope.value}")
