package com.yutou.bilibili.QQBot;

import com.alibaba.fastjson.JSONObject;
import com.yutou.bilibili.BiliBili.Controllers.RealTimeDataController;
import com.yutou.bilibili.BiliBili.Live;
import com.yutou.bilibili.BiliBili.LiveUtils;
import com.yutou.bilibili.BiliBili.Tools.SaveLive;
import com.yutou.bilibili.BilibiliApplication;
import com.yutou.bilibili.Tools.*;
import com.yutou.bilibili.interfaces.DownloadInterface;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
import kotlin.coroutines.CoroutineContext;
import net.mamoe.mirai.Bot;
import net.mamoe.mirai.BotFactory;
import net.mamoe.mirai.event.EventHandler;
import net.mamoe.mirai.event.GlobalEventChannel;
import net.mamoe.mirai.event.ListeningStatus;
import net.mamoe.mirai.event.SimpleListenerHost;
import net.mamoe.mirai.event.events.GroupMessageEvent;
import net.mamoe.mirai.event.events.MessageEvent;
import net.mamoe.mirai.message.data.Image;
import net.mamoe.mirai.message.data.MessageChainBuilder;
import net.mamoe.mirai.utils.BotConfiguration;
import net.mamoe.mirai.utils.ExternalResource;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class QQBotManager implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (QQBotManager.applicationContext == null) {
            QQBotManager.applicationContext = applicationContext;
        }
    }

    private <T> T getBean(Class<T> tClass) {
        return applicationContext.getBean(tClass);
    }

    private static class QQCommands {
        private final static String QQ_HELP = "!help";
        private final static String QQ_SYSTEM_LOG = "!log";
        private final static String QQ_SYSTEM_RESTART = "!restart";
        private final static String QQ_GET_IP = "!ip";
        private final static String QQ_GET_VERSION = "!version";
        private final static String QQ_LIVE_LIST = "!列表";
        private final static String QQ_LIVE_SAVE = "!录播列表";
        private final static String QQ_LIVE_TO_DAY_DATE = "!今日数据";
        private final static String QQ_LIVE_DATE = "!数据";
        private final static String QQ_LIVE_USE_SAVE = "!启动录播";
        private final static String QQ_LIVE_RELINK="!relink";
    }

    private static QQBotManager botManager = null;
    private Bot bot;
    private static long qqGroup;
    private boolean isLogin = false;
    private static boolean isInit = false;

    @Resource
    RealTimeDataController realTimeDataController;


    private QQBotManager() {
        qqGroup = ConfigTools.load(ConfigTools.CONFIG, "qq_group",long.class,950075833L);
    }
    public void stop(){
        if(bot!=null){
            bot.close();
            bot=null;
        }
    }
    public void init() {
        if (!ConfigTools.load(ConfigTools.CONFIG, "qq_bot",boolean.class)) {
            return;
        }
        new Thread(() -> {
            long qq = Long.parseLong((String) ConfigTools.load(ConfigTools.CONFIG, "qq_number"));
            String password = (String) ConfigTools.load(ConfigTools.CONFIG, "qq_password");
            bot = BotFactory.INSTANCE.newBot(qq, password, new BotConfiguration() {
                {
                    setProtocol(MiraiProtocol.ANDROID_PAD);
                    fileBasedDeviceInfo("qq_bot_devices_info.json");
                    if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "qq_debug"))) {
                        noBotLog();
                        noNetworkLog();
                    }
                }
            });
            //Events.registerEvents(bot, new MessageListener());
            GlobalEventChannel.INSTANCE.registerListenerHost(new MessageListener());
            Log.i("准备登陆");
            bot.login();
            Log.i("登陆成功");
            isLogin = true;
            isInit = true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Log.e(e);
                    }
                    String str = sendMessage("姬妻酱上线拉~");
                    Log.i(str);

                }
            }).start();
            bot.join();

        }).start();

    }

    public static QQBotManager getInstance() {
        if (botManager == null && !isInit) {
            botManager = new QQBotManager();
        }
        return botManager;
    }

    public boolean isLogin() {
        return isLogin;
    }

    private Image getImage(File file) {
        if (bot != null) {
            ExternalResource resource=ExternalResource.create(file);
            Image image;
            image= Objects.requireNonNull(bot.getGroup(qqGroup)).uploadImage(resource);
            try {
                resource.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return image;
        }
        return null;
    }

    private String getNotLoginQQ() {
        return "没有登录QQ";
    }


    public String sendMessage(String text) {
        if (bot != null) {
            try {
                return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(text).toString();
            } catch (Exception e) {
                com.yutou.bilibili.Tools.Log.e(e);
            }
        }
        return getNotLoginQQ();
    }

    public String sendMessage(Long group, String text) {
        if (bot != null) {
            try {
                return Objects.requireNonNull(bot.getGroup(group)).sendMessage(text).toString();
            } catch (Exception e) {
                com.yutou.bilibili.Tools.Log.e(e);
            }
        }
        return getNotLoginQQ();
    }

    public void sendMessage(Long group, MessageChainBuilder builder) {
        if (bot != null) {
            Objects.requireNonNull(bot.getGroup(group)).sendMessage(builder.asMessageChain());
        }
    }


    public String sendMessage(File imageFile, String text) {
        try {
            if (bot != null) {
                Image image = getImage(imageFile);
                MessageChainBuilder builder = new MessageChainBuilder();
                if (image != null) {
                    builder.append(image);
                }
                builder.append(text);
                return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(builder.asMessageChain()).toString();
            }
        } catch (Exception e) {
            com.yutou.bilibili.Tools.Log.e(e);
        }

        return getNotLoginQQ();
    }

    public String sendMessage(List<File> imgs, String text) {
        if (bot != null) {
            MessageChainBuilder builder = new MessageChainBuilder();
            for (File img : imgs) {
                builder.append(Objects.requireNonNull(getImage(img)));
            }
            builder.append(text);
            return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(builder.asMessageChain()).toString();
        }
        return getNotLoginQQ();
    }

    private static List<String> getImages(String str) {
        List<String> list = new ArrayList<>();
        String regex = "<img(.*?)/img>";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            list.add(matcher.group().replace("<img", "")
                    .replace("/img>", "")
                    .trim());
        }
        return list;
    }

    public static void main(String[] args) {
        getInstance();
    }

    private static class MessageListener extends SimpleListenerHost {
        @Override
        public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) {
            //    super.handleException(context, exception);
            exception.printStackTrace();
        }


        @EventHandler
        public ListeningStatus onMessage(MessageEvent event) {
            String message=event.getMessage().contentToString();
           String msg = message.replace("！", "!").toLowerCase();
            msg=msg.trim();
            StringBuilder builder = new StringBuilder();
            JSONObject json;
            String[] cmd = new String[0];
            int _roomId = 0;
            switch (msg) {
                case QQCommands.QQ_GET_IP:
                    json = JSONObject.parseObject(HttpTools.get("https://api.asilu.com/ip/"));
                    String ip = json.getString("ip");
                    getInstance().sendMessage("服务器IP:" + ip);
                    break;
                case QQCommands.QQ_GET_VERSION:
                    sendVersion();
                    break;
                case QQCommands.QQ_SYSTEM_RESTART:
                    getInstance().sendMessage("正在重启服务");
                    System.out.println("结束进程");
                    try {
                        AppTools.exec("cd /home/yutou/public/servier/biliob && ./start.sh");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case QQCommands.QQ_LIVE_LIST:
                    builder.append("当前正在记录数据的直播间:");
                    builder.append("\n");
                    for (Live live : Live.lives.values()) {
                        Live.LiveInfo info=live.getLiveInfo();
                        if (live.geData().getLive()==1) {
                            builder.append("【直播中】");
                        }
                        builder
                                .append("名字:").append(live.geData().getName()).append(" ")
                                .append(" roomId:").append(live.geData().getRoomid()).append(" ");
                        if (info != null) {
                            builder.append("标题:").append(info.getTitle()).append("\n");
                        } else {
                            builder.append("\n");
                        }
                    }
                    getInstance().sendMessage(builder.toString());
                    break;
                case QQCommands.QQ_LIVE_SAVE:
                    builder.append("当前正在录制的直播间:");
                    builder.append("\n");
                    for (String roomId : SaveLive.getInstance().getLiveList()) {
                        BilibiliUpInfo data = new BilibiliUpInfo();
                        data.setRoomid(Integer.parseInt(roomId));
                        Live live = LiveUtils.liveContains(data);
                        if (live != null) {
                            File file = SaveLive.getInstance().getLiveFile(Integer.parseInt(roomId));
                            builder
                                    .append("名字:").append(live.geData().getName()).append(" ")
                                    .append("文件大小(字节):").append(file.length()).append(" ")
                                    .append("roomId:").append(live.geData().getRoomid()).append("\n");
                        }

                    }
                    getInstance().sendMessage(builder.toString());
                    break;
                case QQCommands.QQ_HELP:
                    for (Field field : QQCommands.class.getDeclaredFields()) {
                        try {
                            field.setAccessible(true);
                            builder.append(field.get(null)).append("\n");
                        } catch (IllegalAccessException e) {
                            com.yutou.bilibili.Tools.Log.e(e);
                        }
                    }
                    getInstance().sendMessage(builder.toString());
                    break;
                case QQCommands.QQ_LIVE_RELINK:
                    for (Live live : Live.lives.values()) {
                            live.stop();
                    }
                    break;
                default:
                    if (msg.startsWith(QQCommands.QQ_LIVE_TO_DAY_DATE)) {
                        try {
                            cmd = msg.split(" ");
                            _roomId = Integer.parseInt(cmd[1]);
                            QQBotManager.getInstance().sendMessage("请稍等，正在查询...");
                            sendGiftData(_roomId, null, null);
                        } catch (Exception e) {
                            getInstance().sendMessage("参数错误。\n使用方式: " + QQCommands.QQ_LIVE_TO_DAY_DATE + "+空格+roomId");
                        }
                    } else if (msg.startsWith(QQCommands.QQ_LIVE_DATE)) {
                        try {
                            cmd = msg.split(" ");
                            _roomId = Integer.parseInt(cmd[1]);
                            Date startTime = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").parse(cmd[2]);
                            Date endTime = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").parse(cmd[3]);
                            QQBotManager.getInstance().sendMessage("请稍等，正在查询...");
                            sendGiftData(_roomId, startTime, endTime);
                        } catch (Exception e) {
                            getInstance().sendMessage("参数错误。" +
                                    "\n使用方式: " + QQCommands.QQ_LIVE_DATE + "+空格+roomId+起始时间+空格+结束时间" +
                                    "\n时间格式：年-月-日_时:分:秒 例:2021-4-1_12:00:00" +
                                    "\n时分秒不可省略");
                        }
                    } else if (msg.startsWith(QQCommands.QQ_LIVE_USE_SAVE)) {
                        try {
                            cmd = msg.split(" ");
                            _roomId = Integer.parseInt(cmd[1]);
                            if (SaveLive.getInstance().checkLive(_roomId)) {
                                SaveLive.getInstance().stop(_roomId);
                            }
                            SaveLive.getInstance().startLive(_roomId);
                            getInstance().sendMessage("已启动" + _roomId + "的录播");
                        } catch (Exception e) {
                            getInstance().sendMessage("参数错误。\n使用方式: " + QQCommands.QQ_LIVE_USE_SAVE + "+空格+roomId");
                        }
                    } else if (msg.startsWith(QQCommands.QQ_SYSTEM_LOG)) {
                        try {
                            cmd = message.replace("！","!").replace(QQCommands.QQ_SYSTEM_LOG,"").split(" ");
                            RedisTools.set(1,"live-log",cmd[1].trim());
                            getInstance().sendMessage("日志设为:"+cmd[1].trim());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }else {
                        Log.i("未知指令:"+msg);
                    }
            }
            return ListeningStatus.LISTENING; // 表示继续监听事件
        }

        public void sendGiftData(int roomId, Date startTime, Date endTime) {
            StringBuilder builder = new StringBuilder();
            if (startTime == null) {
                startTime = AppTools.getToDayStartTime();
            }
            if (endTime == null) {
                endTime = AppTools.getToDayNowTime();
            }
            if (getInstance().realTimeDataController == null) {
                getInstance().realTimeDataController = getInstance().getBean(RealTimeDataController.class);
            }
            JSONObject json = getInstance().realTimeDataController.queryToDayLiveData(roomId, startTime, endTime);
            System.out.println(json);
            builder.append("当前人气:").append(json.getJSONObject("data").getInteger("popular")).append("\n");
            builder.append("普通观众入场:").append(json.getJSONObject("data").getInteger("userLength")).append("\n");
            builder.append("舰长入场:").append(json.getJSONObject("data").getInteger("vipLength")).append("\n");
            int price = 0;
            for (Object o : json.getJSONObject("data").getJSONArray("price")) {
                price += ((JSONObject) o).getInteger("price");
            }
            builder.append("金瓜子:").append(price).append(" 抽成后:").append((price / 2) / 1000).append("￥").append("\n");
            builder.append("礼物收益情况:").append("\n");
            for (Object o : json.getJSONObject("data").getJSONArray("gift")) {
                builder.append(((JSONObject) o).getString("giftName")).append(":").append(((JSONObject) o).getInteger("size")).append("\n");
            }
            getInstance().sendMessage(builder.toString());
        }

        private List<File> files;
        private int index = 0;

        private void sendImagesMsg(List<String> imgs, String text) {
            files = new ArrayList<>();
            index = 0;
            if (imgs.size() == 0) {
                getInstance().sendMessage(text);
                return;
            }
            for (String img : imgs) {
                Tools.download(img, new DownloadInterface() {
                    @Override
                    public void onDownload(File file) {
                        super.onDownload(file);
                        files.add(file);
                        send(imgs.size(), text);
                    }

                    @Override
                    public void onError(Exception e) {
                        super.onError(e);
                        index++;
                        send(imgs.size(), text);
                    }
                });
            }
        }

        private void send(int size, String text) {
            if ((files.size() + index) == size) {
                String str = getInstance().sendMessage(files, text);
                Log.i("str = " + str);
            }
        }

        private void sendVersion() {
            String msg = "软件版本：" + BilibiliApplication.version;
            QQBotManager.getInstance().sendMessage(msg);
        }

    }
}
