"""Redis Streams queue service.

Streams used:
  media:download  — yt-dlp download jobs
  ai:analyze      — AI analysis jobs
  ai:embed        — embedding generation jobs
  notif:send      — Telegram notification jobs
  dlq             — dead-letter queue for permanently failed jobs
"""
from __future__ import annotations

import json

import redis.asyncio as aioredis
import structlog

log = structlog.get_logger(__name__)

STREAM_DOWNLOAD = "media:download"
STREAM_AI = "ai:analyze"
STREAM_EMBED = "ai:embed"
STREAM_NOTIF = "notif:send"
STREAM_DLQ = "dlq"

ALL_STREAMS = (STREAM_DOWNLOAD, STREAM_AI, STREAM_EMBED, STREAM_NOTIF)


class QueueService:
    def __init__(self, redis_client: aioredis.Redis) -> None:
        self._r = redis_client

    async def enqueue(self, stream: str, **fields: str) -> str:
        """Add a message to a Redis Stream. Returns the message ID."""
        msg_id = await self._r.xadd(stream, fields)
        log.info("queue.enqueue", stream=stream, fields=fields, msg_id=msg_id)
        return msg_id  # type: ignore[return-value]

    async def to_dlq(
        self,
        original_stream: str,
        job_id: str,
        error: str,
        attempts: int,
    ) -> None:
        await self._r.xadd(
            STREAM_DLQ,
            {
                "original_stream": original_stream,
                "job_id": job_id,
                "error": error[:500],
                "attempts": str(attempts),
            },
        )
        log.warning("queue.dlq", job_id=job_id, original_stream=original_stream, error=error[:200])

    async def ensure_consumer_groups(self) -> None:
        """Create consumer groups for all streams if they don't exist."""
        for stream in ALL_STREAMS:
            try:
                await self._r.xgroup_create(stream, f"{stream}-workers", id="0", mkstream=True)
                log.info("queue.group_created", stream=stream)
            except Exception as exc:
                # BUSYGROUP — group already exists; safe to ignore
                if "BUSYGROUP" not in str(exc):
                    log.warning("queue.group_create_error", stream=stream, error=str(exc))
