package com.yutou.qqbot.bilibili;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.yutou.bilibili.api.LiveAPI;
import com.yutou.bilibili.api.LoginAPI;
import com.yutou.bilibili.api.SignApi;
import com.yutou.bilibili.api.UserApi;
import com.yutou.qqbot.QQBotManager;
import com.yutou.qqbot.interfaces.ObjectInterface;
import com.yutou.qqbot.utlis.*;
import org.brotli.dec.BrotliInputStream;

import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.zip.GZIPInputStream;

public class BiliBiliUtils {
    private long qq;
    private long oldBiliBiliHttpTime = 0;

    public enum HTTP {
        POST, GET
    }

    public enum RET_MODEL {
        BYTE, JSON
    }

    public BiliBiliUtils(long qq) {
        this.qq = qq;
    }

    public static BiliBiliUtils getInstance(long qq) {
        return new BiliBiliUtils(qq);
    }

    public synchronized JSONObject http_get(String url) {
        try {
            Log.i("调用url = " + url);
            HttpsURLConnection connection = getBiliHttpGet(url, getCookie());
            BufferedInputStream stream = new BufferedInputStream(connection.getInputStream());
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int len;
            while ((len = stream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
                outputStream.flush();
            }
            String str = outputStream.toString(StandardCharsets.UTF_8);
            outputStream.close();
            try {
                return JSON.parseObject(str);
            } catch (Exception e) {
                JSONObject json = new JSONObject();
                json.put("html", str);
                return json;
            } finally {

                stream.close();
                connection.disconnect();
            }

        } catch (IOException e) {
            //com.yutou.bilibili.Tools.Log.e(e);
            e.printStackTrace();
        }
        return null;
    }

    public JSONObject http_login_getSid(String url) {
        try {
            Log.i("调用url = " + url);
            HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
            setConnection(null, connection);
            connection.setRequestMethod("GET");
            connection.connect();
            BufferedInputStream stream = new BufferedInputStream(connection.getInputStream());
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int len;
            while ((len = stream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
                outputStream.flush();
            }
            List<String> cookie = null;
            if (connection.getHeaderFields().containsKey("Set-Cookie")) {
                cookie = connection.getHeaderFields().get("Set-Cookie");
            }
            String str = outputStream.toString(StandardCharsets.UTF_8);
            outputStream.close();
            try {
                JSONObject json = JSON.parseObject(str);
                if (cookie != null) {
                    StringBuilder ck = new StringBuilder();
                    for (String key : cookie) {
                        ck.append(";").append(key);
                    }
                    json.put("cookie", ck.toString());
                }
                return json;
            } catch (Exception e) {
                JSONObject json = new JSONObject();
                json.put("html", str);
                return json;
            } finally {

                stream.close();
                connection.disconnect();
            }

        } catch (IOException e) {
            //com.yutou.bilibili.Tools.Log.e(e);
            e.printStackTrace();
        }
        return null;
    }

    public JSONObject http_post(String url, String body) {
        return http(url, HTTP.POST, body, RET_MODEL.JSON);
    }

    public <T> T http(String url, HTTP model, String body, RET_MODEL ret_model) {
        return http(url, model, body, null, ret_model);
    }

    public <T> T http(String url, HTTP model, String body, Map<String, String> headers, RET_MODEL ret_model) {
        JSONObject json = null;
        BufferedInputStream stream = null;
        ByteArrayOutputStream outputStream = null;
        OutputStream connectionOutputStream = null;
        HttpURLConnection connection = null;
        try {
            if (System.currentTimeMillis() - oldBiliBiliHttpTime < 1000) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                oldBiliBiliHttpTime = System.currentTimeMillis();
            }
            if (model == HTTP.POST) {
                connection = getBiliHttpPost(url, getCookie());
            } else {
                if (body != null) {
                    if (url.contains("?")) {
                        url += "&" + body;
                    } else {
                        url += "?" + body;
                    }
                    body = null;
                }
                connection = getBiliHttpGet(url, getCookie());
            }
            if (headers != null) {
                for (String key : headers.keySet()) {
                    connection.setRequestProperty(key, headers.get(key));
                }
            } else {
                connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            }

            if (!StringUtils.isEmpty(body)) {
                connectionOutputStream = connection.getOutputStream();
                connectionOutputStream.write(body.getBytes(StandardCharsets.UTF_8));
                connectionOutputStream.flush();
            }
            connection.connect();
            if (connection.getResponseCode() == 400) {
                return null;
            }
            if (connection.getContentEncoding() != null && connection.getContentEncoding().contains("gzip")) {
                stream = new BufferedInputStream(new GZIPInputStream(connection.getInputStream()));
            } else if (connection.getContentEncoding() != null && connection.getContentEncoding().contains("br")) {
                stream = new BufferedInputStream(new BrotliInputStream(connection.getInputStream()));
            } else {
                stream = new BufferedInputStream(connection.getInputStream());
            }
            outputStream = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int len = 0, size;
            while ((len = stream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
                outputStream.flush();
            }
            if (ret_model == RET_MODEL.BYTE) {
                return (T) outputStream.toByteArray();
            }
            String str = outputStream.toString(StandardCharsets.UTF_8);

            try {
                json = JSON.parseObject(str);
                json.put("cookie", connection.getHeaderField("Set-Cookie"));
                return (T) json;
            } catch (Exception e) {
                json = new JSONObject();
                json.put("html", str);
                json.put("cookie", connection.getHeaderField("Set-Cookie"));
                return (T) json;
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (stream != null) {
                    stream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
                if (connectionOutputStream != null) {
                    connectionOutputStream.close();
                }
                if (connection != null) {
                    connection.disconnect();
                }

            } catch (Exception ignored) {

            }
        }
        return null;
    }

    public String getCookie() {
        if (StringUtils.isEmpty(ConfigTools.readFile(new File(qq + "_bilibili.cookie")))) {
            return "";
        }
        JSONObject json = JSON.parseObject(ConfigTools.readFile(new File(qq + "_bilibili.cookie")));
        StringBuilder builder = new StringBuilder();
        for (String s : json.keySet()) {
            builder.append(s).append("=").append(json.getString(s)).append(";");

        }
        return builder.toString();
    }

    public HttpURLConnection getBiliHttpPost(String url, String cookie) throws Exception {
        if (System.currentTimeMillis() - oldBiliBiliHttpTime < 1000) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            oldBiliBiliHttpTime = System.currentTimeMillis();
        }
        HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);
        connection.setDoInput(true);
        setConnection(cookie, connection);
        return connection;
    }

    public HttpsURLConnection getBiliHttpGet(String url, String cookie) throws IOException {
        if (System.currentTimeMillis() - oldBiliBiliHttpTime < 1000) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException ignored) {
            }
            oldBiliBiliHttpTime = System.currentTimeMillis();
        }
        HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
        if (cookie != null) {
            setConnection(cookie, connection);
        }
        connection.setReadTimeout(5000);
        connection.setConnectTimeout(5000);
        return connection;
    }

    public File download(final String url, final String saveName, boolean isProxy) {
        File jar = null;
        try {
            File savePath = new File(HttpTools.downloadPath + saveName);
            Proxy proxy = null;
            if (!savePath.exists()) {
                savePath.mkdirs();
            }
            savePath.delete();
            Log.i("DOWNLOAD", "下载文件:" + url + " 保存文件:" + saveName);
            if (isProxy) {
                proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890));
            }
            HttpsURLConnection connection;
            if (isProxy) {
                connection = (HttpsURLConnection) new URL(url).openConnection(proxy);
            } else {
                connection = (HttpsURLConnection) new URL(url).openConnection();
            }
            setConnection(getCookie(), connection);

            InputStream inputStream = connection.getInputStream();
            jar = new File(HttpTools.downloadPath + saveName + "_tmp.tmp");
            jar.createNewFile();
            Log.i("DOWNLOAD", "临时保存文件:" + jar.getAbsolutePath());
            OutputStream outputStream = new FileOutputStream(jar);
            byte[] bytes = new byte[1024];
            double size = connection.getContentLength();
            double downSize = 0;
            int len;
            while ((len = inputStream.read(bytes)) > 0) {
                outputStream.write(bytes, 0, len);
                downSize += len;
            }
            outputStream.close();
            inputStream.close();
            File oldJar = new File(HttpTools.downloadPath + saveName);
            if (oldJar.exists()) {
                oldJar.delete();
            }
            jar.renameTo(oldJar);
            Log.i("DOWNLOAD", "实际保存：" + oldJar.getAbsolutePath() + " " + oldJar.getName());
            return oldJar;
        } catch (Exception e) {
            e.printStackTrace();
            if (jar != null) {
                jar.delete();
            }
        }
        return null;
    }

    public void download_ffmpeg(final List<String> url, final String saveName) {
        new Thread(() -> {
            StringBuilder builder = new StringBuilder();
            builder.append(ConfigTools.load(ConfigTools.CONFIG, ConfigTools.FFMPEG, String.class)).append(" ");
         /*   builder.append("-user_agent").append(" ");
            builder.append("\"").append("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 Referer:https://live.bilibili.com").append("\"").append(" ");
            builder.append("-cookies").append(" ");
            builder.append("\"").append(getCookie()).append("\"").append(" ");
            builder.append("-headers").append(" ");
            builder.append("\"").append("Referer:https://live.bilibili.com").append("\"").append(" ");*/
            for (String _url : url) {
                builder.append("-i").append(" ");
                builder.append("\"").append(_url).append("\"").append(" ");
            }
            builder.append("-vcodec").append(" ");
            builder.append("copy").append(" ");
            builder.append("-acodec").append(" ");
            builder.append("copy").append(" ");
            builder.append("-threads").append(" ");
            builder.append("8").append(" ");
//            builder.append("-y").append(" ");
            builder.append(new File(HttpTools.downloadPath + saveName + ".mp4").getAbsolutePath()).append(" ");
            System.out.println(builder);
            AppTools.exec(builder.toString(), new ObjectInterface() {
                @Override
                public void out(String data) {
                    super.out(data);
                    System.out.println("data = " + data);
                }
            }, false, false);
        }).start();
    }


    private void setConnection(String cookie, HttpURLConnection connection) {
        connection.addRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
        connection.addRequestProperty("Accept-Language", "zh-CN,zh;q=0.8");
        connection.addRequestProperty("Cache-Control", "max-age=0");
        connection.setRequestProperty("Referer", "https://www.bilibili.com");
        connection.addRequestProperty("Connection", "keep-alive");
        connection.addRequestProperty("Upgrade-Insecure-Requests", "1");
        if (!StringUtils.isEmpty(cookie)) {
            connection.addRequestProperty("Cookie", cookie);
        }
        connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36");
    }

    public JSONObject getLoginInfo() {
        JSONObject jsonObject = http_get(UserApi.NAV);
        if (jsonObject == null) {
            jsonObject = new JSONObject();
            jsonObject.put("code", "-1");
            jsonObject.put("data", new JSONObject());
        }
        return jsonObject;
    }

    public static void main(String[] args) {
     /*   String url="https://xy218x85x123x8xy.mcdn.bilivideo.cn:4483/upgcxcode/12/12/17281212/17281212-16-80.flv?e=ig8euxZM2rNcNbNBhbdVhwdlhbUghwdVhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1660538573&gen=playurlv2&os=mcdn&oi=2936701972&trid=00006f9623cac1514d8ea18fba3a15a756cau&mid=96300&platform=pc&upsig=25ddd1da610960e8e1d2e80dc97c2361&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&mcdnid=11000101&bvc=vod&nettype=0&orderid=0,2&agrr=1&bw=253116&logo=A0000400&requestFrom=BILIBILI_HELPER_2.5.8";
        File file=download(url,"16.mp4",false);
        System.out.println("file.getAbsolutePath() = " + file.getAbsolutePath());*/
    /*    System.out.println(getLiveRoom(42062));
        System.out.println("--------------------------------------------");
        System.out.println(getUserInfo(730732));*/
        JSONObject sign = new BiliBiliUtils(583819556).getUserInfo(96300);
        System.out.println("sign = " + sign);
    }

    public boolean sendLiveDanmu(long roomId, String msg) {
        JSONObject body = new JSONObject();
        body.put("msg", msg);
        body.put("roomid", roomId);
        body.put("color", 16777215);
        body.put("fontsize", 25);
        body.put("rnd", System.currentTimeMillis() / 1000);
        body.put("csrf", BiliLogin.getCookieToken(qq));
        body.put("csrf_token", BiliLogin.getCookieToken(qq));
        JSONObject post = http_post(LiveAPI.LIVE_SEND_DANMU, HttpTools.toUrlParams(body));
        return post.getInteger("code") == 0;
    }

    public String liveSignIn() {
        //{"code":0,"data":{"coin":1,"gold":19500,"silver":106394,"tid":"Silver2Coin22101413201169763005873"},"message":"兑换成功"}
        JSONObject body = new JSONObject();
        body.put("csrf", BiliLogin.getCookieToken(qq));
        body.put("csrf_token", BiliLogin.getCookieToken(qq));
        JSONObject toCoin = http_post(SignApi.LIVE_SIGN_COIN, HttpTools.toUrlParams(body));
        JSONObject liveSign = http_get(SignApi.LIVE_SIGN);
        JSONObject vipSign = http_post(SignApi.VIP_SIGN, null);
        return "银瓜子兑换硬币:" + toCoin.getString("message") + "|" + "直播签到:" + liveSign.getString("message") + "|大会员中心签到:" + vipSign.getString("message");
    }

    public JSONObject getLiveRoom(int roomId) {
        JSONObject body = new JSONObject();
        body.put("room_id", roomId);
        body.put("csrf", BiliLogin.getCookieToken(qq));
        body.put("csrf_token", BiliLogin.getCookieToken(qq));
        return http_post(LiveAPI.LIVE_ROOM_INFO, HttpTools.toUrlParams(body));
    }

    public JSONObject getUserInfo(int mid) {
        TreeMap<String, String> body = new TreeMap<>();
        body.put("mid", mid + "");
        BiliBiliWbiSign.getWbiSign(body);
        return http_get(UserApi.USER_INFO_V2 + "?" + HttpTools.toUrlParams(body));
    }

    public boolean checkLiveRoom(int roomId) {
        JSONObject post = getLiveRoom(roomId);
        return post.getInteger("code") == 0;
    }
}
