import Taro from '@tarojs/taro';

import { LoginResponse } from '@/types/login';

import http from '.';
import { API } from './api';
import { TOKEN_KEY, TOKEN_EXPIRES_TIME } from './constant';

let token = '';
let _fetchTokenPromise: Promise<string> | null = null;

const getCode = (): Promise<string> => {
  return new Promise((resolve, reject) => {
    Taro.login({
      success: res => resolve(res.code),
      fail: reject,
    });
  });
};

const clearToken = () => {
  token = '';
  Taro.setStorageSync(TOKEN_KEY, '');
  Taro.setStorageSync(TOKEN_EXPIRES_TIME, 0);
};

const requestToken = (): Promise<string> => {
  return getCode()
    .then(code => {
      return http.post<LoginResponse>(API.LOGIN, { data: { code } }).then(data => {
        const newToken = data?.token || '';
        const expires = data?.expires || 0;
        if (newToken) {
          token = newToken;
          Taro.setStorageSync(TOKEN_KEY, newToken);
        }
        if (expires) {
          Taro.setStorageSync(TOKEN_EXPIRES_TIME, Date.now() + expires);
        }
        return newToken;
      });
    })
    .finally(() => {
      _fetchTokenPromise = null;
    });
};

export const isTokenExpired = () => (Taro.getStorageSync(TOKEN_EXPIRES_TIME) || 0) < Date.now();

export const refreshToken = () => {
  if (_fetchTokenPromise) {
    return _fetchTokenPromise;
  }
  clearToken();
  _fetchTokenPromise = requestToken();
  return _fetchTokenPromise;
};

export const getToken = () => {
  if (token) {
    return token;
  }
  token = Taro.getStorageSync(TOKEN_KEY);
  return token;
};
