<template>
  <el-select
    ref="selectRef"
    clearable
    :multiple="props.multiple"
    :style="getWidth"
    v-model="selectValue"
    popper-class="table-select"
    @clear="selectClear"
    @remove-tag="selectRemoveTag"
  >
    <template #empty>
      <div class="table-select-content" ref="popoverContentRef" :style="getPopoverWidth">
        <BasicForm
          v-if="props.formProps.schemas"
          @reset="handleFormReset"
          @register="register"
          @submit="handleFormSubmit"
        />
        <BasicTable
          ref="basicTableRef"
          v-bind="getTableProps"
          :highlight-current-row="!props.multiple"
          :pagination="{ small: true, layout: 'prev, pager, next' }"
          :showTableSetting="false"
          :isKeepRowKeys="true"
          :rowSelection="getRowSelection"
          :max-height="365"
          @row-click="tableRowSelect"
          @select="tableSelect"
          @select-all="tableSelectAll"
          @fetch-success="tableFetchSuccess"
        />
      </div>
    </template>
  </el-select>
</template>

<script lang="ts" setup>
  import { ref, computed, watch, nextTick } from 'vue';
  import { BasicTable } from '../index';
  import { TableSelectProps } from './props';
  import { BasicForm, useForm } from '@/components/Form/index';
  import { cloneDeep } from 'lodash-es';
  import type { BasicColumn } from '@/components/Table/src/types/table';

  const selectValue = ref<any>();
  const selectRef = ref();
  const basicTableRef = ref();
  const selectedRowKeys = ref<any[]>([]);
  const popoverContentRef = ref();

  const props = defineProps({
    ...TableSelectProps,
  });

  const emit = defineEmits(['clear', 'remove-tag', 'change', 'update:value', 'form-values-change']);

  watch(
    () => props.value,
    () => {
      selectValue.value = props.value;
    },
    {
      immediate: true,
      deep: true,
    },
  );

  const getPopoverWidth = computed(() => {
    return {
      width: props.popoverWidth,
    };
  });

  const getWidth = computed(() => {
    return {
      width: props.width,
    };
  });

  const getTableProps = computed(() => {
    const tableProps = cloneDeep(props.tableProps);
    const newColumns: BasicColumn[] = tableProps.columns;
    if (props.multiple) {
      newColumns.unshift({
        type: 'selection',
        width: 45,
      });
    }
    return tableProps;
  });

  const getRowSelection = computed(() => {
    return {
      type: props.multiple ? 'checkbox' : 'radio',
      showCheckedAll: props.multiple ? true : false,
      selectedRowKeys: selectedRowKeys.value,
    };
  });

  const [register, { getFieldsValue }] = useForm({
    ...props.formProps,
  });

  // 表格数据加载完成
  function tableFetchSuccess() {
    nextTick(() => {
      const tableRef = basicTableRef.value.getTableRef();
      const tableData = getDataSource();
      if (props.multiple) {
        selectedRowKeys.value.forEach((row) => {
          const info = tableData.filter((item) => item[props.valueField] === row[props.valueField]);
          info.length && tableRef.toggleRowSelection(info[0], true);
        });
      } else {
        const info = tableData.filter(
          (item) => item[props.valueField] === selectedRowKeys.value[props.valueField],
        );
        tableRef.setCurrentRow(info[0]);
      }
    });
  }

  // 隐藏 select
  function selectBlur() {
    selectRef.value?.blur();
  }

  //清空
  function selectClear() {
    if (props.multiple) basicTableRef.value.getTableRef().clearSelection();
    else basicTableRef.value.getTableRef().setCurrentRow();
    selectedRowKeys.value = [];
    emit('clear', selectValue.value);
    emit('update:value', selectValue.value);
  }

  //多选删除
  function selectRemoveTag(val) {
    const row = findTableRow(val[props.valueField]);
    if (row) {
      basicTableRef.value.getTableRef().toggleRowSelection(row, false);
    } else {
      selectedRowKeys.value.splice(
        selectedRowKeys.value.findIndex((item) => item[props.valueField] == val[props.valueField]),
        1,
      );
    }
    emit('remove-tag', val);
  }

  //查找 table 行
  function findTableRow(value) {
    const tableList = basicTableRef.value?.getDataSource();
    return tableList.find((item) => item[props.valueField] === value);
  }

  function handleFormSubmit(values: Recordable) {
    emit('form-values-change', values);
    basicTableRef.value.reload(values);
  }

  function handleFormReset() {
    emit('form-values-change', getFormValues());
    basicTableRef.value.reload();
  }

  // 单选
  function tableRowSelect(row) {
    const _row = cloneDeep(row);
    _row.label = row[props.labelField];
    _row.value = row[props.valueField];
    selectValue.value = _row;
    selectBlur();
    emit('change', selectValue.value);
    emit('update:value', selectValue.value);
  }

  //多选
  function tableSelect(selection, row) {
    const isChecked = selection.length && selection.indexOf(row) !== -1;
    if (isChecked) {
      selectedRowKeys.value.push(row as any);
    } else {
      selectedRowKeys.value.splice(
        selectedRowKeys.value.findIndex((item) => item[props.valueField] == row[props.valueField]),
        1,
      );
    }
    const newList = selectedRowKeys.value.map((item) => {
      return {
        ...item,
        label: item[props.labelField],
        value: item[props.valueField],
      };
    });
    selectValue.value = newList;
    emit('change', selectedRowKeys.value);
    emit('update:value', selectedRowKeys.value);
  }

  //全选
  function tableSelectAll(selection) {
    const _selection = cloneDeep(selection);
    selectValue.value = _selection.map((item) => {
      return {
        ...item,
        label: item[props.labelField],
        value: item[props.valueField],
      };
    });
    emit('change', selectValue.value);
    emit('update:value', selectValue.value);
  }

  function getFormValues() {
    return getFieldsValue();
  }

  function getTagAllValues() {
    return selectValue.value;
  }

  function getDataSource() {
    return basicTableRef.value?.getDataSource();
  }

  defineExpose({
    getDataSource,
    getFormValues,
    getTagAllValues,
  });
</script>

<style lang="scss" scoped>
  .table-select {
    &-content {
      padding: 10px 20px 20px 20px;
    }
  }
</style>
