import asyncio
import uuid
import httpx
import logging
from typing import Optional, Dict, Any, List
from .profile import local_profile
from runtime.config import load_config

logger = logging.getLogger("brynq.rooms.manager")

_config = load_config()
CLOUD_URL = _config.cloud_url  # https://api.brynq.ai in prod, overridable via env

class RoomManager:
    def __init__(self):
        self.active_room: Optional[Dict[str, Any]] = None
        self.is_host: bool = False
        self.host_service = None
        self.client_service = None
        self._token: Optional[str] = None

    def _get_auth_headers(self) -> Dict[str, str]:
        """Get JWT auth headers, auto-registering if needed."""
        if self._token:
            return {"Authorization": f"Bearer {self._token}"}
        # Try to load from local storage
        from pathlib import Path
        token_file = Path.home() / ".brynq" / "cloud_token"
        if token_file.exists():
            self._token = token_file.read_text("utf-8").strip()
            if self._token:
                return {"Authorization": f"Bearer {self._token}"}
        return {}

    async def _ensure_auth(self) -> Dict[str, str]:
        """Ensure we have a valid JWT token. Auto-registers if needed."""
        headers = self._get_auth_headers()
        if headers:
            return headers
        # Auto-register with cloud to get a token
        prof = local_profile.get()
        user_id = prof.get("user_id") or str(uuid.uuid4())
        if not prof.get("user_id"):
            local_profile.update(user_id=user_id)
        try:
            async with httpx.AsyncClient() as client:
                resp = await client.post(f"{CLOUD_URL}/v1/auth/register", json={
                    "runtime_id": user_id,
                }, timeout=10)
                if resp.status_code == 200:
                    data = resp.json()
                    self._token = data.get("token", "")
                    if self._token:
                        from pathlib import Path
                        token_file = Path.home() / ".brynq" / "cloud_token"
                        token_file.parent.mkdir(parents=True, exist_ok=True)
                        token_file.write_text(self._token, "utf-8")
                        return {"Authorization": f"Bearer {self._token}"}
        except Exception as e:
            logger.warning("Cloud auth failed: %s", e)
        return {}

    async def create_room(self, name: str) -> Dict[str, Any]:
        """Creates a room on the cloud, starts the local host WebSocket."""
        prof = local_profile.get()
        if not prof["user_id"]:
            prof["user_id"] = str(uuid.uuid4())
            local_profile.update(user_id=prof["user_id"])

        headers = await self._ensure_auth()

        async with httpx.AsyncClient() as client:
            resp = await client.post(f"{CLOUD_URL}/v1/rooms", json={
                "name": name,
                "host_id": prof["user_id"],
                "host_address": "ws://localhost:8081/ws/room"
            }, headers=headers)
            resp.raise_for_status()
            room = resp.json()

        self.active_room = room
        self.is_host = True
        
        # Start the local host service
        from .room_host import RoomHost
        self.host_service = RoomHost(self)
        asyncio.create_task(self.host_service.start())
        
        return room

    async def join_room(self, code: str) -> Dict[str, Any]:
        """Joins via the cloud directory, connects to host."""
        headers = await self._ensure_auth()
        async with httpx.AsyncClient() as client:
            resp = await client.post(f"{CLOUD_URL}/v1/rooms/join", json={
                "room_code": code
            }, headers=headers)
            resp.raise_for_status()
            room = resp.json()

        self.active_room = room
        self.members = room.get("members", [])
        self.is_host = False

        # Connect client to the host
        from .room_client import RoomClient
        self.client_service = RoomClient(self, room["host_address"], room["room_id"])
        asyncio.create_task(self.client_service.connect())
        
        return room

    async def leave_room(self):
        if self.client_service:
            await self.client_service.disconnect()
            self.client_service = None
        self.active_room = None
        self.is_host = False

    async def close_room(self):
        if not self.is_host or not self.active_room:
            return
        
        headers = await self._ensure_auth()
        async with httpx.AsyncClient() as client:
            await client.delete(f"{CLOUD_URL}/v1/rooms/{self.active_room['room_id']}",
                                headers=headers)
            
        if self.host_service:
            await self.host_service.stop()
            self.host_service = None
        
        self.active_room = None
        self.is_host = False

    def send_message(self, content: str):
        if self.is_host and self.host_service:
            asyncio.create_task(self.host_service.broadcast_chat(content))
        elif not self.is_host and self.client_service:
            asyncio.create_task(self.client_service.send_chat(content))

    def send_message_raw(self, message: Dict[str, Any]):
        """Send an arbitrary JSON message through the room WebSocket.

        Unlike send_message() which wraps content in a chat message,
        this sends the dict as-is. Used for project sync messages.
        """
        import json
        if self.is_host and self.host_service:
            asyncio.create_task(self.host_service.broadcast(message))
        elif not self.is_host and self.client_service:
            asyncio.create_task(self.client_service.ws.send(json.dumps(message)))

room_manager = RoomManager()
