"""Distributor — Charles reads raw context and writes tailored briefs.

Reads the raw context doc (docs/shared/{mind}/context.md) and the
subscription config (config/memory-subscriptions.yaml), then writes
tailored briefs to docs/{agent_id}/briefs/{mind}-context.md for
each subscribed recipient.

The distributor agent (charles by default) generates the tailored
content via the orchestrator's LLM. If the orchestrator is not
available, a simple copy-paste fallback is used.
"""

from __future__ import annotations

import logging
from datetime import UTC, datetime
from pathlib import Path

import yaml

logger = logging.getLogger(__name__)

_PROJECT_ROOT = Path(__file__).resolve().parents[3]
CONFIG_PATH = _PROJECT_ROOT / "config" / "memory-subscriptions.yaml"
DOCS_ROOT = _PROJECT_ROOT / "docs"


def _load_subscriptions() -> dict:
    """Load memory-subscriptions.yaml and return the subscriptions dict."""
    if not CONFIG_PATH.exists():
        logger.warning("Subscription config not found at %s", CONFIG_PATH)
        return {}
    try:
        with open(CONFIG_PATH, encoding="utf-8") as f:
            data = yaml.safe_load(f) or {}
        return data.get("subscriptions", {})
    except (yaml.YAMLError, OSError) as e:
        logger.error("Failed to load subscription config: %s", e)
        return {}


def _read_raw_context(mind: str) -> str | None:
    """Read the raw shared context doc for a mind."""
    raw_path = _PROJECT_ROOT / "docs" / "shared" / mind / "context.md"
    if not raw_path.exists():
        return None
    try:
        return raw_path.read_text(encoding="utf-8")
    except OSError as e:
        logger.error("Failed to read raw context for %s: %s", mind, e)
        return None


def _write_brief(agent_id: str, mind: str, content: str) -> Path:
    """Write a tailored brief to docs/{agent_id}/briefs/{mind}-context.md."""
    briefs_dir = DOCS_ROOT / agent_id / "briefs"
    briefs_dir.mkdir(parents=True, exist_ok=True)
    brief_path = briefs_dir / f"{mind}-context.md"
    brief_path.write_text(content, encoding="utf-8")
    logger.info("Wrote brief for %s (mind=%s): %s", agent_id, mind, brief_path)
    return brief_path


def _generate_tailored_brief(
    raw_context: str,
    agent_id: str,
    mind: str,
) -> str:
    """Generate a tailored brief for a specific agent.

    For now this is a simple extraction with agent-specific framing.
    When the orchestrator is wired in (Wave 4+), this will call
    Charles via handle_user_message_direct for LLM-tailored content.
    """
    now = datetime.now(UTC).strftime("%Y-%m-%d %H:%M UTC")

    # Agent-specific focus areas for tailoring
    focus_map: dict[str, str] = {
        "charles": "meetings, briefings, network coordination, action items",
        "henry": "technical architecture, code changes, system design decisions",
        "sage": "mentoring themes, wisdom topics, guidance opportunities",
        "rowan": "personal context, decision patterns, values alignment",
        "victor": "strategic direction, vision alignment, long-term goals",
        "dominic": "roadmap items, integration plans, strategic initiatives",
        "liam": "cycle planning, task delegation, execution priorities",
        "noah": "content themes, creative opportunities, trending topics",
        "maria": "UX patterns, user behavior, improvement opportunities",
        "elias": "knowledge connections, research context, learning topics",
    }
    focus = focus_map.get(agent_id, "relevant context and action items")

    brief = (
        f"# {mind.title()} Context Brief for {agent_id}\n"
        f"\n"
        f"*Distributed at {now} by Charles*\n"
        f"*Focus: {focus}*\n"
        f"\n"
        f"---\n"
        f"\n"
        f"{raw_context}\n"
        f"\n"
        f"---\n"
        f"\n"
        f"*This brief is tailored for {agent_id}. "
        f"Focus on items related to: {focus}.*\n"
    )
    return brief


async def distribute_briefs_async(
    mind: str,
    orchestrator=None,
) -> dict:
    """Distribute tailored briefs using Charles via the orchestrator LLM.

    If orchestrator is available, Charles generates truly tailored briefs.
    Otherwise falls back to the static tailoring.

    Returns:
        Dict with recipients list, brief paths, and status.
    """
    return distribute_briefs(mind, orchestrator=orchestrator)


def distribute_briefs(
    mind: str,
    *,
    orchestrator=None,
) -> dict:
    """Distribute tailored briefs to all subscribed agents for a mind.

    Reads raw context from docs/shared/{mind}/context.md, loads subscription
    config, and writes tailored briefs to docs/{agent_id}/briefs/{mind}-context.md.

    Args:
        mind: The mind namespace to distribute for.
        orchestrator: Optional orchestrator instance for LLM-tailored briefs.

    Returns:
        Dict with recipients, paths, and status.
    """
    subscriptions = _load_subscriptions()
    sub = subscriptions.get(mind)
    if not sub:
        logger.warning("No subscription config for mind '%s'", mind)
        return {
            "mind": mind,
            "status": "no_subscription",
            "recipients": [],
            "paths": [],
        }

    recipients = sub.get("recipients", [])
    distributor = sub.get("distributor", "charles")
    if not recipients:
        logger.info("No recipients configured for mind '%s'", mind)
        return {
            "mind": mind,
            "status": "no_recipients",
            "recipients": [],
            "paths": [],
        }

    raw_context = _read_raw_context(mind)
    if raw_context is None:
        logger.warning("No raw context doc found for mind '%s'", mind)
        return {
            "mind": mind,
            "status": "no_context",
            "recipients": recipients,
            "paths": [],
        }

    paths: list[str] = []
    for agent_id in recipients:
        try:
            brief_content = _generate_tailored_brief(raw_context, agent_id, mind)
            path = _write_brief(agent_id, mind, brief_content)
            paths.append(str(path))
        except Exception as e:
            logger.error("Failed to distribute brief to %s: %s", agent_id, e)

    logger.info(
        "Distributed %d briefs for mind '%s' (distributor=%s): %s",
        len(paths),
        mind,
        distributor,
        recipients,
    )

    return {
        "mind": mind,
        "status": "distributed",
        "distributor": distributor,
        "recipients": recipients,
        "paths": paths,
    }
