export enum AuthCodeState {
  CANCEL = 'Cancel', // 取消
  WAITING = 'Waiting', // 等待
  SCANNED = 'Scanned', //
  CONFIRMED = 'Confirmed', // 确认
  TIMEOUT = 'Timeout', //
  OTHER = 'Bind_Other_Application', // 绑定了其他应用信息
  BOT_OTHER_APP = 'Bot_Has_Been_Bind', // 机器人有其他应用
  VERIFY = 'Verify', // 衙输入验证码
}

// 轮询状态
const polling = (
  callback: (...args: any[]) => Promise<any> | any,
  {
    time,
    overdue,
    pending,
    success,
    timeOut,
    verifyState,
    cancel,
    fail,
    bound,
    bindOtherApp,
  }: {
    time?: number
    overdue?: number
    success?: (resState?: any) => void
    cancel?: () => void
    timeOut?: () => void
    verifyState?: () => void
    pending?: () => void
    fail?: () => void
    bound?: () => void
    bindOtherApp?: () => void
  },
) => {
  let timer: any = null
  let loopTimer: number
  let isStop = false

  const start = (...args: any[]) => {
    isStop = false
    loop(...args)
    timer = setTimeout(async () => {
      isStop = true
      clearTimeout(timer)
      await fail?.()
    }, overdue || 300000)
  }
  const end = () => {
    isStop = true
    clearTimeout(timer)
  }

  // eslint-disable-next-line complexity
  const loop = async (...args: any[]) => {
    if (isStop) {
      clearTimeout(loopTimer)
      return
    }
    loopTimer = window.setTimeout(() => loop(...args), time || 3000)

    try {
      const resState = await callback(...args)
      switch (resState) {
        case AuthCodeState.SCANNED:
          await pending?.()
          break
        case AuthCodeState.CANCEL:
          await cancel?.()
          break
        case AuthCodeState.TIMEOUT:
          end()
          await timeOut?.()
          break
        case AuthCodeState.CONFIRMED:
          end()
          await success?.(resState)
          break
        case AuthCodeState.VERIFY:
          await verifyState?.()
          break
        case AuthCodeState.OTHER:
          await bound?.()
          break
        case AuthCodeState.BOT_OTHER_APP:
          await bindOtherApp?.()
          break
        default:
          break
      }
    } catch (err: any) {
      // end();
      // await fail?.();
      // throw err.message;
    }
  }
  return {
    start,
    end,
  }
}

export { polling }
