<template>
  <a-modal
    :width="800"
    :visible="props.multipleDialog"
    :title="title"
    :destroyOnClose="true"
    @ok="submitDialog"
    @cancel="closeDialog"
    :okText="t('确认')"
    :cancelText="t('取消')"
    :bodyStyle="{ padding: '20px' }"
  >
    <a-spin :spinning="state.spinning">
      <a-row :gutter="12" style="margin-bottom: 10px">
        <a-col :span="8">
          <a-input
            v-model:value="state.searchText"
            :placeholder="t('请输入要查询的关键字')"
            @keypress.enter="getDatasourceList(1)"
          />
        </a-col>
        <a-col>
          <a-button type="primary" @click="getDatasourceList(1)">
            <template #icon><Icon icon="ant-design:search-outlined" /></template>
            {{ t('搜索') }}
          </a-button>
        </a-col>
        <a-col>
          <a-button @click="resetSearch">
            <template #icon><Icon icon="ant-design:sync-outlined" /></template>
            {{ t('重置') }}
          </a-button>
        </a-col>
      </a-row>
      <a-tabs
        v-model:activeKey="state.activeKey"
        v-if="popupType === 'multiple' || popupType === 'preload' || popupType === 'button'"
      >
        <a-tab-pane key="1" :tab="t('数据选择')" style="overflow-y: auto">
          <a-table
            :dataSource="state.dataSourceList"
            :columns="state.sourceColumns"
            :row-selection="{
              selectedRowKeys: state.selectedRowKeys,
              onChange: onSelectChange,
              onSelect: handleSelect,
            }"
            :customRow="customRow"
            :rowKey="valueField"
            :pagination="paginationProps"
            :scroll="{ y: '200px' }"
          />
        </a-tab-pane>
        <a-tab-pane key="2" :tab="t('已选记录')" force-render>
          <a-table
            :dataSource="selectedList"
            :columns="state.selectedColumns"
            :scroll="{ y: '200px' }"
          >
            <template #bodyCell="{ column, record, index }">
              <template v-if="column.key === 'delete'">
                <Icon
                  icon="ant-design:delete-outlined"
                  color="#f56c6c"
                  @click="deleteSelected(record, index)"
                  style="cursor: pointer"
                />
              </template>
            </template>
          </a-table>
        </a-tab-pane>
      </a-tabs>
      <a-table
        v-else-if="popupType === 'associate'"
        :dataSource="state.dataSourceList"
        :columns="state.sourceColumns"
        :pagination="paginationProps"
        :rowKey="valueField"
        :row-selection="{
          selectedRowKeys: state.selectedRowKeys,
          onChange: onSelectChange,
          type: 'radio',
        }"
        :customRow="customRow"
        :scroll="{ y: '200px' }"
      />
    </a-spin>
  </a-modal>
</template>

<script lang="ts" setup>
  import { onMounted, watch, reactive, computed, inject, ref } from 'vue';
  import { cloneDeep } from 'lodash-es';
  import { Icon } from '/@/components/Icon';
  import { getDatasourceById } from '/@/api/system/datasource';
  import { getDicDetailPageList } from '/@/api/system/dic';
  import { isFunction } from '/@/utils/is';
  import type { ColumnProps } from 'ant-design-vue/lib/table';
  import { apiConfigFunc, camelCaseString } from '/@/utils/event/design';
  import { useI18n } from '/@/hooks/web/useI18n';
  const { t } = useI18n();
  const props = defineProps({
    multipleDialog: { type: Boolean },
    popupType: { type: String },
    dataSourceOptions: { type: Array },
    params: {
      type: [Array, Object, String, Number],
    },
    value: {
      type: String,
    },
    popupValue: { type: String },
    labelField: { type: String, default: 'label' },
    valueField: { type: String, default: 'value' },
    selectedDataSource: {
      type: Array as PropType<any[]>,
      default: () => [],
    },
    dicOptions: { type: Array as PropType<any[]> },
    //数据来源 默认为空  如果不为空
    datasourceType: String,
    apiConfig: Object,
    tableColumns: { type: Array },
    //是否子表按钮选数据使用
    isSubFormUse: {
      type: Boolean,
      default: false,
    },
    mainKey: String,
    subTableIndex: Number,
    pageSize: { type: Number, default: 10 },
    assoTitle: { type: String },
    api: {
      type: Function,
      default: null,
    },
    outputParams: {
      type: Array,
    },
  });
  const emit = defineEmits([
    'update:multipleDialog',
    'update:popupValue',
    'update:selectedDataSource',
    'getList',
    'submit',
  ]);

  onMounted(async () => {
    if (props.isSubFormUse) {
      await getDatasourceList(1);
    }
  });

  watch(
    () => props.multipleDialog,
    async (val) => {
      if (val) {
        await getDatasourceList(1);
      }
    },
  );

  const state = reactive({
    selectedRowKeys: [] as any[],
    activeKey: '1',
    searchText: '',
    sourceColumns: [] as ColumnProps[],
    selectedColumns: [] as ColumnProps[],
    dataSourceList: [] as any[],
    assoComponent: {},
    spinning: false,
  });

  const selectedList = ref(props.selectedDataSource);

  const paginationProps = reactive({
    current: 1,
    total: 0,
    defaultPageSize: props.pageSize,
    onChange: (page) => getDatasourceList(page),
  });
  const formModel = inject<any>('formModel', null);
  const isCamelCase = inject<boolean>('isCamelCase', false);
  const title = computed(() => {
    switch (props.popupType) {
      case 'multiple':
        return t('多选弹层-选择记录');
      case 'associate':
        return props.assoTitle || '联想弹层-联想数据配置';
      case 'preload':
      case 'button':
        return t('选择数据');
      default:
        return '';
    }
  });

  watch(
    () => props.datasourceType,
    (val) => {
      let options = [] as any[];
      if (val === 'datasource' && props.dataSourceOptions?.length) {
        options = props.dataSourceOptions as any[];
      }
      if (val === 'dic' && props.dicOptions?.length) {
        options = props.dicOptions as any[];
      }
      if (val === 'api') {
        options = props.apiConfig?.outputParams as any[];
      }
      if (props.api && props.outputParams) {
        options = props.outputParams;
      }
      options?.map((item: any) => {
        if (item.show || !Object.keys(item).includes('show')) {
          state.sourceColumns.push({
            title: item.tableTitle,
            dataIndex: item.name,
            align: 'center',
            width: Number(item.width),
          });
        }
      });
      state.selectedColumns = cloneDeep(state.sourceColumns);
      state.selectedColumns.unshift({
        align: 'center',
        title: '',
        dataIndex: 'delete',
        key: 'delete',
        width: 50,
      });
    },
    {
      deep: true,
      immediate: true,
    },
  );

  watch(
    () => [state.dataSourceList, props.selectedDataSource, props.value],
    () => {
      emit('getList', state.dataSourceList);
    },
    {
      deep: true,
    },
  );
  const customRow = (record) => {
    return {
      onClick: () => {
        handleClick(record);
      },
    };
  };
  const setSelected = (selectedDataSource) => {
    selectedList.value = [];
    state.selectedRowKeys = [];
    if (props.value) {
      selectedDataSource.map((select: any) => {
        selectedList.value.push(select);
        state.selectedRowKeys.push(select.value);
      });
    }
  };

  const resetSearch = () => {
    state.searchText = '';
    getDatasourceList(1);
  };
  const closeDialog = () => {
    emit('update:multipleDialog', false);
  };

  const submitDialog = () => {
    let saveValueArr: string[] = [];
    let showValueArr: string[] = [];
    let saveValue = '';
    let showValue = '';
    selectedList.value?.map((item: any) => {
      saveValueArr.push(item[props.valueField!]);
      showValueArr.push(item[props.labelField!]);
    });
    //value相同去重
    saveValue = [...new Set(saveValueArr)].join(',');
    showValue = showValueArr.join(',');
    setFormModel();
    emit('update:multipleDialog', false);
    emit('update:popupValue', showValue);
    emit('update:selectedDataSource', selectedList.value);
    emit('submit', props.isSubFormUse ? selectedList.value : saveValue);
  };

  const setFormModel = (isNull?) => {
    if (props.popupType === 'associate') {
      let assoConfig;
      if (props.api && props.outputParams) assoConfig = props.outputParams;
      switch (props.datasourceType) {
        case 'datasource':
          assoConfig = props.dataSourceOptions;
          break;
        case 'dic':
          assoConfig = props.dicOptions;
          break;
        case 'api':
          assoConfig = props.apiConfig?.outputParams;
          break;
      }
      if (!formModel) return;
      assoConfig?.map((item: any) => {
        if (item.bindField) {
          const value = selectedList.value.length ? selectedList.value![0][item.name] : '';
          let bindField = !isCamelCase ? item.bindField : camelCaseString(item.bindField);
          let bindTable = '';
          if (item.bindTable) {
            bindTable = !isCamelCase
              ? item.bindTable + 'List'!
              : camelCaseString(item.bindTable + '_List')!;
          }
          let val = isNull ? '' : value;
          if (props.mainKey) {
            if (!item.bindTable) {
              formModel[bindField!] = val;
            } else {
              formModel[props.mainKey][props.subTableIndex!][bindField!] = val;
            }
          } else {
            if (item.bindTable) {
              formModel[bindTable][0][bindField!] = val;
            } else {
              formModel[bindField!] = val;
            }
          }
        }
      });
    } else if (props.popupType === 'button') {
      let table = '';
      selectedList.value?.forEach((x) => {
        const dataObj = {
          isButtonSet: true,
        };
        props.tableColumns?.map((item: any) => {
          if (!item?.bindField) return;
          if (item.bindTable && !table)
            table = !isCamelCase
              ? item.bindTable + 'List'!
              : camelCaseString(item.bindTable + '_List')!;
          let bindField = !isCamelCase ? item.bindField : camelCaseString(item.bindField);
          dataObj[bindField as string] = item.prestrainField ? x[item.prestrainField] : null;
        });
        if (formModel[table]) formModel[table].push(dataObj);
      });
    }
  };

  const getDatasourceList = async (limit = 1) => {
    state.spinning = true;
    paginationProps.current = limit;
    let api;
    if (props.datasourceType) {
      if (props.datasourceType === 'dic') {
        api = getDicDetailPageList;
      }
      if (props.datasourceType === 'datasource') {
        api = getDatasourceById;
      }
      if (props.datasourceType === 'api') {
        const apiConfigParams = cloneDeep(props.apiConfig);
        //默认添加分页参数
        apiConfigParams!.apiParams?.length &&
          apiConfigParams!.apiParams[0].tableInfo.push({
            name: 'limit',
            value: paginationProps.current,
            bindType: 'value',
          });

        apiConfigParams!.apiParams?.length &&
          apiConfigParams!.apiParams[0].tableInfo.push({
            name: 'size',
            value: paginationProps.pageSize,
            bindType: 'value',
          });
        if (!!state.searchText) {
          const keywordInfo =
            apiConfigParams!.apiParams &&
            apiConfigParams!.apiParams[0].tableInfo?.find((item) => item.name === 'keyword');
          if (keywordInfo) {
            keywordInfo.value = state.searchText;
            keywordInfo.bindType = 'value';
          } else {
            if (!apiConfigParams!.apiParams) {
              apiConfigParams!.apiParams = [{ key: '1', title: 'Query Params', tableInfo: [] }];
            }
            apiConfigParams!.apiParams[0].tableInfo.push({
              name: 'keyword',
              value: state.searchText,
              bindType: 'value',
            });
          }
          state.dataSourceList = await apiConfigFunc(
            apiConfigParams,
            isCamelCase,
            formModel,
            props.subTableIndex,
            paginationProps,
          );
        } else {
          state.dataSourceList = await apiConfigFunc(
            apiConfigParams,
            isCamelCase,
            formModel,
            props.subTableIndex,
            paginationProps,
          );
          emit('getList', state.dataSourceList);
        }
        state.spinning = false;
      }
    } else {
      api = props.api;
      console.log('apooooo', api);
    }
    if (!api || !isFunction(api)) return;
    state.dataSourceList = [];
    try {
      let dataParams = {};

      const pageParams = { order: 'desc', size: 10, limit, keyword: state.searchText };
      if (props.datasourceType === 'dic') {
        Object.assign(dataParams, props.params, pageParams);
      } else if (props.datasourceType === 'datasource') {
        Object.assign(
          dataParams,
          {
            id: props.params as string,
          },
          pageParams,
        );
      } else if (props.api && props.params) {
        dataParams = props.params;
      }
      const res = await api(dataParams);
      state.spinning = false;
      state.dataSourceList = res.list;
      paginationProps.total = Number(res.total);
      emit('getList', state.dataSourceList);
    } catch (error) {
      console.warn(error);
    }
  };

  const onSelectChange = (rowKeys, selectedRows) => {
    if (props.popupType !== 'associate') {
      if (rowKeys.length <= 0) {
        state.selectedRowKeys = [];
        selectedList.value = [];
        return;
      }
      state.selectedRowKeys = [...new Set([...state.selectedRowKeys, ...rowKeys])];
      const rows = [...selectedList.value, ...selectedRows];
      selectedList.value = removeDuplicates(rows);
    } else {
      state.selectedRowKeys = rowKeys;
      selectedList.value = selectedRows;
    }
  };

  const handleSelect = (record, selected) => {
    if (!selected) {
      state.selectedRowKeys = state.selectedRowKeys.filter((x) => x !== record.value);
      selectedList.value = selectedList.value.filter((x) => x.value !== record.value);
    }
  };

  const removeDuplicates = (tempArr) => {
    for (let i = 0; i < tempArr.length; i++) {
      for (let j = i + 1; j < tempArr.length; j++) {
        if (tempArr[i].value === tempArr[j].value) {
          tempArr.splice(j, 1);
        }
      }
    }
    return tempArr;
  };

  const deleteSelected = (record, index) => {
    selectedList.value.splice(index, 1);
    state.selectedRowKeys = state.selectedRowKeys.filter((item) => {
      return item !== record.value;
    });
  };
  function handleClick(val) {
    if (props.popupType !== 'associate') {
      if (state.selectedRowKeys.includes(val[props.valueField])) {
        handleSelect(val, null);
      } else {
        onSelectChange([val[props.valueField]], [val]);
      }
    } else {
      onSelectChange([val[props.valueField]], [val]);
    }
  }
  defineExpose({ getDatasourceList, setFormModel, setSelected });
</script>

<style scoped lang="less"></style>
