<template>
  <div ref="wrap">
    <BasicTable @register="registerTable">
      <template #headerTop>
        <Alert type="info" show-icon>
          <template #message>
            <template v-if="checkedKeys.length > 0">
              <span>{{ t('已选中') }}{{ checkedKeys.length }}{{ t('条记录(可跨页)') }}</span>
              <a-button type="link" @click="checkedKeys = []" size="small">{{
                t('清空')
              }}</a-button>
            </template>
            <template v-else>
              <span>{{ t('未选中任何项目') }}</span>
            </template>
          </template>
        </Alert>
      </template>
      <template #toolbar>
        <a-button type="primary" @click="handleCreate">{{ t('新增') }}</a-button>
        <a-button type="primary" @click="handleBatchDelete">{{ t('批量删除') }}</a-button>
        <ImpExcel @success="loadDataSuccess" dateFormat="YYYY-MM-DD">
          <a-button type="primary"> {{ t('导入Excel') }} </a-button>
        </ImpExcel>
      </template>
      <template #action="{ record }">
        <TableAction
          :actions="[
            {
              icon: 'clarity:note-edit-line',
              onClick: handleEdit.bind(null, record),
            },
            {
              icon: 'ant-design:delete-outlined',
              color: 'error',
              popConfirm: {
                title: t('是否确认删除'),
                confirm: handleDelete.bind(null, record),
              },
            },
          ]"
        />
      </template>
    </BasicTable>

    <TableModal @register="registerModal" :formOption="formOption" @success="handleSuccess" />
  </div>
</template>
<script lang="ts" setup>
  import { computed, ref, unref, watch, onMounted, toRaw } from 'vue';
  import { Alert } from 'ant-design-vue';
  import { ImpExcel, ExcelData } from '/@/components/Excel';

  import { BasicTable, useTable, TableAction, BasicColumn } from '/@/components/FormTable';
  import { FormSchema } from '/@/components/TableForm/index';

  import TableModal from './components/TableModal.vue';
  import { useModal } from '/@/components/Modal';
  import { buildUUID } from '/@/utils/uuid';
  import { isFunction } from '/@/utils/is';
  import { get, omit } from 'lodash-es';
  import { useI18n } from '/@/hooks/web/useI18n';
  const { t } = useI18n();
  const replaceColumn = ['ApiSelect', 'ApiRadioGroup', 'ApiCheckboxGroup', 'ApiCascader', 'Upload'];

  type OptionsItem = { label: string; value: string; disabled?: boolean };

  // 入参
  const props = defineProps({
    tableOption: { type: [Array] as PropType<BasicColumn[]>, required: true }, //表格配置json
    formOption: { type: [Array] as PropType<FormSchema[]>, required: true }, //表单配置json
    value: { type: [Array] as PropType<Recordable[]> }, // 值
    readonly: { type: Boolean }, //是否只读
  });

  const emit = defineEmits(['change', 'update:value']);

  //所选行
  const checkedKeys = ref<Array<string | number>>([]);

  const isUpdate = ref(false);

  const columns = computed(() => props.tableOption);
  const formOption = computed(() => props.formOption);

  const [registerModal, { openModal }] = useModal();

  const [
    registerTable,
    { getDataSource, deleteTableDataRecord, updateTableDataRecord, setTableData },
  ] = useTable({
    rowKey: 'rowKey',
    columns,
    useSearchForm: false,
    showTableSetting: true,
    tableSetting: { fullScreen: true },
    bordered: true,
    actionColumn: {
      width: 80,
      title: t('操作'),
      dataIndex: 'action',
      slots: { customRender: 'action' },
    },
    rowSelection: {
      type: 'checkbox',
      selectedRowKeys: checkedKeys,
      onChange: (selectedRowKeys: (string | number)[]) => {
        if (!selectedRowKeys) return;
        checkedKeys.value = selectedRowKeys ?? [];
      },
    },
  });

  /**
   * 监听外部传入变化。(重置表单 触发)
   */
  watch(
    () => props.value,
    () => {
      console.log(t('监听'), props.value);
      checkedKeys.value = [];
      setTableData(props.value ?? []);
    },
  );

  function handleCreate() {
    isUpdate.value = false;
    openModal(true, { isUpdate });
  }

  function handleEdit(record: Recordable) {
    isUpdate.value = true;
    openModal(true, { isUpdate, record: record });
  }

  function handleDelete(record: Recordable) {
    checkedKeys.value = [];
    deleteTableDataRecord(record.rowKey);
  }

  function handleBatchDelete() {
    if (checkedKeys.value.length === 0) return;
    deleteTableDataRecord(checkedKeys.value as string[]);
    checkedKeys.value = [];
    emit('change', []);
    emit('update:value', []);
  }

  function handleSuccess(record: Recordable) {
    const data = getDataSource();

    // 遍历表单所提交的所有值  如果当前字段为 远程组件的。 将保存值 替换 显示值
    for (const key in record) {
      if (datasourceMap.has(key)) {
        const options: OptionsItem[] = datasourceMap.get(key)!;

        //如果是数组类型（多选框，级联是数组结构）
        if (Array.isArray(unref(record[key]))) {
          let labelFieldStr = '';
          record[key].map((r: any) => {
            const thisOption = options.find((op) => op.value === r);
            thisOption && (labelFieldStr += thisOption.label + ',');
          });
          //如果根据字段名 能找到option  就赋值  没有就显示原有值
          labelFieldStr &&
            (record[key + '_labelField'] = labelFieldStr.slice(labelFieldStr.length, 1));
        } else {
          //不是数组就直接替换
          const thisOption = options.find((op) => op.value === record[key]);
          //如果根据字段名 能找到option  就赋值  没有就显示原有值
          thisOption && (record[key + '_labelField'] = thisOption?.label);
        }
      }
    }

    if (unref(isUpdate)) {
      updateTableDataRecord(record.rowKey, record);
    } else {
      data.push(record);
    }
    emit('change', toRaw(data));
    emit('update:value', toRaw(data));
  }
  // 当前子表单所有 远程数据  <字段名,数据源>
  const datasourceMap = new Map<string, OptionsItem[]>();
  //加载子表单 默认获取所有的 异步请求出来的 数据 （下拉框，多选 单选等组件）
  onMounted(() => {
    formOption.value.map((schema) => {
      //遍历所有子表单组件  是否有需要替换的列
      if (replaceColumn.includes(schema.component)) {
        fetch(schema.componentProps, schema.field);
      }
    });
  });

  // 导入
  function loadDataSuccess(excelDataList: ExcelData[]) {
    // console.log(excelDataList);
    const data = getDataSource();
    for (const excelData of excelDataList) {
      const { results } = excelData;

      results.map((item) => {
        const importObj = {} as Recordable;
        for (const key in item) {
          const col = columns.value.find((x) => x.title === key);
          if (col) {
            importObj.rowKey = buildUUID();
            importObj[col!.dataIndex!] = item[key];
          }
        }
        data.push(importObj);
        // importArry.push(importObj);
      });
    }
    emit('change', data);
    emit('update:value', data);
  }

  //远程数据源 发送请求的方法
  async function fetch(props: any, field: string) {
    const api = props.api;

    // 如果不是远程的 默认给option
    if (!props.remote) {
      datasourceMap.set(field, props.options);
      return;
    }

    if (!api || !isFunction(api)) return;

    try {
      const res = await api(props.params);

      if (Array.isArray(res)) {
        datasourceMap.set(field, getOption(props, res));
        return;
      }
      if (props.resultField) {
        datasourceMap.set(field, getOption(props, get(res, props.resultField) || []));
      }
    } catch (error) {
      console.warn(error);
    }
  }

  //从请求中获取到绑定值
  function getOption(props, options) {
    const { labelField, valueField, numberToString } = props;

    return unref(options).reduce((prev, next: Recordable) => {
      if (next) {
        const value = next[valueField];
        prev.push({
          label: next[labelField],
          value: numberToString ? `${value}` : value,
          ...omit(next, [labelField, valueField]),
        });
      }
      return prev;
    }, [] as OptionsItem[]);
  }
</script>
