import Vue from 'vue'

const request = uni.$u.http
const noMoreStatus = 'nomore'
const get = request.get.bind(request)

const createList = (config = {}) => ({
  requesting: false,
  status: 'loading',
  page: 0,
  data: [],
  ...config,
})

const getStatus = (res) => {
  const { has_next: hasNext, total_count: total } = res
  return total === 0 ? 'empty' : hasNext ? 'loading' : noMoreStatus
}

const getList = async (context, listKey = '', req = [], options = {}) => {
  const { transform = (data) => data, mergeData, abandon = () => false, beforeSetData = () => {}, callback = () => {} } = options

  const getTarget = () => context[listKey]
  const list = getTarget()

  const setList = (value) => Vue.set(context, listKey, value)
  const setKey = (key, value) => Vue.set(getTarget(), key, value)

  if (list.requesting || list.status === noMoreStatus) return

  setKey('requesting', true)
  const newPage = list.page + 1

  try {
    let res
    if (req instanceof Promise) {
      res = await req
    } else {
      const [url, data, ...restParams] = Array.isArray(req) ? req : [req]
      const params = { page: newPage, page_num: newPage, ...data }
      res = await get(url, { params }, ...restParams)
    }
    if (abandon()) return
    const newListData = transform(res.list)
    const newList = {
      ...list,
      total: res.total_count,
      status: getStatus(res),
      page: newPage,
      data: mergeData ? mergeData(list.data, newListData) : newPage === 1 ? newListData : [...list.data, ...newListData],
    }
    beforeSetData()
    setList(newList)
    return Promise.resolve(res)
  } catch (e) {
    console.error('getList:', e)
    setList({ ...list, status: 'error' })
  } finally {
    setKey('requesting', false)
  }
}

export { createList, getList }
