#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
WebSocket 配置与推送（模块名符合 PEP 8：小写+下划线）。
"""

import json
import logging
import urllib

from asgiref.sync import async_to_sync
from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncJsonWebsocketConsumer
from channels.layers import get_channel_layer
from django.conf import settings
from django.core.cache import cache
from jwt import InvalidSignatureError

# 配置日志
logger = logging.getLogger(__name__)

send_dict = {}
# WebSocket Key
WS_ROOM_NAME_KEY = "user_"


# 发送消息结构体
def set_message(sender, msg_type, msg, refresh_unread=False):
    text = {"sender": sender, "contentType": msg_type, "content": msg, "refresh_unread": refresh_unread}
    return text


@database_sync_to_async
def _get_message_unread(user_id):
    """获取用户的未读消息数量"""
    from django_base_ai.system.models import MessageCenterTargetUser

    count = MessageCenterTargetUser.objects.filter(users=user_id, is_read=False).count()
    return count or 0


def request_data(scope):
    query_string = scope.get("query_string", b"").decode("utf-8")
    qs = urllib.parse.parse_qs(query_string)
    return qs


class CxWebSocket(AsyncJsonWebsocketConsumer):
    async def connect(self):
        try:
            import jwt

            self.service_uid = self.scope["url_route"]["kwargs"]["service_uid"]
            # 用户处理客户端websocket链接 带上设备id nid
            self.nid = self.scope["url_route"]["kwargs"].get("nid", 0)
            logger.info(f"WebSocket连接尝试 - service_uid: {self.service_uid}, nid: {self.nid}")

            decoded_result = jwt.decode(self.service_uid, settings.SECRET_KEY, algorithms=["HS256"])
            if decoded_result:
                self.user_id = decoded_result.get("user_id")
                self.room_name = f"{WS_ROOM_NAME_KEY}{str(self.user_id)}_{self.nid}"
                logger.info(f"WebSocket连接成功 - user_id: {self.user_id}, room_name: {self.room_name}")

                # 收到连接时候处理，
                await self.channel_layer.group_add(self.room_name, self.channel_name)
                await self.accept()
                cache.set(self.user_id, self.nid, 300)
                # 主动推送消息
                unread_count = await _get_message_unread(self.user_id)
                logger.info(f"用户 {self.user_id} 未读消息数量: {unread_count}")

                if unread_count == 0:
                    # 发送连接成功
                    logger.info(f"向用户 {self.user_id} 发送连接成功消息")
                    await self.send_json(set_message("system", "SYSTEM", "连接成功"))
                else:
                    logger.info(f"向用户 {self.user_id} 发送未读消息提醒")
                    await self.send_json(set_message("system", "SYSTEM", "请查看您的未读消息~", refresh_unread=True))
        except InvalidSignatureError as e:
            logger.error(f"WebSocket连接失败 - JWT签名验证错误: {e}")
            await self.disconnect(None)
        except Exception as e:
            logger.error(f"WebSocket连接异常: {e}")
            await self.disconnect(None)

    async def disconnect(self, close_code):
        # Leave room group
        logger.info(
            f"WebSocket断开连接 - close_code: {close_code}, user_id: {getattr(self, 'user_id', 'unknown')}, room_name: {getattr(self, 'room_name', 'unknown')}"
        )
        await self.channel_layer.group_discard(self.room_name, self.channel_name)
        cache.delete(self.user_id)
        logger.info(f"用户 {self.user_id} WebSocket连接已关闭")
        try:
            await self.close(close_code)
        except Exception as e:
            logger.error(f"关闭WebSocket连接时发生异常: {e}")
            pass


class BaseWebSocketCenter(CxWebSocket):
    """
    消息中心
    """

    async def receive(self, text_data):
        # 接受客户端的信息，你处理的函数
        logger.info(f"收到用户 {self.user_id} 的消息: {text_data}")
        await self.channel_layer.group_send(self.room_name, {"type": "push.message", "json": {"content": text_data}})
        cache.set(self.user_id, self.nid, 300)
        logger.debug(f"用户 {self.user_id} 缓存已更新")

    async def push_message(self, event):
        """消息发送"""
        message = event["json"]
        logger.info(f"向用户 {self.user_id} 推送消息: {message}")
        await self.send(text_data=json.dumps(message))
        logger.debug(f"消息推送完成 - user_id: {self.user_id}")


def websocket_push(room_name, message):
    """
    主动推送
    @param room_name: 群组名称 uid_nid
    @param message: 消息内容
    """
    logger.info(f"主动推送消息 - room_name: {room_name}, message: {message}")
    channel_layer = get_channel_layer()
    try:
        async_to_sync(channel_layer.group_send)(
            f"{WS_ROOM_NAME_KEY}{room_name}", {"type": "push.message", "json": message}
        )
        logger.info(f"消息推送成功 - room_name: {room_name}")
    except Exception as e:
        logger.error(f"消息推送失败 - room_name: {room_name}, error: {e}")
