from typing import TYPE_CHECKING
import json
if TYPE_CHECKING:
    from client import BotClient

from dataclasses import dataclass

PRIVATE_ACTION_IDS = [str(i) for i in range(200, 210)] + [str(i) for i in range(30200, 30210)]
GROUP_ACTION_IDS = [str(i) for i in range(300, 329)] + [str(i) for i in range(30300, 30329)]
CHANNEL_ACTION_IDS = [str(i) for i in range(400, 427)] + [str(i) for i in range(30400, 30427)]

@dataclass
class User:
    data: dict

    @property
    def user_id(self) -> int | None:
        value = self.data.get("userId")
        return int(value) if value is not None else None

    @property
    def cache_id(self) -> str | None:
        return self.data.get("cacheId")


@dataclass
class Author:
    data: dict

    @property
    def hash(self) -> str | None:
        return self.data.get("hash")

    @property
    def user(self) -> User:
        return User(self.data.get("user", {}))


@dataclass
class RoomMessage:
    data: dict

    @property
    def message_id(self) -> int | None:
        value = self.data.get("messageId")
        return value if value is not None else None

    @property
    def message_version(self) -> int | None:
        value = self.data.get("messageVersion")
        return value if value is not None else None

    @property
    def status(self) -> str | None:
        return self.data.get("status")

    @property
    def status_version(self) -> int | None:
        value = self.data.get("statusVersion")
        return value if value is not None else None

    @property
    def message(self) -> str | None:
        return self.data.get("message")

    @property
    def author(self) -> Author:
        return Author(self.data.get("author", {}))

    @property
    def create_time(self) -> int | None:
        return self.data.get("createTime")

    @property
    def update_time(self) -> int | None:
        return self.data.get("updateTime")

    @property
    def random_id(self) -> int | None:
        value = self.data.get("randomId")
        return value if value is not None else None
    
    @property
    def reply_to(self) -> "RoomMessage | None":
        """اگر پیام دارای replyTo باشد، آن را به صورت RoomMessage برگردان"""
        reply_data = self.data.get("replyTo")
        if reply_data:
            return RoomMessage(reply_data)
        return None


class Message:
    def __init__(self, client: "BotClient", update: dict):
        self.client = client
        self.update = update

        self.room_id = int(update.get("roomId")) if update.get("roomId") else None
        self.room_message = RoomMessage(update.get("roomMessage", {}))
        self.action_id = update.get("actionId", "666 6666 666 333")

    # میان‌برهای سطح بالا
    @property
    def text(self) -> str | None:
        return self.room_message.message

    @property
    def random_id(self) -> int | None:
        return self.room_message.random_id

    @property
    def user_id(self) -> int | None:
        return self.room_message.author.user.user_id
    
    def __str__(self) -> str:
        """نمایش خوانای update"""
        return json.dumps(self.update, ensure_ascii=False, indent=2)
    
    def __getitem__(self, key):
        return self.update[key]

    def __repr__(self) -> str:
        """نمایش دقیق‌تر برای دیباگ"""
        return f"<Message update={self.update}>"
    
    async def reply_message(self, text: str, room_id: int=None, reply_to_message_id: int | None = None):
        if self.action_id in PRIVATE_ACTION_IDS:
            return await self.client.send_message(room_id or self.room_id, text, reply_to_message_id  or self.room_message.message_id, target_type="private")
        elif self.action_id in GROUP_ACTION_IDS:
            return await self.client.send_message(room_id or self.room_id, text, reply_to_message_id or self.room_message.message_id, target_type="group")
        elif self.action_id in CHANNEL_ACTION_IDS:
            return await self.client.send_message(room_id or self.room_id, text, reply_to_message_id or self.room_message.message_id, target_type="channel")
    
    async def delete_message(self, room_id: int=None, message_id: int=None, delete_type: str = "Global"):
        if self.action_id in PRIVATE_ACTION_IDS:
            return await self.client.delete_message(room_id or self.room_id, message_id or self.room_message.message_id, delete_type, "private")
        elif self.action_id in GROUP_ACTION_IDS:
            return await self.client.delete_message(room_id or self.room_id, message_id or self.room_message.message_id, "group")
        elif self.action_id in CHANNEL_ACTION_IDS:
            return await self.client.delete_message(room_id or self.room_id, message_id or self.room_message.message_id, "channel")
    
    async def ban_member(self, room_id, member_id):
        if self.action_id in GROUP_ACTION_IDS:
            return await self.client.ban_member(room_id, member_id, "group")

    async def reply_message_private(self, text: str, reply_to_message_id: int | None = None):
        return await self.client.send_message(self.room_id, text, reply_to_message_id  or self.room_message.message_id, "private")
    
    async def delete_message_private(self, message_id: int=None, delete_type="Global"):
        return await self.client.delete_message(self.room_id, message_id or self.room_message.message_id, delete_type, "private")

    async def reply_message_group(self, text: str, reply_to_message_id: int | None = None):
        return await self.client.send_message(self.room_id, text, reply_to_message_id or self.room_message.message_id, "group")
    
    async def delete_message_group(self, message_id: int=None):
        return await self.client.delete_message(self.room_id, message_id or self.room_message.message_id, target_type="group")
    
    async def ban_member_group(self, room_id, member_id):
        return await self.client.ban_member(room_id, member_id, "group")
    
    async def reply_message_channel(self, text: str, reply_to_message_id: int | None = None):
        return await self.client.send_message(self.room_id, text, reply_to_message_id or self.room_message.message_id, "channel")
    
    async def delete_message_channel(self, message_id: int=None):
        return await self.client.delete_message(self.room_id, message_id or self.room_message.message_id, target_type="channel")