"""NapCatQQ WebSocket 网关。"""

import asyncio
import json
from typing import Optional

import websockets
from websockets.client import WebSocketClientProtocol

from butler.gateway.base import BaseGateway
from butler.session.state import NapCatEvent


class NapCatGateway(BaseGateway):
    """NapCatQQ WebSocket 网关。"""

    name = "napcat"

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

    async def start(self) -> None:
        """连接 NapCat WebSocket。"""
        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
                    print(f"[napcat] Connected to {self.ws_url}")
                    await self._listen(ws)
            except Exception as e:
                print(f"[napcat] Connection error: {e}")
                print("[napcat] Will retry in 30 seconds...")
                if self._running:
                    await asyncio.sleep(30)

    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:
                        result = self._message_handler(
                            str(event.user_id), event.message, self.name
                        )
                        if asyncio.iscoroutine(result):
                            asyncio.ensure_future(result)

            except Exception as e:
                print(f"[napcat] 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_message(self, user_id: str, text: str) -> None:
        """通过 NapCat 发送私聊消息。"""
        if not self._ws:
            return

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

    async def stop(self) -> None:
        """停止网关。"""
        self._running = False
        if self._ws:
            await self._ws.close()
