from nonebot import get_driver, require
from nonebot.log import logger
from nonebot.plugin import PluginMetadata
from nonebot.plugin.load import inherit_supported_adapters

require("nonebot_plugin_uninfo")
require("nonebot_plugin_alconna")
require("nonebot_plugin_apscheduler")
require("nonebot_plugin_localstore")
require("nonebot_plugin_htmlrender")
from nonebot_plugin_apscheduler import scheduler

from .config import Config

__plugin_meta__ = PluginMetadata(
    name="堡垒之夜游戏插件",
    description="堡垒之夜战绩，季卡，商城，vb图查询",
    usage="季卡/生涯季卡/战绩/生涯战绩/商城/vb图",
    type="application",
    config=Config,
    homepage="https://github.com/fllesser/nonebot-plugin-fortnite",
    supported_adapters=inherit_supported_adapters(
        "nonebot_plugin_alconna", "nonebot_plugin_uninfo"
    ),
)

from .pve import VB_FILE, screenshot_vb_img
from .shop import SHOP_FILE, screenshot_shop_img
from .stats import get_level, get_stats_image
from .utils import get_size_in_mb


@get_driver().on_startup
async def check_resources():
    import asyncio
    from pathlib import Path

    from .config import CHINESE_FONT_PATH, GG_FONT_PATH, STATS_BG_PATH, VB_FONT_PATH

    paths = [CHINESE_FONT_PATH, GG_FONT_PATH, VB_FONT_PATH, STATS_BG_PATH]

    async def dwonload_file(path: Path):
        import aiofiles
        import httpx

        url = f"https://raw.githubusercontent.com/fllesser/nonebot-plugin-fortnite/master/resources/{path.name}"
        logger.info(f"文件 {path.name} 不存在，开始从 {url} 下载...")
        try:
            async with httpx.AsyncClient(timeout=60) as client:
                response = await client.get(url)
            response.raise_for_status()
            font_data = response.content

            async with aiofiles.open(path, "wb") as f:
                await f.write(font_data)

            size = get_size_in_mb(path)
            logger.success(f"文件 {path.name} 下载成功，文件大小: {size:.2f} MB")
        except Exception:
            logger.exception("文件下载失败")
            logger.warning(f"请前往仓库下载资源文件到 {path}")

    tasks = [dwonload_file(path) for path in paths if not path.exists()]
    if len(tasks) > 0:
        await asyncio.gather(*tasks)


@scheduler.scheduled_job(
    "cron",
    id="fortnite",
    hour=8,
    minute=5,
    misfire_grace_time=300,
)
async def _():
    logger.info("开始更新商城/VB图...")
    try:
        await screenshot_shop_img()
        size = get_size_in_mb(SHOP_FILE)
        logger.success(f"商城更新成功，文件大小: {size:.2f} MB")
    except Exception:
        logger.exception("商城更新失败")
    try:
        await screenshot_vb_img()
        size = get_size_in_mb(VB_FILE)
        logger.success(f"vb图更新成功, 文件大小: {size:.2f} MB")
    except Exception:
        logger.exception("vb图更新失败")


import re

from arclet.alconna import Alconna, Args, Arparma
from nonebot import on_startswith
from nonebot.permission import SUPERUSER
from nonebot_plugin_alconna import AlconnaMatcher, Match, on_alconna
from nonebot_plugin_alconna.uniseg import Image, Text, UniMessage
from nonebot_plugin_uninfo import Uninfo

timewindow_prefix = ["生涯", ""]
name_args = Args["name?", str]


battle_pass_alc = on_alconna(Alconna(timewindow_prefix, "季卡", name_args))
stats_alc = on_alconna(Alconna(timewindow_prefix, "战绩", name_args))


@battle_pass_alc.handle()
@stats_alc.handle()
async def _(matcher: AlconnaMatcher, session: Uninfo, name: Match[str]):
    if name.available:
        matcher.set_path_arg("name", name.result)
        return
    # 获取群昵称
    if not session.member or not session.member.nick:
        return
    pattern = r"(?:id:|id\s)(.+)"
    if matched := re.match(pattern, session.member.nick, re.IGNORECASE):
        matcher.set_path_arg("name", matched.group(1))


name_prompt = UniMessage.template(
    "{:At(user, $event.get_user_id())} 请发送游戏名称\n"
    "群昵称设置如下可快速查询:\n"
    "    id:name\n"
    "    ID name"
)


@battle_pass_alc.got_path("name", prompt=name_prompt)
async def _(arp: Arparma, name: str):
    header: str = arp.header_match.result
    receipt = await UniMessage.text(f"正在查询 {name} 的{header}，请稍后...").send()
    level_info = await get_level(name, header)
    await UniMessage(Text(level_info)).send()
    await receipt.recall(delay=1)


@stats_alc.got_path("name", prompt=name_prompt)
async def _(arp: Arparma, name: str):
    header: str = arp.header_match.result
    receipt = await UniMessage.text(f"正在查询 {name} 的{header}，请稍后...").send()
    try:
        file = await get_stats_image(name, header)
    except Exception as e:
        if isinstance(e, ValueError):
            await UniMessage(Text(str(e))).finish()
        logger.exception("查询失败")
        await UniMessage(Text("查询失败")).finish()
    await UniMessage(Image(path=file)).send()
    await receipt.recall(delay=1)
    file.unlink(missing_ok=True)


shop_matcher = on_startswith("商城")


@shop_matcher.handle()
async def _():
    if not SHOP_FILE.exists():
        logger.info("商城图不存在, 开始更新商城...")
        try:
            await screenshot_shop_img()
            size = get_size_in_mb(SHOP_FILE)
            logger.success(f"商城更新成功，文件大小: {size:.2f} MB")
        except Exception:
            logger.exception("商城更新失败")
    await UniMessage(
        Image(path=SHOP_FILE)
        + Text("可前往 https://www.fortnite.com/item-shop?lang=zh-Hans 购买")
    ).send()


@on_startswith("更新商城", permission=SUPERUSER).handle()
async def _():
    receipt = await UniMessage.text("正在更新商城，请稍后...").send()
    try:
        file = await screenshot_shop_img()
        await UniMessage(Text("手动更新商城成功") + Image(path=file)).send()
    except Exception:
        logger.exception("手动更新商城失败")
        await UniMessage(Text("手动更新商城失败")).send()
    finally:
        await receipt.recall(delay=1)


vb_matcher = on_startswith(("vb图", "VB图", "Vb图"))


@vb_matcher.handle()
async def _():
    if not VB_FILE.exists():
        logger.info("vb 图不存在, 开始更新vb图...")
        try:
            await screenshot_vb_img()
            size = get_size_in_mb(VB_FILE)
            logger.success(f"vb图更新成功, 文件大小: {size:.2f} MB")
        except Exception as e:
            logger.warning(f"vb图更新失败: {e}")
    await UniMessage(Image(path=VB_FILE)).send()


@on_startswith("更新vb图", permission=SUPERUSER).handle()
async def _():
    receipt = await UniMessage.text("正在更新vb图, 请稍后...").send()
    try:
        file = await screenshot_vb_img()
        await UniMessage(Text("手动更新 VB 图成功") + Image(path=file)).send()
    except Exception as e:
        await UniMessage(Text(f"手动更新 VB 图失败 | {e}")).send()
    finally:
        await receipt.recall(delay=1)
