import Taro from '@tarojs/taro'
import {
  getMyInfo,
  getWechatUserInfoByCode,
  UserInfoResponse,
} from '../api/auth'
import {
  IS_LOGIN_STORAGE_KEY,
  OPEN_ID_STORAGE_KEY,
  USER_ID_ENCODED_STORAGE_KEY,
  USER_ID_STORAGE_KEY,
  USER_INFO_STORAGE_KEY,
  USER_TOKEN_STORAGE_KEY,
} from '../constant'

export function getNewCodeIfLogin(): Promise<string> {
  return new Promise((resolve, reject) => {
    const isLogin = Taro.getStorageSync(IS_LOGIN_STORAGE_KEY)
    if (!isLogin) {
      return reject()
    }
    Taro.login({
      success: (res) => {
        console.log('success code in refreshCode', res) // 不要注释: 开发时，该console用于观测code的消耗情况
        // 什么都不干，就是为了初始化的时候调用一次，确保后面获取到到code是有效的
        resolve(res.code)
      },
      fail: () => {
        console.log('fail code')
        reject()
      },
    })
  })
}

export function getNewCode(): Promise<string> {
  return new Promise((resolve, reject) => {
    Taro.login({
      success: (res) => {
        console.log('success code in refreshCode', res) // 不要注释: 开发时，该console用于观测code的消耗情况
        // 什么都不干，就是为了初始化的时候调用一次，确保后面获取到到code是有效的
        resolve(res.code)
      },
      fail: () => {
        console.log('fail code')
        reject()
      },
    })
  })
}

/**
 * 保存登录状(设为1)、保存userId、保存Token，保存整个data到storage
 * @param {*} data
 */
export function updateUserInfo(data) {
  console.log('set login info')
  Taro.setStorageSync(IS_LOGIN_STORAGE_KEY, '1')
  Taro.setStorageSync(USER_ID_STORAGE_KEY, data.userId)
  Taro.setStorageSync(USER_TOKEN_STORAGE_KEY, data.token)
  Taro.setStorageSync(USER_INFO_STORAGE_KEY, data)
}

export function clearUserInfo() {
  console.log('clear login info')
  Taro.clearStorageSync()
}

export function getUserInfo() {
  return Taro.getStorageSync(USER_INFO_STORAGE_KEY)
}

// 获取用户登录
export const getWechatUserInfo = async () => {
  const code = await getNewCodeIfLogin()
  const data = (await getWechatUserInfoByCode(code)).data

  return data
}

let userInfo: UserInfoResponse

export default function refreshUserId(canUseCache = false) {
  if (canUseCache && userInfo) {
    return Promise.resolve(userInfo)
  }
  if (Taro.getStorageSync(IS_LOGIN_STORAGE_KEY)) {
    return getMyInfo().then((res) => {
      // console.log(res,8888)
      Taro.setStorageSync(USER_ID_ENCODED_STORAGE_KEY, res.data.encodeUserId)
      Taro.setStorageSync(USER_ID_STORAGE_KEY, res.data.userId)
      userInfo = res.data
      return res.data
    })
  } else {
    return Promise.reject(new Error('unauthorized'))
  }
}

export function getUserId() {
  return Taro.getStorageSync(USER_ID_STORAGE_KEY) || ''
}

export function isMySelf(userId) {
  if (!userId) {
    return false
  }
  return Taro.getStorageSync(USER_ID_STORAGE_KEY) === userId
}

let openIdCache: string | null = null
let fetchOpenIdPromise: Promise<string> | null = null

async function fetchOpenId(): Promise<string> {
  if (fetchOpenIdPromise) return fetchOpenIdPromise

  fetchOpenIdPromise = (async () => {
    const data = await getWechatUserInfo()
    const { openId, userId } = data
    if (!openId) throw new Error('Failed to retrieve openId')

    Taro.setStorageSync(OPEN_ID_STORAGE_KEY, openId)
    if (userId) {
      await updateUserInfo(data)
    } else {
      throw new Error('Unregistered user (userId = 0)')
    }

    openIdCache = openId
    return openId
  })()

  try {
    return await fetchOpenIdPromise
  } catch (error) {
    fetchOpenIdPromise = null
    throw error
  }
}

export async function getOpenIdAsync(forceRefresh = false): Promise<string> {
  if (!forceRefresh && openIdCache) {
    try {
      await getMyInfo()
      return openIdCache
    } catch {}
  }

  if (!forceRefresh && !openIdCache) {
    const stored = Taro.getStorageSync(OPEN_ID_STORAGE_KEY) as
      | string
      | undefined
    if (stored) {
      try {
        await getMyInfo()
        openIdCache = stored
        return stored
      } catch {}
    }
  }

  return fetchOpenId()
}
