"""
Memory Selector — Decides which memory layers to include.

PRD §9 — Memory Selection Rules:
    experience:    always include (core)
    user_memory:   top 3 preferences + top 2 constraints
    context:       summary + latest events
    task_memory:   shared task state
    team_memory:   only if relevant (task_type in [deployment, planning])
"""

import logging
from typing import Dict, Any, Optional

logger = logging.getLogger("openmemo.orchestrator")

# Task types that warrant team memory inclusion (PRD §9)
_TEAM_RELEVANT_TASKS = {"deployment", "planning", "coding"}


class MemorySelector:
    """
    Decides which memory layers to fetch and how to constrain them.

    Returns a SelectionPlan describing what to include from each layer.

    Usage:
        selector = MemorySelector()
        plan = selector.select("deployment", user_id="alice", session_id="s1")
        # plan.include_team  → True
        # plan.context_level → 2  (summary + timeline)
    """

    def select(self, task_type: str = "coding",
               user_id: str = "", session_id: str = "",
               agent_id: str = "", team_id: str = "") -> "SelectionPlan":
        """
        Build a SelectionPlan for the given task context.
        """
        plan = SelectionPlan(
            task_type=task_type,
            user_id=user_id,
            session_id=session_id,
            agent_id=agent_id,
            team_id=team_id,
        )

        # §9: Experience — always include
        plan.include_experience = True

        # §9: User Memory — always include when user_id present
        plan.include_user_memory = bool(user_id)
        plan.user_memory_top_n = 5           # 3 preferences + 2 constraints

        # §9: Context Memory — include when session_id present
        plan.include_context = bool(session_id)
        plan.context_level = self._context_level(task_type)

        # §9: Task Memory — shared task state (always if agent_id)
        plan.include_task_memory = bool(agent_id)

        # §9: Team Memory — only if relevant task type and team_id
        plan.include_team_memory = (
            bool(team_id) and task_type in _TEAM_RELEVANT_TASKS
        )

        logger.debug("select task=%s plan=%s", task_type, plan.summary())
        return plan

    def _context_level(self, task_type: str) -> int:
        """
        Choose progressive recall level based on task type.

        debug/deployment → level 2 (summary + timeline)
        research/planning → level 1 (summary only)
        others → level 2
        """
        if task_type in ("research", "planning"):
            return 1
        return 2   # summary + timeline events by default


class SelectionPlan:
    """
    Describes which memory layers to include and their constraints.
    """

    def __init__(self, task_type: str = "coding", user_id: str = "",
                 session_id: str = "", agent_id: str = "", team_id: str = ""):
        self.task_type = task_type
        self.user_id = user_id
        self.session_id = session_id
        self.agent_id = agent_id
        self.team_id = team_id

        self.include_experience = True
        self.include_user_memory = False
        self.include_context = False
        self.include_task_memory = False
        self.include_team_memory = False

        self.user_memory_top_n = 5
        self.context_level = 2         # 1=summary, 2=+timeline, 3=+raw
        self.experience_top_k = 3

    def enabled_layers(self) -> list:
        layers = []
        if self.include_experience:
            layers.append("experience")
        if self.include_user_memory:
            layers.append("user_memory")
        if self.include_context:
            layers.append("context")
        if self.include_task_memory:
            layers.append("task_memory")
        if self.include_team_memory:
            layers.append("team_memory")
        return layers

    def summary(self) -> dict:
        return {
            "task_type": self.task_type,
            "layers": self.enabled_layers(),
            "context_level": self.context_level,
            "user_memory_top_n": self.user_memory_top_n,
        }

    def to_dict(self) -> dict:
        return {
            "task_type": self.task_type,
            "user_id": self.user_id,
            "session_id": self.session_id,
            "agent_id": self.agent_id,
            "team_id": self.team_id,
            "include_experience": self.include_experience,
            "include_user_memory": self.include_user_memory,
            "include_context": self.include_context,
            "include_task_memory": self.include_task_memory,
            "include_team_memory": self.include_team_memory,
            "context_level": self.context_level,
            "user_memory_top_n": self.user_memory_top_n,
            "experience_top_k": self.experience_top_k,
        }
