from datetime import datetime, timedelta
from typing import Literal
from typing_extensions import Self

from tortoise import fields
from tortoise.functions import Count

from zhenxun.services.db_context import Model


class ChatHistory(Model):
    id = fields.IntField(pk=True, generated=True, auto_increment=True)
    """自增id"""
    user_id = fields.CharField(255)
    """用户id"""
    group_id = fields.CharField(255, null=True)
    """群聊id"""
    text = fields.TextField(null=True)
    """文本内容"""
    plain_text = fields.TextField(null=True)
    """纯文本"""
    create_time = fields.DatetimeField(auto_now_add=True)
    """创建时间"""
    bot_id = fields.CharField(255, null=True)
    """bot记录id"""
    platform = fields.CharField(255, null=True)
    """平台"""

    class Meta:  # type: ignore
        table = "chat_history"
        table_description = "聊天记录数据表"

    @classmethod
    async def get_group_msg_rank(
        cls,
        gid: str | None,
        limit: int = 10,
        order: str = "DESC",
        date_scope: tuple[datetime, datetime] | None = None,
    ) -> list[Self]:
        """获取排行数据

        参数:
            gid: 群号
            limit: 获取数量
            order: 排序类型，desc，des
            date_scope: 日期范围
        """
        o = "-" if order == "DESC" else ""
        query = cls.filter(group_id=gid) if gid else cls
        if date_scope:
            query = query.filter(create_time__range=date_scope)
        return list(
            await query.annotate(count=Count("user_id"))
            .order_by(f"{o}count")
            .group_by("user_id")
            .limit(limit)
            .values_list("user_id", "count")
        )  # type: ignore

    @classmethod
    async def get_group_first_msg_datetime(
        cls, group_id: str | None
    ) -> datetime | None:
        """获取群第一条记录消息时间

        参数:
            group_id: 群组id
        """
        if group_id:
            message = (
                await cls.filter(group_id=group_id).order_by("create_time").first()
            )
        else:
            message = await cls.all().order_by("create_time").first()
        return message.create_time if message else None

    @classmethod
    async def get_message(
        cls,
        uid: str,
        gid: str,
        type_: Literal["user", "group"],
        msg_type: Literal["private", "group"] | None = None,
        days: int | tuple[datetime, datetime] | None = None,
    ) -> list[Self]:
        """获取消息查询query

        参数:
            uid: 用户id
            gid: 群聊id
            type_: 类型，私聊或群聊
            msg_type: 消息类型，用户或群聊
            days: 限制日期
        """
        if type_ == "user":
            query = cls.filter(user_id=uid)
            if msg_type == "private":
                query = query.filter(group_id__isnull=True)
            elif msg_type == "group":
                query = query.filter(group_id__not_isnull=True)
        else:
            query = cls.filter(group_id=gid)
            if uid:
                query = query.filter(user_id=uid)
        if days:
            if isinstance(days, int):
                query = query.filter(
                    create_time__gte=datetime.now() - timedelta(days=days)
                )
            elif isinstance(days, tuple):
                query = query.filter(create_time__range=days)
        return await query.all()  # type: ignore

    @classmethod
    async def _run_script(cls):
        return [
            # 允许 group_id 为空
            "alter table chat_history alter group_id drop not null;",
            # 允许 text 为空
            "alter table chat_history alter text drop not null;",
            # 允许 plain_text 为空
            "alter table chat_history alter plain_text drop not null;",
            # 将user_id改为user_id
            "ALTER TABLE chat_history RENAME COLUMN user_qq TO user_id;",
            "ALTER TABLE chat_history "
            "ALTER COLUMN user_id TYPE character varying(255);",
            "ALTER TABLE chat_history "
            "ALTER COLUMN group_id TYPE character varying(255);",
            # 添加bot_id字段
            "ALTER TABLE chat_history ADD bot_id VARCHAR(255);",
            "ALTER TABLE chat_history ALTER COLUMN bot_id TYPE character varying(255);",
            "ALTER TABLE chat_history ADD COLUMN platform character varying(255);",
        ]
