package com.yutou.biliapi.net;

import com.alibaba.fastjson2.JSONObject;
import com.yutou.biliapi.api.LoginApi;
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
import com.yutou.biliapi.bean.login.LoginInfoBean;
import com.yutou.biliapi.bean.login.QRCodeGenerateBean;
import com.yutou.biliapi.databases.BiliBiliLoginDatabase;
import com.yutou.common.okhttp.HttpBody;
import com.yutou.common.okhttp.HttpCallback;
import com.yutou.common.okhttp.api.BaseApi;
import okhttp3.Headers;
import org.springframework.util.StringUtils;
import retrofit2.Response;

import java.io.IOException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;

public class BiliLoginNetApiManager extends BaseApi {
    public static final int LOGIN_QRCODE = 100;
    public static final int LOGIN_SUCCESS = 101;

    private static BiliLoginNetApiManager instance;

    private BiliLoginNetApiManager() {
        super("https://passport.bilibili.com");
    }

    public static BiliLoginNetApiManager getInstance() {
        if (instance == null) {
            instance = new BiliLoginNetApiManager();
        }
        return instance;
    }

    public LoginApi getLoginApi() {
        return getLoginApi(null);
    }

    public LoginApi getLoginApi(String loginUid) {
        if (StringUtils.hasText(loginUid)) {
            LoginCookieDatabaseBean cookie = BiliBiliLoginDatabase.getInstance().getCookie(loginUid);
            if (cookie != null) {
                useCookie(JSONObject.parseObject(JSONObject.toJSONString(cookie)));
            }
        }
        return createApi(LoginApi.class);
    }

    public void login(HttpCallback<LoginCookieDatabaseBean> callback) {
        getLoginApi().getQRCodeGenerate().enqueue(new HttpCallback<QRCodeGenerateBean>() {
            @Override
            public void onResponse(Headers headers, int code, String status, QRCodeGenerateBean response, String rawResponse) {
                String oauthKey = response.getQrcode_key();
                String url = response.getUrl();
                String bd = "gourl=https%3A%2F%2Fpassport.bilibili.com%2Fajax%2FminiLogin%2Fredirect&oauthKey=" + oauthKey;
                callback.onResponse(headers, LOGIN_QRCODE, null, null, url);
                new Thread(() -> waitLogin(oauthKey, callback)).start();
            }

            @Override
            public void onFailure(Throwable throwable) {

            }
        });
    }

    private void waitLogin(String oauthKey, HttpCallback<LoginCookieDatabaseBean> callback) {
        long time = System.currentTimeMillis();
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                String bd = "gourl=https%3A%2F%2Fpassport.bilibili.com%2Fajax%2FminiLogin%2Fredirect&oauthKey=" + oauthKey;
                if ((System.currentTimeMillis() - time) > 5 * 60 * 1000) {
                    cancel();
                    return;
                }

                try {
                    Response<HttpBody<LoginInfoBean>> response = getLoginApi().loginQRCode(oauthKey).execute();
                    LoginCookieDatabaseBean cookie = getCookie(response.headers(), response.body());
                    if (cookie != null) {
                        cookie.setGourl(bd);
                        cancel();
                        callback.onResponse(response.headers(), LOGIN_SUCCESS, "ok", cookie, JSONObject.toJSONString(cookie));

                    }
                } catch (
                        IOException e) {
                    cancel();
                    throw new RuntimeException(e);
                }
            }
        }, 1000, 3000);
    }

    public LoginCookieDatabaseBean getCookie(Headers headers, HttpBody<LoginInfoBean> httpBody) {
        if (httpBody.getData().getCode() == 0) {
            JSONObject ck = new JSONObject();
            List<String> list = headers.values("set-cookie");
            for (String cookie : list) {
                String[] split = cookie.split(";");
                for (String string : split) {
                    if (!ck.containsKey(string) && StringUtils.hasText(string) && string.contains("=")) {
                        String key = string.split("=")[0].trim();
                        String value = string.split("=")[1].trim();
                        if (key.contains("Expires")) {
                            SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMMM yyyy HH:mm:ss z", Locale.ENGLISH);
                            sdf.setTimeZone(TimeZone.getDefault());
                            Date date = sdf.parse(value, new ParsePosition(0));
                            value = String.valueOf(date.getTime() / 1000);
                        }
                        ck.put(key, value);
                    }
                }
            }

            LoginCookieDatabaseBean cookie = JSONObject.parseObject(ck.toString(), LoginCookieDatabaseBean.class);
            cookie.setRefreshToken(httpBody.getData().getRefresh_token());
            return cookie;
        } else {
            return null;
        }
    }
}