import { ref, computed, watch, nextTick, unref, onMounted, onBeforeUnmount, onDeactivated } from 'vue'
import { isDefine, toggleClass } from '@/utils/common'
import type { Ref, ShallowRef, UnwrapRef } from 'vue'
import type { InstanceTable } from 'global-type'
import type { MultipleResult } from '@/api/api'
import { throttle } from 'lodash-es'
import useMainStore from '@/store/main'
import bus from '@/utils/bus'
import { ElMessage } from 'element-plus'
type ArrayObjectType = Array<Record<string, any>>

type MultipleResultType<T = Record<string, any>> = MultipleResult<T>

type InputDataType = MultipleResultType | ArrayObjectType

type TableDataType<T> = Ref<T> | ShallowRef<T>

type ArrayData<T extends InputDataType> = T extends MultipleResultType<infer D> ? D : ExtractArrayValue<T>

type RowType<T extends TableDataType<InputDataType>> = ArrayData<UnwrapRef<T>> & {
  index: number
}
const mainStore = useMainStore()
function isMultipleData(data: any): data is MultipleResultType {
  return isDefine(data?.result) && isDefine(data?.totalCount)
}

const useTableCheck = <T extends TableDataType<InputDataType>>(data: T, auto = true, queryPosition: any = null) => {
  const tableRef = ref<InstanceTable>()

  const elTableRef = computed(() => {
    return tableRef?.value?.tableRef
  })
  const totalCount = ref<any>(null)
  const pageSize = ref<any>(null)
  const pageNumber = ref<any>(null)

  const initPaginationParams = () => {
    const _data: any = unref(data)
    if (isMultipleData(_data)) {
      totalCount.value = _data.totalCount
      pageSize.value = _data.pageSize
      pageNumber.value = _data.pageNumber
    }
  }
  initPaginationParams()
  watch(data, () => {
    initPaginationParams()
  })
  const tableData = computed(() => {
    const d = unref(data)
    // let result: RowType<T>[] = []
    let result: any[] = []
    if (d) {
      if (isMultipleData(d)) {
        result = d?.result?.map((d, index) => ({ ...d, index: d.index ?? index }))
      } else {
        result = d?.map((d, index) => ({ ...d, index: d.index ?? index }))
      }
    }
    return result
  })

  // const current = ref<RowType<T>>()
  const current = ref<any>()

  // const currentView = ref<RowType<T>>()
  const currentView = ref<any>()

  const visibleHistory = ref<boolean>(false)

  watch(
    tableData,
    () => {
      current.value = void 0
      currentView.value = void 0
      if (tableData?.value?.length && auto) {
        let positionIndex = 0
        if (!!queryPosition) {
          const key = Object.keys(queryPosition)[0]
          const fIndex = tableData.value.findIndex((item: any) => {
            if (queryPosition?.isFloat) {
              return parseFloat(item[key]) == parseFloat(queryPosition?.[key])
            } else {
              return item[key] == queryPosition?.[key]
            }
          })
          if (fIndex > -1) {
            positionIndex = fIndex
            queryPosition = null
          }
        }
        nextTick(() => {
          elTableRef?.value?.setCurrentRow(tableData.value[positionIndex])
          //设置了高亮的行号后，还需要让表格的dom滚动到该处
          const tBodyDomWrap: any = elTableRef?.value?.$refs.bodyWrapper
          if (tBodyDomWrap) {
            const index = positionIndex
            if (index % tableData.value.length == 0) {
              elTableRef?.value?.scrollTo({ left: 0, top: 0, behavior: 'smooth' })
            } else {
              const wrap = tBodyDomWrap.getElementsByClassName('el-scrollbar__wrap')[0]
              const oHeight = wrap.offsetHeight
              const sTop = wrap.scrollTop
              const sHeight = wrap.scrollHeight
              const targetRowAsHeight = 36 * positionIndex
              if (sHeight > oHeight && targetRowAsHeight > oHeight) {
                const t = sHeight - targetRowAsHeight
                elTableRef?.value?.scrollTo({ left: 0, top: targetRowAsHeight - 18, behavior: 'smooth' })
              }
            }
          }
        })
      }
    },
    { immediate: true }
  )

  /** 表格选中 */
  // const onCurrentChange = (row: RowType<T>) => {
  const onCurrentChange = (row: any) => {
    current.value = row
  }

  /** 表格行双击 */
  // const onDbClick = (row: RowType<T>) => {
  const onDbClick = (row: any) => {
    currentView.value = row
    visibleHistory.value = true
  }

  /** 下一份 */
  const next = () => {
    // elTableRef?.value?.setCurrentRow(tableData.value[((current.value?.index || 0) + 1) % tableData.value.length])
    const rightTableViewDom = document.querySelector('.table-view')
    if (rightTableViewDom) {
      toggleClass(rightTableViewDom, 'collapse')
    }
  }
  const nextRow = throttle(() => {
    console.log('current.value?.index:', current.value?.index)
    console.log('tableData.value.length:', tableData.value.length)
    if (current.value?.index == tableData.value.length - 1) {
      //说明高亮正处于最后一行了，需要提示用户是否需要翻到下一页。
      if (totalCount.value !== null && pageSize.value !== null) {
        // 说明页面只使用了useTableCheck，而未使用useTable。
        //注意：这里只处理只使用了useTableCheck而未使用useTable的情况。另外一种情况在useTable里处理。避免重复
        //只使用了useTableCheck，而未使用useTable的情况，基本上是pageSize传了99999这种情况，所以一页就是全部的数据，最后一行就是到底了
        if (pageNumber.value * pageSize.value + 1 > totalCount.value) {
          console.log('当前页已是最后一页: from useTableCheck')
          ElMessage.warning('当前页已是最后一页')
        } else {
          //该情况应该不可能出现，因为只使用了useTableCheck而未使用useTable的情况，是只有一页的，即pageSize传的999999之类
          // mainStore.setRowNextBottomDialogStatus(true)
        }
      } else {
        //在useTable里才能拿到分页相关信息，所以要对useTable进行通信，告诉它到了最后一行了，是否需要弹框诱导到下一页

        bus.emit('atBottomRowFromUseTableCheck')
      }
      return
    }
    const index = (current.value?.index || 0) + 1
    elTableRef?.value?.setCurrentRow(tableData.value[index % tableData.value.length])
    const tBodyDomWrap: any = elTableRef?.value?.$refs.bodyWrapper
    if (tBodyDomWrap) {
      if (index % tableData.value.length == 0) {
        elTableRef?.value?.scrollTo({ left: 0, top: 0, behavior: 'smooth' })
      } else {
        const wrap = tBodyDomWrap.getElementsByClassName('el-scrollbar__wrap')[0]
        const oHeight = wrap.offsetHeight
        const sTop = wrap.scrollTop
        const sHeight = wrap.scrollHeight
        const targetRowAsHeight = 36 * ((current.value?.index || 0) + 1)
        if (sHeight > oHeight && targetRowAsHeight - sTop > oHeight) {
          const t = sHeight - targetRowAsHeight
          elTableRef?.value?.scrollTo({ left: 0, top: sTop + 36, behavior: 'smooth' })
        }
      }
    }
    // elTableRef?.value?.scrollTo(0, (current.value?.index || 0) * 36)
  }, 300)
  const prevRow = throttle(() => {
    console.log('current.value?.index:', current.value?.index)
    if (current.value?.index > 0) {
      const index = current.value?.index
      elTableRef?.value?.setCurrentRow(tableData.value[index - 1])
      const tBodyDomWrap: any = elTableRef?.value?.$refs.bodyWrapper
      if (tBodyDomWrap) {
        if (index % tableData.value.length == 0) {
          elTableRef?.value?.scrollTo({ left: 0, top: 0, behavior: 'smooth' })
        } else {
          const wrap = tBodyDomWrap.getElementsByClassName('el-scrollbar__wrap')[0]
          const oHeight = wrap.offsetHeight
          const sTop = wrap.scrollTop
          const sHeight = wrap.scrollHeight
          const targetRowAsHeight = 36 * (current.value?.index || 0)
          if (targetRowAsHeight - 36 < sTop) {
            elTableRef?.value?.scrollTo({ left: 0, top: targetRowAsHeight - 36, behavior: 'smooth' })
          }
        }
      }
    }
  }, 300)
  const arrowDownToNextRow = (e: any) => {
    // if (e.target.tagName === 'INPUT' || (e.target.className || '').includes('contenteditable-ele')) {
    //   return false
    // }
    if ((e.target.className || '').includes('contenteditable-ele')) {
      return false
    }
    // e.preventDefault()

    if (e.key === 'ArrowDown') {
      e.preventDefault()
      nextRow()
    } else if (e.key === 'ArrowUp') {
      e.preventDefault()
      prevRow()
    }
  }
  onMounted(() => {
    document.addEventListener('keydown', arrowDownToNextRow)
  })
  onBeforeUnmount(() => {
    document.removeEventListener('keydown', arrowDownToNextRow)
  })
  onDeactivated(() => {
    document.removeEventListener('keydown', arrowDownToNextRow)
  })
  return {
    tableRef,
    elTableRef,
    tableData,
    current,
    currentView,
    visibleHistory,
    onCurrentChange,
    onDbClick,
    next,
    nextRow,
  }
}

export default useTableCheck
