"""Memory categories with TTL tier mappings.

Defines the 11 memory categories used by the claude-engram daemon,
their TTL tiers (ephemeral, volatile, session, permanent), and
utility functions for validation and TTL lookup.
"""

from __future__ import annotations

from enum import StrEnum


class MemoryCategory(StrEnum):
    """The 12 memory categories managed by claude-engram."""

    FILE_OWNERSHIP = "file_ownership"
    INTERFACE = "interface"
    QUERY_CACHE = "query_cache"
    LESSON = "lesson"
    CHECKPOINT = "checkpoint"
    SESSION_SUMMARY = "session_summary"
    DECISION = "decision"
    WORKER_MSG = "worker_msg"  # Inter-worker communication (#52)
    # Phase 6: Agent Coordination categories
    FILE_CLAIM = "file_claim"  # Advisory file/symbol ownership claims
    INTERFACE_BROADCAST = "interface_broadcast"  # Public API announcements
    COORDINATION_EVENT = "coordination_event"  # Event log entries
    # H9: Passive capture — ideas survive 7 days, promoted to decisions manually
    IDEA = "idea"


class TTLTier(StrEnum):
    """TTL volatility tiers for memory expiration."""

    EPHEMERAL = "ephemeral"  # ~5 min
    SHORT = "short"  # ~30 min (worker messages)
    VOLATILE = "volatile"  # ~4 hours
    SESSION = "session"  # ~7 days
    PERMANENT = "permanent"  # no TTL


# Mapping from TTL tier to seconds (None = never expires)
TTL_MAP: dict[TTLTier, int | None] = {
    TTLTier.EPHEMERAL: 300,  # 5 minutes
    TTLTier.SHORT: 1800,  # 30 minutes (worker messages)
    TTLTier.VOLATILE: 14400,  # 4 hours
    TTLTier.SESSION: 604800,  # 7 days
    TTLTier.PERMANENT: None,
}

# Mapping from category to its TTL tier
CATEGORY_TTL: dict[MemoryCategory, TTLTier] = {
    MemoryCategory.FILE_OWNERSHIP: TTLTier.SESSION,
    MemoryCategory.INTERFACE: TTLTier.SESSION,
    MemoryCategory.QUERY_CACHE: TTLTier.EPHEMERAL,
    MemoryCategory.LESSON: TTLTier.PERMANENT,
    MemoryCategory.CHECKPOINT: TTLTier.VOLATILE,
    MemoryCategory.SESSION_SUMMARY: TTLTier.SESSION,
    MemoryCategory.DECISION: TTLTier.SESSION,
    MemoryCategory.WORKER_MSG: TTLTier.SHORT,  # 30-min TTL (#52)
    # Phase 6: Agent Coordination categories
    MemoryCategory.FILE_CLAIM: TTLTier.VOLATILE,  # 4h TTL, active claims expire
    MemoryCategory.INTERFACE_BROADCAST: TTLTier.SESSION,  # 7d, persist while symbol exists
    MemoryCategory.COORDINATION_EVENT: TTLTier.SESSION,  # 7d, matches history retention
    MemoryCategory.IDEA: TTLTier.SESSION,  # 7d, ideas that survive get promoted manually
}

# Categories that represent durable cross-window knowledge.
# Used by what_changed to detect memories written by other sessions.
# NOTE: file_claim is NOT included -- claims are checked on-demand via hook,
# not injected at session start.
CROSS_WINDOW_CATEGORIES: frozenset[str] = frozenset(
    {
        "decision",
        "lesson",
        "interface",
        "session_summary",
        "interface_broadcast",  # Agents need to see each other's interfaces
        "coordination_event",  # Agents need to see coordination events
        "idea",  # Ideas should be visible across windows for promotion
    }
)

# Legacy category name kept for backward compatibility with v1 memories
_LEGACY_CATEGORY = "general"


def validate_category(category: str) -> MemoryCategory | str:
    """Validate and return a MemoryCategory enum value.

    Accepts case-insensitive strings. Returns the legacy "general" string
    unchanged for backward compatibility with existing v1 memories.

    Args:
        category: Category name (case-insensitive).

    Returns:
        MemoryCategory enum value, or the string "general" for legacy data.

    Raises:
        ValueError: If category is not a known MemoryCategory or "general".
    """
    normalized = category.strip().lower()

    if normalized == _LEGACY_CATEGORY:
        return _LEGACY_CATEGORY

    try:
        return MemoryCategory(normalized)
    except ValueError:
        valid = [c.value for c in MemoryCategory] + [_LEGACY_CATEGORY]
        msg = f"Unknown category '{category}'. Valid categories: {valid}"
        raise ValueError(msg) from None


def get_ttl_seconds(category: MemoryCategory) -> int | None:
    """Get TTL in seconds for a memory category.

    Args:
        category: A MemoryCategory enum value.

    Returns:
        TTL in seconds, or None for permanent categories.
    """
    tier = CATEGORY_TTL[category]
    return TTL_MAP[tier]
