<script setup lang="ts">
import type { VxeFormProps } from 'vxe-pc-ui'

import type { MjListProps } from '.'
import type { MjFormProps } from '../mj-table'

import type { BasicService } from '#/api/service/basic'

import obj from '#/utils/obj'

import { mj_form_input } from '../mj-table'

defineOptions({ name: 'MjList' })

const props = withDefaults(
  defineProps<
    MjListProps & {
      searchForm?: MjFormProps
      searchParams?: any
      service: BasicService
    }
  >(),
  {
    autoLoad: true,
    searchForm: undefined,
    searchParams: undefined,
  },
)

// 列表数据
const rows = ref([] as any[])

// 分页数据
const pager = ref({
  current: 1,
  size: 10,
  totalRows: 150,
})

const listRef = ref()
const listBoxRef = ref()

const listHeight = computed(() => {
  return listRef.value?.offsetHeight
    ? `${listRef.value?.offsetHeight}px !important`
    : '100%'
})

// 滚动到顶部
function scrollToTop() {
  if (listBoxRef.value) {
    listBoxRef.value.scrollTop = 0
  }
}

// 搜索表单事件
const searchFormEvents = {
  submit() {
    reload()
  },
}

// 搜索表单
const defaultSearchFormOptions = {
  titleBold: true,
  data: {},
  collapseNode: true,
} as VxeFormProps
const _searchForm = ref({} as VxeFormProps)

// 初始化搜索表单
function initSearchForm() {
  const searchFormOptions = {
    ...defaultSearchFormOptions,
    data: props.searchForm?.data || {},
  }
  obj.cover(searchFormOptions, props.searchForm)
  searchFormOptions.items = [
    {
      field: 'keyword',
      title: '关键字',
      span: 6,
      titleWidth: 70,
      itemRender: {
        name: mj_form_input,
        props: {
          clearable: true,
        },
      },
    },
    ...(props.searchForm?.items || []),
    {
      slots: { default: 'action' },
    },
  ]
  _searchForm.value = searchFormOptions
}

// 页码改变
function pageChange() {
  reloadAndScrollTop()
}

function reloadAndScrollTop() {
  reload(() => {
    // 数据加载完成后滚动到顶部
    nextTick(() => {
      scrollToTop()
    })
  })
}

// 加载数据
const loading = ref(false)
async function reload(success?: any) {
  loading.value = true
  try {
    // 搜索条件
    let findPageParams = {
      current: pager.value.current,
      size: pager.value.size,
      ...props.searchParams,
      ..._searchForm.value.data,
    } as any
    if (props.beforeLoadData) {
      findPageParams = props.beforeLoadData(findPageParams)
    }
    let res = await props.service.findPage(
      pager.value.current,
      pager.value.size,
      findPageParams,
    )
    if (props.afterLoadData) {
      res = props.afterLoadData(res)
    }
    pager.value.totalRows = res.totalRows
    rows.value = res.rows

    success && success(res)
  } finally {
    loading.value = false
  }
}

// 重置搜索表单
function searchFormReset() {
  _searchForm.value.data = {}
  // 重新搜索
  reload()
}

watch(
  [() => props.searchForm, () => props.searchParams],
  () => {
    initSearchForm()
    if (props.autoLoad) {
      reload()
    }
  },
  {
    immediate: true,
    // 深度监听
    deep: true,
  },
)

defineExpose({
  reload,
  scrollToTop,
  reloadAndScrollTop,
  updateSearchFormData(data: any) {
    if (!data) return
    obj.cover(_searchForm.value.data, data)
  },
})
</script>

<template>
  <div class="mj-list" v-loading="loading">
    <vxe-form v-bind="_searchForm" v-on="searchFormEvents">
      <template #action>
        <vxe-button icon="vxe-icon-repeat" @click="searchFormReset">
          重置
        </vxe-button>
        <vxe-button type="submit" icon="vxe-icon-search" status="primary">
          搜索
        </vxe-button>
      </template>
    </vxe-form>
    <div
      class="list-wrapper"
      ref="listRef"
      :style="{
        height: listHeight,
      }"
    >
      <div
        v-if="rows.length > 0"
        ref="listBoxRef"
        class="list-box"
        :style="{
          height: listHeight,
        }"
      >
        <div class="item-box" v-for="(item, index) in rows" :key="item.id">
          <slot name="item" :row="item" :index="index"></slot>
        </div>
      </div>
      <div v-else class="empty">暂无数据</div>
    </div>
    <vxe-pager
      v-model:current-page="pager.current"
      v-model:page-size="pager.size"
      :total="pager.totalRows"
      :layouts="[
        'Home',
        'PrevJump',
        'PrevPage',
        'Number',
        'NextPage',
        'NextJump',
        'End',
        'Sizes',
        'FullJump',
        'Total',
      ]"
      @page-change="pageChange"
    />
  </div>
</template>

<style lang="scss" scoped>
$radius: 4px;

.mj-list {
  display: flex;
  flex-direction: column;
  gap: 20px;
  height: 100%;

  .empty {
    font-size: 32px;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100%;
    color: #969799;
  }

  .vxe-form {
    border-radius: $radius;
  }

  .vxe-pager {
    margin-top: 0;
  }

  .list-wrapper {
    display: flex;
    flex: 1;
    flex-direction: column;
    overflow: hidden;

    .list-box {
      display: flex;
      flex-direction: column;
      gap: 16px;
      height: 100%;
      overflow: auto;
    }
  }
}
</style>
