"""NapCatQQ WebSocket 网关。"""

import asyncio
import json
from typing import Callable, Optional

import websockets
from websockets.client import WebSocketClientProtocol

from butler.session.state import NapCatEvent


class NapCatGateway:
    """NapCatQQ WebSocket 网关。"""

    def __init__(self, ws_url: str = "ws://localhost:3001", access_token: str = ""):
        self.ws_url = ws_url
        self.access_token = access_token
        self.message_handler: Optional[Callable[[NapCatEvent], None]] = None
        self._ws: Optional[WebSocketClientProtocol] = None
        self._running = False

    def on_message(self, handler: Callable[[NapCatEvent], None]) -> None:
        self.message_handler = handler

    async def connect(self) -> None:
        headers = {}
        if self.access_token:
            headers["Authorization"] = f"Bearer {self.access_token}"

        self._running = True

        while self._running:
            try:
                async with websockets.connect(
                    self.ws_url,
                    additional_headers=headers,
                    ping_interval=30,
                    ping_timeout=10,
                ) as ws:
                    self._ws = ws
                    await self._listen(ws)
            except Exception as e:
                print(f"Gateway connection error: {e}")
                if self._running:
                    await asyncio.sleep(5)

    async def _listen(self, ws: WebSocketClientProtocol) -> None:
        async for raw_message in ws:
            try:
                data = json.loads(raw_message)

                if isinstance(data, dict):
                    event = NapCatEvent(
                        time=data.get("time", 0),
                        self_id=data.get("self_id", 0),
                        post_type=data.get("post_type", ""),
                        message_type=data.get("message_type", ""),
                        user_id=data.get("user_id", 0),
                        message=self._extract_message(data),
                        raw_message=str(data),
                    )

                    if event.is_private_message and self.message_handler:
                        self.message_handler(event)

            except Exception as e:
                print(f"Error processing message: {e}")

    def _extract_message(self, data: dict) -> str:
        message = data.get("message", "")
        if isinstance(message, str):
            return message
        elif isinstance(message, list):
            texts = []
            for seg in message:
                if isinstance(seg, dict) and seg.get("type") == "text":
                    texts.append(seg.get("data", {}).get("text", ""))
            return "".join(texts)
        return str(message)

    async def send_private_message(self, user_id: int, message: str) -> None:
        if not self._ws:
            return

        payload = {
            "action": "send_private_msg",
            "params": {"user_id": user_id, "message": message},
        }
        await self._ws.send(json.dumps(payload))

    async def stop(self) -> None:
        self._running = False
        if self._ws:
            await self._ws.close()
