<template>
  <div class="select-table">
    <cip-search-form v-if="searchFieldList.length > 0"
      style="margin-bottom: 10px;"
      :grid="3"
      v-model:model="searchFilter"
      :field-list="searchFieldList"
      :default-model="config?.defaultSearchFilter"
      @search="handleSearch" />
    <div class="select-table-box">
      <page-layout-list class="dialog-table">
        <cip-table
          v-if="checkType === 'radio'"
          ref="tableRef"
          v-loading="listLoading"
          :data="itemList"
          :columns="tableColumns"
          :offset="offset"
          size="small"
          :select-type="checkType"
          :select-radio="selectRadio"
          :select-label="optionProps.value"
          @current-change="currentChange"></cip-table>
        <cip-table
          v-if="checkType === 'checkbox'"
          ref="tableRef"
          v-loading="listLoading"
          :data="itemList"
          :columns="tableColumns"
          :offset="offset"
          size="small"
          :select-type="checkType"
          :selectable="selectable"
          @select="onSelect"
          @select-all="onSelectAll"></cip-table>
        <template v-if="withPagination" #pagination>
          <cip-pagination
            v-model:offset="offset"
            v-model:limit="limit"
            :total="total"
            :current-page="currentPage"
            @refresh="getItemList"></cip-pagination>
        </template>
      </page-layout-list>
      <slot name="group"></slot>
      <tags
        v-if="!$slots.group && withTags"
        class="dialog-tags"
        :options="checkOptions"
        :key-prop="optionProps"
        @update:options="updateOptions"></tags>
    </div>
  </div>
</template>

<script>
import { useCurd } from '@cip/hooks/use-curd'
import { useTableCacheSelect } from '@cip/components/hooks/table-cache-select'
import { ref, computed, nextTick, watch, watchEffect } from 'vue'
import { ElLoading } from 'element-plus'
import PageLayoutList from '@cip/components/page-layout/list'
import CipSearchForm from '@cip/components/cip-search-form'
import CipTable from '@cip/components/cip-table'
import CipPagination from '@cip/components/cip-pagination'
import { useFormInput, useOptions } from '@cip/components/hooks/form-input'
import { formInputProps, fromInputEmits } from '../../form-input-props'
import Tags from './tags.vue'
export default {
  components: { Tags, PageLayoutList, CipSearchForm, CipTable, CipPagination },
  directives: {
    loading: ElLoading.directive
  },
  props: formInputProps,
  emits: [...fromInputEmits],
  setup (props, context) {
    const { proxyValue, updateStream, securityConfig } = useFormInput(
      props,
      context
    )
    const { optionProps } = useOptions(props, false, updateStream)
    const valueKey = computed(() => optionProps.value.value)
    const labelKey = computed(() => optionProps.value.label)
    const checkType = computed(() => securityConfig.value.checkType ?? 'radio')
    const tableColumns = computed(() => securityConfig.value.tableColumns ?? [])
    const searchFieldList = computed(
      () => securityConfig.value.searchFieldList ?? []
    )
    const withPagination = computed(
      () => securityConfig.value.withPagination ?? true
    )
    const withTags = computed(() => securityConfig.value.withTags ?? true)
    const selectable = computed(
      () => securityConfig.value.selectable ?? (() => true)
    )
    const multiple = computed(() => checkType.value === 'checkbox')

    const tableRef = ref()
    const CURD = useCurd(props.config.entity, {
      ...props.config.curdFn,
      itemType: props.config.itemType
    })

    const { itemList, getItemList, searchFilter, search } = CURD
    // 外层触发请求
    const getTableList = (item = {}) => {
      searchFilter.value = {
        ...props.config.defaultSearchFilter,
        ...searchFilter.value,
        ...item
      }
      getItemList()
    }
    // 外层获取search搜索条件值
    const getSearchFilter = () => {
      return { ...props.config.defaultSearchFilter, ...searchFilter.value }
    }
    const { cacheSelectedList, onSelect, onSelectAll } = useTableCacheSelect(
      itemList,
      valueKey.value,
      (val) => {
        proxyValue.value = val
      }
    )

    const checkOptions = computed(() => {
      if (cacheSelectedList.value.length === 0) {
        if (props.modelValue) {
          return multiple.value
            ? props.modelValue
            : {
              [valueKey.value]: props.modelValue[valueKey.value] ?? '',
              [labelKey.value]: props.modelValue[labelKey.value] ?? ''
            }
        }
        return multiple.value ? [] : {}
      } else {
        return cacheSelectedList.value
      }
    })

    // 右侧数据改变
    const updateOptions = (newSelectedValue) => {
      cacheSelectedList.value = newSelectedValue
      proxyValue.value = newSelectedValue
      handleSelectShow()
    }

    watch(
      () => props.config?.defaultSearchFilter,
      (val = {}) => {
        getTableList(val)
      },
      { immediate: true }
    )

    // 已选择的radio
    const selectRadio = computed(() => {
      if (props.modelValue && props.modelValue[valueKey.value]) {
        return props.modelValue[valueKey.value]
      }
      return radioCache.value
    })

    // radio类型时的缓存
    const radioCache = computed(() => {
      const cache = itemList.value?.find(
        (v) => v[valueKey.value] === props.modelValue
      )
      return cache ? cache[valueKey.value] : undefined
    })

    const currentChange = (currentRow) => {
      // 单选不能取消，只能有值时才填入
      if (currentRow) {
        proxyValue.value = currentRow
      }
    }

    // checkbox类型更新选中视图
    const showSelectedView = (rows, select) => {
      nextTick(() => {
        rows.forEach((row) => {
          tableRef.value.cipTableRef.toggleRowSelection(row, select)
        })
      })
    }

    // tag组件传入值需要更新table选中视图
    const handleSelectShow = () => {
      const selectedPropsCode = cacheSelectedList.value.map(
        (button) => button[valueKey.value]
      )
      const rows = itemList.value.filter((item) => {
        return !selectedPropsCode.includes(item[valueKey.value])
      })
      showSelectedView(rows, false)
    }

    if (checkType.value === 'checkbox') {
      // 分页切换时缓存数据处理
      watch(
        () => [itemList.value, props.modelValue],
        () => {
          cacheHandle()
        }
      )
    } else {
      const unWatch = watchEffect(() => {
        if (props.modelValue && props.modelValue[valueKey.value]) {
          const checkItem = itemList.value.filter(
            (item) => item[valueKey.value] === props.modelValue[valueKey.value]
          )[0]
          if (checkItem) {
            proxyValue.value = checkItem
            unWatch()
          }
        }
      })
    }

    // 缓存数据处理
    const cacheHandle = () => {
      if (cacheSelectedList.value.length === 0) {
        cacheSelectedList.value = props.modelValue ?? []
      }
      const cacheSelectButtonCode = cacheSelectedList.value.map(
        (button) => button[valueKey.value]
      )
      const rows = itemList.value.filter((item) => {
        const selectList =
          props.modelValue ||
          (cacheSelectButtonCode.includes(item[valueKey.value])
            ? cacheSelectButtonCode
            : [])
        return (
          selectList.findIndex(
            (v) => v[valueKey.value] === item[valueKey.value]
          ) !== -1
        )
      })
      showSelectedView(rows, true)
    }
    // 搜索
    const handleSearch = (type) => {
      search()
    }

    return {
      updateOptions,
      checkOptions,
      getTableList,
      getSearchFilter,
      handleSearch,
      optionProps,
      checkType,
      tableColumns,
      searchFieldList,
      withPagination,
      withTags,

      ...CURD,
      tableRef,
      selectable,
      selectRadio,
      currentChange,
      onSelect,
      onSelectAll,
      cacheSelectedList
    }
  }
}
</script>

<style lang="less" scoped>
.select-table {
  flex: 1;
  .select-table-box {
    display: flex;
  }
  .dialog-table {
    flex: 1;
    margin: 0 15px 15px 0;
    padding: 0;
  }
  .dialog-tags {
    padding: 8px 0;
    flex-basis: 220px;
  }
}
</style>
