import redis
import redis.asyncio as aioredis
import os
import asyncio
from .websocket_service import WebSocketManager
import json
# Synchronous client for regular operations
try:
    redis_host = os.getenv("REDIS_HOST", "localhost")
    redis_port = int(os.getenv("REDIS_PORT", 6379))
    redis_client = redis.Redis(host=redis_host, port=redis_port, db=0, decode_responses=True)
    redis_client.ping()
    print(f"Successfully connected to Redis (sync) at {redis_host}:{redis_port}")
except redis.exceptions.ConnectionError as e:
    print(f"FATAL: Could not connect to Redis: {e}")
    redis_client = None

# Async client for pub/sub
async_redis_client = None
if redis_client:
    try:
        async_redis_client = aioredis.Redis(host=redis_host, port=redis_port, db=0, decode_responses=True)
        print(f"Created async Redis client for pub/sub")
    except Exception as e:
        print(f"Could not create async Redis client: {e}")



async def redis_listener(manager: WebSocketManager):
    """
    Listens to Redis Pub/Sub for messages and broadcasts them to local clients.
    This is the core of the multi-worker communication.
    """
    from services.redis_client import async_redis_client
    
    if not async_redis_client:
        print("ERROR: Async Redis client not available for pub/sub listener")
        return
        
    pubsub = async_redis_client.pubsub()
    await pubsub.psubscribe("quiz_channel:*")
    
    print("Redis listener started and subscribed to quiz_channel:*")
    try:
        while True:
            message = await pubsub.get_message(ignore_subscribe_messages=True, timeout=1.0)
            if message and message.get("type") == "pmessage":
                channel = message['channel']
                if isinstance(channel, bytes):
                    channel = channel.decode('utf-8')
                room_id = channel.split(':')[-1]
                
                data_raw = message['data']
                if isinstance(data_raw, bytes):
                    data_raw = data_raw.decode('utf-8')
                    
                data = json.loads(data_raw)
                print(f"Redis listener received message for room {room_id}: {data.get('type')}")
                await manager.broadcast_local(room_id, data)
    except asyncio.CancelledError:
        print("Redis listener cancelled.")
    finally:
        await pubsub.unsubscribe("quiz_channel:*")
        await pubsub.close()
        print("Redis listener stopped.")


# --- HELPER FUNCTIONS FOR REDIS INTERACTIONS ---

def get_room_key(room_id: str) -> str:
    return f"quiz_room:{room_id}"

def get_room_channel(room_id: str) -> str:
    return f"quiz_channel:{room_id}"
