import Vue from "vue";
import axios from "axios";
import { loadProgressBar } from "./axiosProgress";
import cachingGet from "./axiosCache";
import { Message, Modal } from "iview";
import router from "../router";
import { createLog } from "@/utils/logger";
//axios配置 start

const qmInstance = axios.create({});

//请求拦截

/**
 * A. token lifecycle
 * 1. /login UI => localStorage.removeItem('token') && localStorage.setItem('token')
 * 2. non /login UI => axios if(!wk_token) wk_token = window.sessionStorage.getItem("token"), send request
 * 3. if axios request fail with 401/403, wk_token = null, redirect to /login removeItem('token')
 * 4. logout to /login, before send request, invalidate wk_token
 * */

let wk_token, wk_key;
qmInstance.interceptors.request.use(
  (config) => {
    // debugger;
    if (
      config.url.includes("/login") === false ||
      config.url.includes("/api/ecs_core/auth/thirdPartyStudentAccess") ===
        false
    ) {
      // if (!wk_token) {
      wk_token = window.sessionStorage.getItem("token");
      wk_key = window.localStorage.getItem("key");
      // }
      if (wk_token && config.headers.common["token"] == null) {
        config.headers.common["token"] = wk_token;
        // Axios.defaults.headers.common["key"] = window.localStorage.getItem("key");
        config.headers.common["key"] = wk_key;
      }
    } else {
      wk_token = null;
    }

    return config;
  },
  (error) => {
    Message.error({
      content: error,
      duration: 15,
      closable: true,
    });
    createLog({
      action: "axios request",
      errorJSON: JSON.stringify(error, (key, value) =>
        key === "token" ? "" : value
      ),
      errorName: error.name,
      errorMessage: error.message,
      errorStack: error.stack,
    });
    return Promise.resolve(error);
  }
);

//响应拦截
qmInstance.interceptors.response.use(
  (response) => {
    return response;
  },
  (error) => {
    console.log("axios response error: " + JSON.stringify(error));
    createLog({
      action: "axios response",
      errorJSON: JSON.stringify(error, (key, value) =>
        key === "token" ? "" : value
      ),
      errorName: error.name,
      errorMessage: error.message,
      errorStack: error.stack,
    });
    if (!error.response) {
      // "Network Error" 网络不通，直接返回
      // "timeout of 30000ms exceeded" 连接超时，可能是客户端原因，也可能是服务器原因
      if (
        window.___lastNetworkError === undefined ||
        window.___lastNetworkError < Date.now() - 15 * 1000
      ) {
        Message.error({
          content: "网络连接异常，请检查网络设置。",
          duration: 15,
          closable: true,
        });
        window.___lastNetworkError = Date.now();
        createLog({
          action:
            "网络连接异常，请检查网络设置" +
            (eval(
              [
                "nav",
                "iga",
                "tor",
                ".c",
                "onn",
                "ec",
                "ti",
                "on",
                ".r",
                "t",
                "t",
              ].join("")
            ) && "."),
        });
      }

      // TODO: 由于chrome58不支持navigator.connection.downlink , 所以无法判断客户端网络状况

      let detailInfo = "";
      try {
        (detailInfo += error.config.url
          .replace(/=\w*/g, "=")
          .replace(/\d+/g, "/{id}")) +
          " ||| " +
          error.message;
      } catch (error) {
        console.log("detailInfo error");
      }

      window._hmt.push([
        "_trackEvent",
        location.pathname.replace(/=\w*/g, "=").replace(/\d+/g, "{id}"),
        "网络连接异常，请检查网络设置。",
        detailInfo,
      ]);

      return Promise.reject(error);
    }
    // 这里是返回状态码不为200时候的错误处理
    let status = error.response.status;

    // 登录失效 跳转登录页面
    if (status == 403 || status == 401) {
      if (
        window.___lastInvalidDate === undefined ||
        window.___lastInvalidDate < Date.now() - 1000
      ) {
        Message.error({
          content: "登录失效，请重新登录！",
          duration: 15,
          closable: true,
        });
        window.___lastInvalidDate = Date.now();

        const redirectUrl = sessionStorage.getItem("redirectUrl");
        if (redirectUrl) {
          Modal.error({
            title: "确认返回",
            content: "token失效",
            onOk: () => {
              window.location = redirectUrl;
            },
          });
        } else {
          router.push("/login/");
        }
      }
      wk_token = null;
      // router.push("/login/" + localStorage.getItem("domain"));
      return; // 仅显示登录失效，不显示因登录失效造成的后续错误
    } else if (status == 502) {
      window._hmt.push([
        "_trackEvent",
        location.pathname.replace(/=\w*/g, "=").replace(/\d+/g, "{id}"),
        "服务器异常(502)！",
        error.config.url.replace(/=\w*/g, "=").replace(/\d+/g, "{id}"),
      ]);
      Message.error({
        content: "服务器异常(502)！",
        duration: 15,
        closable: true,
      });
      createLog({
        action: "axios response error",
        errorMessage: "服务器异常(502)",
        url: error.config.url,
      });
      return Promise.reject(error);
    } else if (status == 503) {
      const deal503Apis = [
        "/api/ecs_oe_student/examControl/checkExamInProgress",
        "/api/branch_ecs_oe_admin/examControl/queryExamList",
      ];
      if (deal503Apis.includes(error.config.url)) {
        return Promise.resolve({ status: 503 });
      }
      window._hmt.push([
        "_trackEvent",
        location.pathname.replace(/=\w*/g, "=").replace(/\d+/g, "{id}"),
        "服务器繁忙(503)！请稍后重试。",
        error.config.url.replace(/=\w*/g, "=").replace(/\d+/g, "{id}"),
      ]);
      Message.error({
        content: "服务器繁忙(503)！请稍后重试。",
        duration: 15,
        closable: true,
      });
      createLog({
        action: "axios response error",
        errorMessage: "服务器繁忙(503)！请稍后重试。",
        url: error.config.url,
      });
      return Promise.reject(error);
    } else if (status == 504) {
      window._hmt.push([
        "_trackEvent",
        location.pathname.replace(/=\w*/g, "=").replace(/\d+/g, "{id}"),
        "服务器异常(504)！",
        error.config.url.replace(/=\w*/g, "=").replace(/\d+/g, "{id}"),
      ]);
      Message.error({
        content: "服务器异常(504)！",
        duration: 15,
        closable: true,
      });
      createLog({
        action: "axios response error",
        errorMessage: "服务器异常",
        url: error.config.url,
      });
      return Promise.reject(error);
    } else if (status != 200) {
      window._hmt.push([
        "_trackEvent",
        location.pathname.replace(/=\w*/g, "=").replace(/\d+/g, "{id}"),
        "status: " + status,
        error.config.url.replace(/=\w*/g, "=").replace(/\d+/g, "{id}"),
      ]);
      createLog({
        action: "axios response error",
        errorMessage: `服务器繁忙(${status})`,
        url: error.config.url,
      });
      if (
        wk_token &&
        ![401, 403].includes(status) &&
        !error.config.url.includes("/api/ecs_core/log/studentClient/")
      ) {
        setTimeout(() => {
          qmInstance.post(
            "/api/ecs_core/log/studentClient/" + "debug/S-009001",
            error.config.url + " 请求失败",
            {
              headers: {
                "Content-Type": "text/plain",
              },
            }
          );
        }, 3 * 1000);
      }

      function showDescOrNot(descMaybe) {
        if (descMaybe && descMaybe.desc) {
          Message.error({
            content: descMaybe.desc,
            duration: 15,
            closable: true,
          });
        } else {
          Message.error({
            content: "未定义异常: " + JSON.stringify(descMaybe, 2),
            duration: 15,
            closable: true,
          });
        }
      }
      let data = error.response.data;
      if (data instanceof Blob) {
        // data = data.read
        const fr = new FileReader();
        fr.addEventListener(
          "load",
          () => {
            let res = fr.result;
            if (typeof res === "string") res = JSON.parse(res);
            showDescOrNot(res);
          },
          false
        );
        fr.readAsText(data);
      } else {
        showDescOrNot(data);
      }

      return Promise.reject(error);
    }
  }
);

qmInstance.defaults.withCredentials = true; //允许跨域携带cookie
qmInstance.defaults.timeout = 30 * 1000; //超时时间
qmInstance.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest"; //标识这是一个 ajax 请求

qmInstance.get = cachingGet(qmInstance.get, [
  /\/api\/exam_question\/question\/\?question_id/,
  /\/api\/exam_question\/paper_struct\/\?exam_record_id=/,
  /\/api\/ecs_oe_student\/examQuestion\/getQuestionContent\?questionId=.*&exam_record_id=/,
  // /\/api\/ecs_exam_work\/exam\/\d+$/,
  // /\/api\/ecs_oe_student_face\/upyun$/,
  /\/api\/ecs_oe_student\/examFaceLivenessVerify\/checkFaceLiveness$/,
]);
loadProgressBar(qmInstance);

Vue.prototype.$http = qmInstance;
// Vue.prototype.$upyunhttp = upyunInstance;
export default {
  install: function (Vue) {
    Object.defineProperty(Vue.prototype, "$http", {
      value: qmInstance,
    });
    // Object.defineProperty(Vue.prototype, "$upyunhttp", {
    //   value: upyunInstance
    // });
  },
};
