"""Redis publish helpers — Stream + pub/sub."""

from __future__ import annotations

import json

from redis.asyncio import Redis

from loom.bus import channels
from loom.bus.events import EventType


async def publish_event(
    redis: Redis,
    project_id: str,
    event_type: EventType,
    task_id: str | None = None,
    agent_id: str | None = None,
    payload: dict | None = None,
) -> str:
    """Publish an event to both the Redis Stream and the pub/sub updates channel."""
    data = {
        "event_type": event_type.value,
        "task_id": task_id or "",
        "agent_id": agent_id or "",
        "payload": json.dumps(payload or {}),
    }
    # Append to the persistent event stream
    stream_id = await redis.xadd(channels.event_stream(project_id), data)
    # Publish to the real-time updates channel
    await redis.publish(channels.updates_channel(project_id), json.dumps(data))
    return stream_id


async def publish_escalation(
    redis: Redis,
    project_id: str,
    task_id: str,
    message: str,
) -> None:
    """Publish an escalation to the escalation channel and queue."""
    data = json.dumps({"task_id": task_id, "message": message})
    await redis.publish(channels.escalation_channel(project_id), data)
    await redis.lpush(channels.escalation_queue(project_id), data)


async def send_agent_message(
    redis: Redis,
    project_id: str,
    to: str,
    message: str,
    thread_id: str | None = None,
) -> None:
    """Send a direct message to an agent via pub/sub."""
    data = json.dumps({
        "to": to,
        "message": message,
        "thread_id": thread_id or "",
    })
    if to == "broadcast":
        await redis.publish(channels.broadcast_channel(project_id), data)
    else:
        await redis.publish(channels.agent_channel(project_id, to), data)
