import asyncio
from pathlib import Path
from typing import ClassVar

import aiofiles
import nonebot
from pydantic import BaseModel

from zhenxun import ui
from zhenxun.configs.config import BotConfig, Config
from zhenxun.configs.path_config import DATA_PATH
from zhenxun.configs.utils.models import PluginExtraData
from zhenxun.models.statistics import Statistics
from zhenxun.models.user_console import UserConsole
from zhenxun.services.log import logger
from zhenxun.utils.platform import PlatformUtils
from zhenxun.utils.pydantic_compat import model_dump

DIR_PATH = DATA_PATH / "bot_profile"

PROFILE_PATH = DIR_PATH / "profile"
PROFILE_PATH.mkdir(parents=True, exist_ok=True)


Config.add_plugin_config(
    "bot_profile",
    "AUTO_SEND_PROFILE",
    True,
    help="在添加好友/群组时是否自动发送BOT自我介绍图片",
    default_value=True,
    type=bool,
)


class Profile(BaseModel):
    bot_id: str
    """BOT ID"""
    introduction: str
    """BOT自我介绍"""
    avatar: Path | None
    """BOT头像"""
    name: str
    """BOT名称"""


class PluginProfile(BaseModel):
    name: str
    """插件名称"""
    introduction: str
    """插件自我介绍"""
    precautions: list[str] | None = None
    """BOT自我介绍时插件的注意事项"""


class BotProfileManager:
    """BOT自我介绍管理器"""

    _bot_data: ClassVar[dict[str, Profile]] = {}

    _plugin_data: ClassVar[dict[str, PluginProfile]] = {}

    @classmethod
    def clear_profile_image(cls, bot_id: str | None = None):
        """清除BOT自我介绍的内存缓存"""
        if bot_id:
            if bot_id in cls._bot_data:
                del cls._bot_data[bot_id]
        else:
            cls._bot_data.clear()

    @classmethod
    async def _read_profile(cls, bot_id: str):
        """读取BOT自我介绍

        参数:
            bot_id: BOT ID

        异常:
            FileNotFoundError: 文件不存在
        """
        bot_file_path = PROFILE_PATH / f"{bot_id}"
        bot_file_path.mkdir(parents=True, exist_ok=True)
        bot_profile_file = bot_file_path / "profile.txt"
        if not bot_profile_file.exists():
            logger.debug(f"BOT自我介绍文件不存在: {bot_profile_file}, 跳过读取")
            bot_file_path.touch()
            return
        async with aiofiles.open(bot_profile_file, encoding="utf-8") as f:
            introduction = await f.read()
        avatar = bot_file_path / f"{bot_id}.png"
        if not avatar.exists():
            avatar = None
        bot = await PlatformUtils.get_user(nonebot.get_bot(bot_id), bot_id)
        name = bot.name if bot else "未知"
        cls._bot_data[bot_id] = Profile(
            bot_id=bot_id, introduction=introduction, avatar=avatar, name=name
        )

    @classmethod
    async def get_bot_profile(cls, bot_id: str) -> Profile | None:
        if bot_id not in cls._bot_data:
            await cls._read_profile(bot_id)
        return cls._bot_data.get(bot_id)

    @classmethod
    def load_plugin_profile(cls):
        """加载插件自我介绍"""
        for plugin in nonebot.get_loaded_plugins():
            if plugin.module_name in cls._plugin_data:
                continue
            metadata = plugin.metadata
            if not metadata:
                continue
            extra = metadata.extra
            if not extra:
                continue
            extra_data = PluginExtraData(**extra)
            if extra_data.introduction or extra_data.precautions:
                cls._plugin_data[plugin.name] = PluginProfile(
                    name=metadata.name,
                    introduction=extra_data.introduction or "",
                    precautions=extra_data.precautions or [],
                )

    @classmethod
    def get_plugin_profile(cls) -> list[dict]:
        """获取插件自我介绍"""
        if not cls._plugin_data:
            cls.load_plugin_profile()
        return [model_dump(e) for e in cls._plugin_data.values()]

    @classmethod
    def is_auto_send_profile(cls) -> bool:
        """是否自动发送BOT自我介绍图片"""
        return Config.get_config("bot_profile", "AUTO_SEND_PROFILE")

    @classmethod
    async def build_bot_profile_image(
        cls, bot_id: str, tags: list[dict[str, str]] | None = None
    ) -> bytes | None:
        """构建BOT自我介绍图片"""
        profile, service_count, call_count = await asyncio.gather(
            cls.get_bot_profile(bot_id),
            UserConsole.get_new_uid(),
            Statistics.filter(bot_id=bot_id).count(),
        )
        if not profile:
            return None
        if not tags:
            tags = [
                {"text": f"服务人数: {service_count}", "color": "#5e92e0"},
                {"text": f"调用次数: {call_count}", "color": "#31e074"},
            ]
        profile_data = {
            "avatar": profile.avatar.absolute().as_uri() if profile.avatar else None,
            "bot_name": profile.name,
            "bot_description": profile.introduction,
            "service_count": service_count,
            "call_count": call_count,
            "plugin_list": cls.get_plugin_profile(),
            "tags": tags,
            "title": f"{BotConfig.self_nickname}简介",
        }
        return await ui.render_template(
            "pages/builtin/bot_profile",
            data=profile_data,
            use_cache=True,
        )


BotProfileManager.clear_profile_image()
