import { getIn } from "herculex/dist/utils/manipulate";
import {
  host,
  getTicketUrl,
  ywtHost,
  terminal,
  ywtEnvVersionPrefix,
} from "./constants";
import { getSilentAuthCode, getAppId, getServerTime } from "./jsapi";
import { joinUrl } from "./format";
import { getCurrentStore } from "../../../antbuilder/core/utils/index";

function showErrorMessgage({ isShowError, error }) {
  if (isShowError) {
    my.showToast({
      type: "fail",
      content: error && (error.msg || error.errorMessage),
      duration: 3000,
    });
  }
}

async function checkTimeExpire(time) {
  if (!time) return false;
  const [err, res] = await getServerTime();
  const currentTime = err ? new Date().getTime() : +res.time;
  return time < currentTime;
}

export function _request({
  url,
  method = "post",
  data = {},
  headers = {},
  isShowLoadig = false,
  isShowError = false,
} = {}) {
  return new Promise((resolve) => {
    if (isShowLoadig) {
      my.showLoading();
    }
    // eslint-disable-next-line no-undef
    const app = getApp();
    my.request({
      url: url.startsWith("http") ? url : joinUrl(host, url),
      method,
      data: Object.assign(data, {
        userId: app.globalData.ywtUserId || "",
        appId: app.globalData.appId || "",
        alipayUid: app.globalData.alipayUid,
        terminal,
      }),
      headers: {
        "content-type": "application/x-www-form-urlencoded",
        ticket: app.globalData.ticketData.ticket, // todo test
        appId: app.globalData.appId, // todo test
        ...headers,
      },
      dataType: "json",
      success(res) {
        const result = res.data || {};
        const code = +result.code;
        if (result && code === 200) {
          resolve([
            null,
            {
              data: result.data,
              code,
            },
          ]);
        } else if (code === 20002 || code === 20001 || code === 20008) {
          resolve([
            null,
            {
              code,
              data: null,
            },
          ]);
        } else if (code === 401) {
          resolve([null, result]);
        } else if (code >= 600) {
          // 自定义错误
          showErrorMessgage({
            isShowError: true,
            error: { msg: result.msg || "未知错误" },
          });
          my.hideLoading();
          resolve([result, null]);
        } else {
          showErrorMessgage({
            isShowError,
            error: result,
          });
          resolve([result, null]);
        }
      },
      fail(err) {
        showErrorMessgage({
          isShowError,
          error: err,
        });
        resolve([err, null]);
      },
      complete() {
        if (isShowLoadig) {
          my.hideLoading();
        }
      },
    });
  });
}

export const ywtEnvUrl = {
  "3508C5373A7C4BF18BF3F835FA2B5146": "https://api-qa.ywtinfo.com/",
  F0C507F7F24C4E1E95924A02B8617DC7: "https://api.ywtinfo.com/",
  "1374B32A31454A2E90E09FF738866E02": "https://api.ywtinfo.com/", // 太和QA
  A94C3DEE59344D0184C3902418DB6D81: "https://api-qa.ywtinfo.com/",
};

export function _ywtRequest({
  url,
  method = "post",
  data = {},
  headers = {},
  isShowLoadig = false,
  isShowError = false,
} = {}) {
  return new Promise((resolve) => {
    if (isShowLoadig) {
      my.showLoading();
    }
    const app = getApp();
    const ywtRequestUrl =
      ywtEnvUrl[app.globalData.templateUUID] + ywtEnvVersionPrefix;
    my.request({
      url: url.startsWith("http") ? url : joinUrl(ywtRequestUrl, url),
      method,
      data: Object.assign(data, {
        userId: app.globalData.ywtUserId || "",
        appId: app.globalData.appId || "",
        alipayUid: app.globalData.alipayUid,
        terminal,
      }),
      headers: {
        ...headers,
      },
      dataType: "json",
      success(res) {
        const result = res.data || {};
        const code = +result.code;
        if (result && code === 0) {
          resolve([
            null,
            {
              data: result.data,
              code,
            },
          ]);
        } else if (code === 20002 || code === 20001 || code === 20008) {
          resolve([
            null,
            {
              code,
              data: null,
            },
          ]);
        } else if (code >= 600) {
          // 自定义错误
          showErrorMessgage({
            isShowError: true,
            error: { msg: result.msg || "未知错误" },
          });
          my.hideLoading();
          resolve([result, null]);
        } else {
          showErrorMessgage({
            isShowError,
            error: result,
          });
          resolve([result, null]);
        }
      },
      fail(err) {
        showErrorMessgage({
          isShowError,
          error: err,
        });
        resolve([err, null]);
      },
      complete() {
        if (isShowLoadig) {
          my.hideLoading();
        }
      },
    });
  });
}

export async function getTicket() {
  // eslint-disable-next-line no-undef
  const app = getApp();
  const { appId } = app.globalData;
  if (!appId) {
    app.globalData.appId = getAppId();
  }
  const [err, res] = await getSilentAuthCode();
  if (err) return [err, null];
  const data = {
    authCode: res.authCode,
    appId: app.globalData.appId,
  };
  const result = await _request({
    url: getTicketUrl,
    data,
  });
  return result;
}

export async function setTicket() {
  const app = getApp();
  const { expiresTime } = app.globalData.ticketData;
  console.log("expiresTime", expiresTime);
  // 如果当前其他请求更新了ticket，则不用重新请求
  if (expiresTime && (await checkTimeExpire(expiresTime))) {
    console.log(
      "checkTimeExpire(expiresTime)",
      await checkTimeExpire(expiresTime)
    );
    return;
  }
  // 如果没有ticket正在请求，则在gloabl上增加setTicket
  if (!app.globalData.getTicketing) {
    app.globalData.setTicket = (async function () {
      app.globalData.getTicketing = true;
      const [err, res] = await getTicket();
      if (err) {
        return [err, null];
      }
      // eslint-disable-next-line no-undef
      app.globalData.ticketData.ticket = res.data.ticket;
      app.globalData.ticketData.expiresTime = res.data.expiresTime;
      app.globalData.getTicketing = false;
      return [null, res];
    })();
  }
  // 如果ticket正在请求，则返回正在请求的ticket
  return app.globalData.setTicket;
}

export default async function request(options) {
  const app = getApp();
  // 如果没有ticket直接请求ticket
  if (!app.globalData.ticketData.ticket && !options.noNeedTicket) {
    await setTicket();
  }
  const [err, res] = await _request(options);
  if (err) return [err, null];
  const code = +getIn(res, ["code"], "");
  if (code === 20001 || code === 20002 || code === 20008) {
    console.log("code ===>", code);
    const [error] = await setTicket();
    if (!error) {
      const result = await request(options);
      return result;
    }
    return [error, null];
  } else if (code === 401) {
    // 手动发起请求
    const currentStore = getCurrentStore();
    const { dispatchGlobal } = currentStore;
    const scopes = "auth_user";
    /* 这里表示如果不是通过按钮触发的手机号登录，需要打开按钮弹窗 */
    // if (currentScope !== scopes) {
    // await dispatch.call(currentStore, "launchPhone");
    // }
    const success = await dispatchGlobal("doLogin", { scopes });
    /* 登录失败 */
    if (!success) {
      showErrorMessgage({
        isShowError: true,
        error: { msg: "登录失败" },
      });
      my.navigateBack();
      return;
    }
    const result = await request(options);
    return result;
  }
  const data = res.data || null;
  return [null, data];
}

export async function ywtRequest(options) {
  const [err, res] = await _ywtRequest(options);
  if (err) return [err, null];
  const code = +getIn(res, ["code"], "");
  if (code === 20001 || code === 20002 || code === 20008) {
    const [error] = await setTicket();
    if (!error) {
      const result = await ywtRequest(options);
      return result;
    }
    return [error, null];
  }
  const data = res.data || null;
  return [null, data];
}
