import axios from 'axios'
import { ref, watch, onActivated, onMounted } from 'vue'
import { getApp } from '@/app'
import { UN_REQ_NUM } from '@/constant'
import { throttle } from '@/util'

const getOperState = (attr) => {
  const operState = ref({
    state: {
      show: false,
      id: 0, 
      ...JSON.parse(JSON.stringify(attr)) 
    },
    _readyUpdate(item) {
      operState.value.state.id = item.id
      operState.value.state.show = true
  
      Object.keys(attr).forEach(key => {
        operState.value.state[key] = attr[key]
      })

      Object.keys(attr).forEach(key => {
        if (item[key] !== void 0) {
          operState.value.state[key] = item[key]
        }
      })
    },
    readyInsert() {
      operState.value.reset()
      operState.value.state.show = true
    },
    reset() {
      Object.keys(attr).forEach(key => {
        operState.value.state[key] = attr[key]
      })
      operState.value.state.show = false
      operState.value.state.id = void 0
    },
    quit() {
      operState.value.reset()
    }
  })
  console.log('getOperState',operState)
  return operState
}

const getSearchState = (attr) => {
  const searchState = ref({
    state: { ...JSON.parse(JSON.stringify(attr)) },
    reset() {
      Object.keys(attr).forEach(key => {
        searchState.value.state[key] = attr[key]
      })
    }
  })

  return searchState
}


const getDataListState = (isSelect) => {
  const listStateState = ref({
    state: [],
  })

  if (isSelect) {
    listStateState.value.selectRows = []
    listStateState.value.changeSelectRows = (data) => {
      listStateState.value.selectRows = data
    }
  }

  return listStateState
}

const getPagState = () => {
  const pagState = ref({
    state: {
      currPage: 1,
      size: 12,
      total: 0
    },
    sizeChange(attr) {
      pagState.value.state.size = attr
    },
    currentChange(attr) {
      pagState.value.state.currPage = attr
    }
  })

  return pagState
}

const referListData = async (ret, getUrl, pagAttr = {}) => {
  let params = {
    pageNum: ret.pag.value.state.currPage,
    pageSize: ret.pag.value.state.size
  }
  if (ret.search) {
    Object.keys(ret.search.value.state).forEach(key => {
      if (UN_REQ_NUM !== ret.search.value.state[key]) {
        if (typeof ret.search.value.state[key] === 'string') {
          params[key] = ret.search.value.state[key].trim()
        } else {
          params[key] = ret.search.value.state[key]
        }
      }
    })
  }
  
  try {
    let res = await axios.get(getUrl,  { params })
    ret.pag.value.state.total = pagAttr['totalNum'] ? res.data[pagAttr['totalNum']] : res.data.total
    ret.dataList.value.state = res.data.records = 'list'in pagAttr ?  pagAttr['list'] ? res.data[pagAttr['list']] : res.data : res.data.records
  } catch {
    ret.dataList.value.state = []
    ret.pag.value.state.total = 0
  }
  
}


export default ({operAttr, searchAttr, pagAttr, isSelect = true, getUrl, updateUrl, insertUrl, delUrl, delMsg, delAttr } = {}) => {
  let ret = {
    dataList: getDataListState(isSelect),
    pag: getPagState()
  }
  let watchItems = [
    () => ret.pag.value.state.currPage,
    () => ret.pag.value.state.size,
  ]

  if (operAttr) {
    const oper = getOperState(operAttr)

    oper.value.readyUpdate = function(...args) {
      oper.value._readyUpdate(...args)
      oper.value.state.__oldData = ret.dataList.value.state.find(({id}) => id === oper.value.state.id)
    }

    updateUrl && (
      oper.value.update = async (data) => {
        let target = data || oper.value.state
        let updateIndex = ret.dataList.value.state.findIndex(({id}) => id === target.id)
        let item = { ...ret.dataList.value.state[updateIndex] }

        if (item) {
          Object.keys(operAttr).forEach(key => item[key] = target[key])
        }
        
        await axios.post(updateUrl, data || item)
        
        ret.dataList.value.state[updateIndex] = item
        oper.value.reset()
        ret.dataList.value.refer()
      }
    )

    insertUrl && (
      oper.value.insert = async (data) => {
        let target = data || oper.value.state
        console.log(oper.value.state)
        let item = {}
        Object.keys(operAttr).forEach(key => item[key] = target[key])
        await axios.post(insertUrl, data || item)

        ret.dataList.value.state.push(item)
        oper.value.reset()
        ret.dataList.value.refer()
      }
    )

    ret.oper = oper
  }

  if (searchAttr) {
    const search = getSearchState(searchAttr)

    search.value.submit = () => {
      ret.dataList.value.refer()
    }
    ret.search = search

    watchItems.push(search.value.state)
  }


  if (updateUrl || delUrl) {
    if (delUrl) {
      ret.dataList.value._delete = async (data) => {
        let reqData = {}
        if (delAttr) {
          for (let [k, v] of Object.entries(delAttr)) {
            reqData[k] = data[v]
          }

          console.log(delAttr, data, reqData)
        } else {
          reqData.id = data.id
        }
        await axios.post(delUrl, reqData)
      }
    } else {
      ret.dataList.value._delete = async (data) => {
        data.isDelete = 1
        await axios.post(updateUrl, data)
      }
    }

    ret.dataList.value.delete = async (data) => {
      if (await getApp().$confirm(delMsg || '确定要删除此数据吗？', '提示')) {
        await ret.dataList.value._delete(data)
        getApp().$message({message: '删除成功', type: 'success'});
        ret.dataList.value.refer()
      }
    }

    if (isSelect) {
      ret.dataList.value.deleteSelect = async () => {
        const rows = ret.dataList.value.selectRows
        if (rows.length === 0) {
          getApp().$message.error('请勾选数据后再删除数据！', '提示')
        } else if (await getApp().$confirm(`确定要删除这${rows.length}条数据吗？`, '提示')) {
          await Promise.all(rows.map(item => ret.dataList.value._delete(item)))
          getApp().$message({message: '删除成功', type: 'success'});
          ret.dataList.value.refer()
        }
      }
    }
  }

  ret.dataList.value.refer = throttle(
    () => {
      referListData(ret, getUrl, pagAttr)
    },
    100
  )

  // 刷新数据
  watch( watchItems, ret.dataList.value.refer )
  // 激活再刷新一次
  onActivated(() => referListData(ret, getUrl, pagAttr))
  onMounted(() => referListData(ret, getUrl, pagAttr))
  console.log('getTableState',ret)
  return ret
}