import traceback
import nonebot.adapters.onebot.v11
from loguru import logger
from nonebot import on_command, on_message, get_driver
from nonebot.params import CommandArg
from nonebot.permission import SUPERUSER
from nonebot.adapters.onebot.v11 import Message, MessageSegment,MessageEvent,Bot,ActionFailed,GroupMessageEvent,PrivateMessageEvent
from nonebot_plugin_guild_patch import GuildMessageEvent
from nonebot.log import logger
from .wws_ship import ShipSecletProcess
from .wws_clan import ClanSecletProcess
from .utils import DailyNumberLimiter,FreqLimiter,get_bot,download
from .data_source import nb2_file
from .command_select import select_command
from nonebot_plugin_htmlrender import text_to_pic
from pathlib import Path
import httpx
import json
import asyncio
import re
import html
import os
import platform
import sys
from nonebot import require
scheduler = require("nonebot_plugin_apscheduler").scheduler

_max = 100
EXCEED_NOTICE = f'您今天已经冲过{_max}次了，请明早5点后再来！'
_nlmt = DailyNumberLimiter(_max)
_flmt = FreqLimiter(3)
__version__ = '0.3.4'
dir_path = Path(__file__).parent
template_path = dir_path / "template"

bot = on_command("wws", block=False, aliases={"WWS"},priority=5)
bot_checkversion = on_command("wws 检查更新",priority=5,block=True)
bot_update = on_command("wws 更新Hikari",priority=5,block=True,permission=SUPERUSER)
bot_listen = on_message(priority=5,block=False)
driver = get_driver()

@bot.handle()
async def main(bot:Bot, ev:MessageEvent, matchmsg: Message = CommandArg()):
    try:
        server_type = None
        if isinstance(ev, PrivateMessageEvent) and (driver.config.private or str(ev.user_id) in driver.config.superusers):       #私聊事件,superusers默认不受影响
            server_type = 'QQ'
        elif isinstance(ev, GroupMessageEvent) and driver.config.group and ev.group_id not in driver.config.ban_group_list:         #群聊事件
            server_type = 'QQ'
        elif isinstance(ev, GuildMessageEvent) and driver.config.channel:       #频道事件
            if driver.config.all_channel or ev.channel_id in driver.config.channel_list:
                server_type = 'QQ_CHANNEL'
            else:
                return
        else:
            return
        msg = ''
        qqid = ev.user_id
        replace_name = None
        if not _nlmt.check(qqid):
            await bot.send(ev,EXCEED_NOTICE, at_sender=True)
            return
        if not _flmt.check(qqid):
            await bot.send(ev,'您冲得太快了，请稍候再冲', at_sender=True)
            return
        _flmt.start_cd(qqid)
        _nlmt.increase(qqid) 
        searchtag = html.unescape(str(matchmsg)).strip()
        if not searchtag:
            await bot.send(ev,"请发送wws help查看相关帮助")
            return
        if searchtag == 'help':
            msg = await send_bot_help()
            await bot.send(ev,MessageSegment.image(msg))
            return
        match = re.search(r"(\(|（)(.*?)(\)|）)",searchtag)
        if match:
            replace_name = match.group(2)
            search_list = searchtag.replace(match.group(0),'').split()
        else:
            search_list = searchtag.split()
        command,search_list = await select_command(search_list)
        if replace_name:
            search_list.append(replace_name)
        msg = await command(server_type,search_list,bot,ev)
        if msg:
            if isinstance(msg,str):
                await bot.send(ev,msg)
                return
            else:
                await bot.send(ev,MessageSegment.image(msg))
                return
        else:
            await bot.send(ev,'没有获取到数据，可能是内部问题')
            return
    except ActionFailed:
        logger.warning(traceback.format_exc())
        try:
            await bot.send(ev,'发不出图片，可能被风控了QAQ')
        except Exception:
            pass
        return
    except Exception:
        logger.error(traceback.format_exc())
        await bot.send(ev,'呜呜呜发生了错误，可能是网络问题，如果过段时间不能恢复请联系麻麻哦~')
             
async def send_bot_help():
    try:
        url = 'https://benx1n.oss-cn-beijing.aliyuncs.com/version.json'
        async with httpx.AsyncClient() as client:
            resp = await client.get(url, timeout=10)
            result = json.loads(resp.text)
        latest_version = result['latest_version']
        url = 'https://benx1n.oss-cn-beijing.aliyuncs.com/wws_help.txt'
        async with httpx.AsyncClient() as client:
            resp = await client.get(url, timeout=10)
            result = resp.text
        result = f'''帮助列表                                                当前版本{__version__}  最新版本{latest_version}\n{result}'''
        img = await text_to_pic(text = result,css_path = str(template_path/"text-help.css"), width = 800)
        return img
    except Exception:
        logger.warning(traceback.format_exc())
        return 'wuwuwu出了点问题，请联系麻麻解决'
    
@bot_listen.handle()
async def change_select_state(ev:MessageEvent):
    try:
        bot = get_bot()
        msg = str(ev.message)
        qqid = ev.user_id
        if ShipSecletProcess[qqid].SelectList and str(msg).isdigit():
            if int(msg) <= len( ShipSecletProcess[qqid].SelectList):
                ShipSecletProcess[qqid] = ShipSecletProcess[qqid]._replace(state = True)
                ShipSecletProcess[qqid] = ShipSecletProcess[qqid]._replace(SlectIndex = int(msg))
            else:
                await bot.send(ev,'请选择列表中的序号哦~')
        if ClanSecletProcess[qqid].SelectList and str(msg).isdigit():
            if int(msg) <= len( ClanSecletProcess[qqid].SelectList):
                ClanSecletProcess[qqid] = ClanSecletProcess[qqid]._replace(state = True)
                ClanSecletProcess[qqid] = ClanSecletProcess[qqid]._replace(SlectIndex = int(msg))
            else:
                await bot.send(ev,'请选择列表中的序号哦~') 
    except Exception:
        logger.warning(traceback.format_exc())
        return

@bot_update.handle()
async def update_Hikari(ev:MessageEvent,bot:Bot):
    try:
        from nonebot_plugin_reboot import Reloader
        await bot.send(ev,'正在更新Hikari，完成后将自动重启，如果没有回复您已上线的消息，请登录服务器查看')
        if hasattr(driver.config,'nb2_path'):
            await asyncio.gather(*[download(
                each['url'],
                f"{driver.config.nb2_path}\{each['name']}"
                ) for each in nb2_file])
        os.system(f'python -m pip install --upgrade hikari-bot')
        os.system(f'python -m pip install --upgrade nonebot-plugin-gocqhttp')
        Reloader.reload(delay=1)
    except RuntimeError:
        if str(platform.system()).lower() == 'linux':
            try:
                import multiprocessing
                for child in multiprocessing.active_children():
                    child.terminate()
                sys.stdout.flush()
                #not compatible with cmdline with '\n' 
                os.execv(os.readlink('/proc/self/exe'), open('/proc/self/cmdline', 'rb').read().replace(b'\0', b'\n').decode().split('\n')[:-1])
            except Exception:
                logger.error(traceback.format_exc())
                await bot.send(ev,'自动更新失败了QAQ，请登录服务器查看具体报错日志')
        else:
            logger.error(traceback.format_exc())
            await bot.send(ev,'不支持nb run启动的方式更新哦，请使用python bot.py 启动Hikari')
    except Exception:
        logger.error(traceback.format_exc())
        await bot.send(ev,'自动更新失败了QAQ，请登录服务器查看具体报错日志')

@bot_checkversion.handle()
async def check_version():
    try:
        bot = get_bot()
        url = 'https://benx1n.oss-cn-beijing.aliyuncs.com/version.json'
        async with httpx.AsyncClient() as client:
            resp = await client.get(url, timeout=10)
            result = json.loads(resp.text)
        superid = driver.config.superusers
        match,msg = False,f'发现新版本'
        for each in result['data']:
            if each['version'] > __version__:
                match = True
                msg += f"\n{each['date']} v{each['version']}\n"
                for i in each['description']:
                    msg += f"{i}\n"
        msg += "实验性更新指令：wws 更新Hikari，请在能登录上服务器的情况下执行该命令"
        if match:
            for each in superid:
                await bot.send_private_msg(user_id=int(each),message=msg)
            try:
                await bot_checkversion.send(msg)
            except Exception:
                return
        else:
            for each in superid:
                await bot.send_private_msg(user_id=int(each),message='Hikari:当前已经是最新版本了')
            try:
                await bot_checkversion.send('Hikari:当前已经是最新版本了')
            except Exception:
                return
        return
    except Exception:
        logger.warning(traceback.format_exc())
        return
        
@driver.on_startup
async def startup():
    try:
        tasks = []
        loop = asyncio.get_running_loop()
        url = 'https://benx1n.oss-cn-beijing.aliyuncs.com/template_Hikari_Latest/template.json'
        async with httpx.AsyncClient() as client:
            resp = await client.get(url, timeout=20)
            result = resp.json()
            for each in result:
                for name, url in each.items():
                    tasks.append(asyncio.ensure_future(startup_download(url, name)))
        await asyncio.gather(*tasks)
    except Exception:
        logger.error(traceback.format_exc())
        return   
    
@driver.on_bot_connect
async def remind(bot: Bot):
    superid = driver.config.superusers
    for each in superid:
        await bot.send_private_msg(user_id=int(each),message=f"Hikari已上线，当前版本{__version__}")

async def startup_download(url,name):
    async with httpx.AsyncClient() as client:
        resp = resp = await client.get(url, timeout=20)
        with open(template_path/name , "wb+") as file:
            file.write(resp.content)
            
scheduler.add_job(
    check_version,
    "cron",
    hour = 12,
)
scheduler.add_job(
    startup,
    "cron",
    hour = 4
)
