<template>
  <a-modal
    :width="900"
    v-model:visible="state.pushOrderDialog"
    :title="title"
    :maskClosable="false"
    :bodyStyle="state.modalBodyStyle"
    destroyOnClose
    @cancel="handleClose"
    @ok="handleSubmit"
  >
    <div class="list-title">基本信息</div>
    <a-row type="flex" align="middle">
      <a-col flex="90px" class="text-right">
        <em class="required-icon">*</em>&nbsp;推单类型：
      </a-col>
      <a-col flex="1">
        <a-select v-model:value="state.pushOrderConfig.type" style="width: 100%">
          <a-select-option value="api">API</a-select-option>
          <a-select-option value="form">表单</a-select-option>
        </a-select>
      </a-col>
      <template v-if="state.pushOrderConfig.type === 'api'">
        <a-col flex="90px" class="text-right">
          <em class="required-icon">*</em>&nbsp;选择API：
        </a-col>
        <a-col flex="1">
          <a-input
            v-model:value="state.apiConfigInfo.path"
            :placeholder="t('点击选择接口')"
            @click="state.apiSelectDialog = true"
          >
            <template #suffix>
              <Icon icon="ant-design:ellipsis-outlined" />
            </template>
          </a-input>
        </a-col>
      </template>
      <template v-if="state.pushOrderConfig.type === 'form'">
        <a-col flex="90px" class="text-right">
          <em class="required-icon">*</em>&nbsp;目标单据：
        </a-col>
        <a-col flex="1">
          <FormSettingModal :list="state.pushOrderConfig.formInfo" @submit="handleFormSubmit">
            <InputModel :value="state.pushOrderConfig.formInfo.length" placeholder="请选择表单">
              <div
                v-if="state.pushOrderConfig.formInfo && state.pushOrderConfig.formInfo.length > 0"
              >
                <a-tag
                  v-for="(item, index) in state.pushOrderConfig.formInfo"
                  :key="item.formId"
                  closable
                  @close="closeTag(item.formName, index)"
                >
                  {{ item.formName }}
                </a-tag>
              </div>
            </InputModel>
          </FormSettingModal>
        </a-col>
      </template>
    </a-row>
    <a-tabs v-model:activeKey="state.activeApiKey" v-if="state.pushOrderConfig.type === 'api'">
      <a-tab-pane :key="item.key" :tab="item.title" v-for="item in state.apiConfigInfo.apiParams">
        <a-table
          :dataSource="item.tableInfo"
          :columns="state.apiConfigColumns"
          :pagination="false"
          :scroll="{ y: '400px' }"
        >
          <template #bodyCell="{ column, record }">
            <template v-if="column.key === 'bindType'">
              <a-select
                v-model:value="record.bindType"
                style="width: 100%"
                :placeholder="t('请选择赋值类型')"
                :options="state.bindType"
                allowClear
                @change="record.value = ''"
              />
            </template>
            <template v-else-if="column.key === 'value'">
              <a-tree-select
                v-model:value="record.value"
                show-search
                style="width: 100%"
                :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
                :placeholder="t('点击选择表单数据')"
                allow-clear
                tree-default-expand-all
                :tree-data="state.dataInfo"
                @select="(_, node) => handleSelect(node, record)"
                v-if="record.bindType === 'data'"
              />
              <a-input
                v-model:value="record.value"
                :placeholder="record.bindType ? t('请填写值') : t('请先选择赋值类型后再配置值')"
                v-else
              />
            </template>
          </template>
        </a-table>
      </a-tab-pane>
    </a-tabs>
    <a-tabs v-model:activeKey="state.activeFormKey" v-if="state.pushOrderConfig.type === 'form'">
      <a-tab-pane
        :key="item.key"
        :tab="item.formName"
        v-for="item in state.pushOrderConfig.formInfo"
      >
        <a-table
          :dataSource="item.config"
          :columns="state.formColumns"
          :pagination="false"
          :scroll="{ y: '400px' }"
        >
          <template #bodyCell="{ column, record, index }">
            <template v-if="column.dataIndex === 'order'">
              <span>
                {{ index + 1 }}
              </span>
            </template>
            <template v-if="column.dataIndex === 'from'">
              <a-tree-select
                v-model:value="record.from"
                style="width: 100%"
                placeholder="请选择来源单据参数"
                :tree-data="state.defaultCurrentFormData"
                allowClear
                treeDefaultExpandAll
                @change="(val) => handleData(val, item.formName, index)"
              />
            </template>
            <template v-if="column.dataIndex === 'target'">
              <a-tree-select
                v-model:value="record.target"
                style="width: 100%"
                placeholder="请选择目标单据参数"
                :tree-data="
                  state.formData[item.formName] ? state.formData[item.formName][index] : []
                "
                allowClear
                treeDefaultExpandAll
              />
            </template>
            <template v-if="column.dataIndex === 'action'">
              <span
                style="color: #ff8080; cursor: pointer"
                @click="handleRemove(item.key, index, item.formName)"
              >
                删除
              </span>
            </template>
          </template>
        </a-table>
        <a-button type="dashed" block @click="handleConfigAdd(item)">
          <PlusOutlined />
          {{ t('新增') }}
        </a-button>
      </a-tab-pane>
    </a-tabs>
  </a-modal>
  <ApiSelect
    v-if="state.apiSelectDialog"
    v-model:apiSelectDialog="state.apiSelectDialog"
    v-model:selectedApiId="state.apiConfigInfo.apiId"
    @success="handleSuccess"
  />
</template>

<script lang="ts" setup>
  import { reactive, inject, onMounted } from 'vue';
  import { Icon } from '/@/components/Icon';
  import { ColumnProps } from 'ant-design-vue/lib/table/Column';
  import ApiSelect from '/@/components/ApiConfig/src/components/ApiConfigSelect.vue';
  import FormSettingModal from './FormSettingModal.vue';

  import InputModel from '/@bpmn/components/InputModel.vue';
  import { cloneDeep } from 'lodash-es';
  import { message } from 'ant-design-vue';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { isValidJSON } from '/@/utils/event/design';
  import { PlusOutlined } from '@ant-design/icons-vue';
  import { getFormTemplate } from '/@/api/form/design';
  import { infoMap, noHaveTableAndField } from '/@/components/Designer/src/types';
  import { PushOrderConfig } from '/@/model/generator/listConfig';

  const { t } = useI18n();

  const props = defineProps({
    pushOrderConfig: {
      type: Object as PropType<PushOrderConfig>,
    },
    pushOrderDialog: { type: Boolean },
    title: { type: String },
  });
  const emit = defineEmits(['update:pushOrderDialog', 'update:pushOrderConfig']);
  const generatorConfig = inject('generatorConfig') as any;

  const state = reactive({
    apiSelectDialog: false as boolean,
    pushOrderDialog: props.pushOrderDialog as boolean,
    pushOrderConfig: {
      type: 'api',
      formInfo: [],
      apiConfig: {},
    } as PushOrderConfig,
    activeApiKey: '1' as string,
    activeFormKey: 0 as number,
    modalBodyStyle: {
      padding: '15px 15px 10px 10px',
      minHeight: '400px',
    },
    apiConfigColumns: [
      {
        title: t('API入参名称'),
        dataIndex: 'name',
        key: 'name',
        align: 'center',
      },
      {
        title: t('API入参类型'),
        dataIndex: 'dataType',
        key: 'dataType',
        align: 'center',
      },
      {
        title: t('赋值类型'),
        dataIndex: 'bindType',
        key: 'bindType',
        align: 'center',
      },
      {
        title: t('赋值配置'),
        dataIndex: 'value',
        key: 'value',
        align: 'center',
      },
    ] as ColumnProps[],
    formColumns: [
      {
        title: t('序号'),
        dataIndex: 'order',
        align: 'center',
        width: 80,
      },
      {
        title: '来源单据参数',
        dataIndex: 'from',
        align: 'center',
      },
      {
        title: '目标单据参数',
        dataIndex: 'target',
        align: 'center',
      },
      {
        title: t('操作'),
        dataIndex: 'action',
        align: 'center',
        width: 80,
      },
    ] as ColumnProps[],
    bindType: [
      {
        label: t('值'),
        value: 'value',
      },
      {
        label: t('表单数据'),
        value: 'data',
      },
    ],
    dataInfo: [
      {
        title: t('表单数据'),
        value: 'formData',
        disabled: true,
        children: [],
      },
      {
        title: '隐藏组件',
        value: 'hiddenComponents',
        disabled: true,
        children: [],
      },
      {
        title: '当前信息',
        value: 'currentInfo',
        disabled: true,
        children: infoMap,
      },
    ] as any[],
    interfaceInfo: [
      {
        key: '1',
        title: 'Query Params',
        tableInfo: [],
      },
      {
        key: '2',
        title: 'Header',
        tableInfo: [],
      },
      {
        key: '3',
        title: 'Body',
        tableInfo: [],
      },
    ],
    apiConfigInfo: {
      apiParams: [],
    } as any,
    formConfig: [],
    formData: [] as any,
    defaultFormData: {},
    currentFormData: {},
    defaultCurrentFormData: [] as any[],
  });

  onMounted(async () => {
    if (generatorConfig?.formJson.list.length) {
      getSelectedList(generatorConfig?.formJson.list);
      getTableComponents(
        generatorConfig?.formJson.list,
        t('主表组件'),
        state.defaultCurrentFormData,
      );
    }
    if (props.pushOrderConfig) {
      state.pushOrderConfig = cloneDeep(props.pushOrderConfig);
      if (state.pushOrderConfig.formInfo?.length) {
        await getFormComponents();
        state.pushOrderConfig.formInfo.forEach((item) => {
          if (item.config.length) {
            if (!state.formData[item.formName]) state.formData[item.formName] = [];
            item.config.forEach((o, i) => {
              state.formData[item.formName][i] = [];
              handleData(item.config[i].from, item.formName, i);
            });
          }
        });
      }
      if (!!state.pushOrderConfig.apiConfig) {
        state.apiConfigInfo = cloneDeep(state.pushOrderConfig.apiConfig);
      }
      if (!state.pushOrderConfig.apiConfig?.apiParams?.length) {
        state.apiConfigInfo.apiParams = state.interfaceInfo;
      }
    }
  });
  const filtercomps = ['divider', 'upload', 'image', 'qrcode', 'button', 'map', 'opinion', 'title'];
  const getSelectedList = (list, bindTable?, key?) => {
    list?.map((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.layout!) {
          getSelectedList(child.list);
        }
      } else if (item.type === 'table-layout') {
        for (const child of item.layout!) {
          for (const el of child.list) {
            getSelectedList(el.children);
          }
        }
      } else if (item.type == 'one-for-one') {
        getSelectedList(item.children, item.bindTable, item.key);
      } else if (item.type !== 'form' && !filtercomps.includes(item.type)) {
        let params: string[] = [];
        if (item.options.datasourceType == 'api' && item.options.apiConfig.apiParams) {
          item.options.apiConfig.apiParams.forEach((p) => {
            p.tableInfo &&
              p.tableInfo.forEach((o) => {
                const value = isValidJSON(o.value);
                if (value) params.push(value.fieldKey);
              });
          });
        }
        let bindField = item.bindField;
        if (item.type == 'time-range' || item.type == 'date-range') {
          bindField = item.bindStartTime + ',' + item.bindEndTime;
        }
        let obj = {
          bindField: bindField,
          bindTable: bindTable,
          tableKey: key,
          fieldKey: item.key,
        };
        state.dataInfo[0].children.push({
          title: item.label,
          value: JSON.stringify(obj),
        });
      }
    });
  };
  const getTableComponents = (list, tableName, formData, key?) => {
    list.forEach((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.layout!) {
          getTableComponents(child.list, tableName, formData);
        }
      } else if (item.type === 'table-layout') {
        for (const child of item.layout!) {
          for (const list of child.list) {
            getTableComponents(list.children, tableName, formData, key);
          }
        }
      } else if (item.type === 'one-for-one') {
        getTableComponents(item.children, item.label, formData, item.key);
      } else if (item.type === 'form') {
        const itemChildren = item.children.filter((child) => {
          return !noHaveTableAndField.includes(child.type) && child.type !== 'sun-form';
        });
        const children: any[] = [];
        itemChildren.forEach((ichild) => {
          if (['time-range', 'date-range'].includes(ichild.type)) {
            children.push({
              label: ichild.label + '开始时间',
              value: `${ichild.bindTable},${ichild.bindStartTime}`,
            });
            children.push({
              label: ichild.label + '结束时间',
              value: `${ichild.bindTable},${ichild.bindEndTime}`,
            });
          } else {
            children.push({
              label: ichild.label,
              value: `${ichild.bindTable},${ichild.bindField}`,
            });
          }
        });

        formData.push({
          label: item.label,
          value: item.key,
          isSubform: true,
          disabled: true,
          children,
        });
      } else if (!noHaveTableAndField.includes(item.type)) {
        const index = formData?.findIndex((x) => x.label === tableName);
        let info;
        if (['time-range', 'date-range'].includes(item.type)) {
          info = [
            {
              label: item.label + '开始时间',
              value:
                tableName === t('主表组件')
                  ? item.bindStartTime
                  : `${item.bindTable},${item.bindStartTime}`,
            },
            {
              label: item.label + '结束时间',
              value:
                tableName === t('主表组件')
                  ? item.bindEndTime
                  : `${item.bindTable},${item.bindEndTime}`,
            },
          ];
        } else {
          info = [
            {
              label: item.label,
              value:
                tableName === t('主表组件')
                  ? item.bindField
                  : `${item.bindTable},${item.bindField}`,
            },
          ];
        }

        if (index >= 0) {
          formData[index].children.push(...info);
        } else if (formData) {
          formData.unshift({
            label: tableName,
            value: tableName === t('主表组件') ? '1' : key,
            isSubForm: false,
            disabled: true,
            children: [...info],
          });
        }
      }
    });
  };

  const getFormComponents = async () => {
    let formData = {};
    state.currentFormData = {};

    await Promise.all(
      state.pushOrderConfig.formInfo.map(async (item) => {
        state.currentFormData[item.formName] = cloneDeep(state.defaultCurrentFormData);

        const data = await getFormTemplate(item.formId);
        if (data) {
          formData[data.name] = [];
          const formJson = JSON.parse(data.formJson);
          getTableComponents(formJson.formJson.list, t('主表组件'), formData[data.name]);
        }
      }),
    );
    state.defaultFormData = cloneDeep(formData);
  };

  const handleSelect = ({ value }, record) => {
    if (!value) {
      message.error(t('请先选择该组件的绑定表及绑定字段'));
      record.value = null;
    }
  };

  const handleClose = () => {
    emit('update:pushOrderDialog', false);
  };

  const closeTag = (formName, index) => {
    state.pushOrderConfig.formInfo.splice(index, 1);

    state.pushOrderConfig.formInfo.forEach((item, index) => {
      item.key = index;
    });
    if (state.activeFormKey > 0) {
      state.activeFormKey -= 1;
    }
    if (state.formData[formName]) delete state.formData[formName];
  };

  const handleConfigAdd = (item) => {
    state.pushOrderConfig.formInfo[item.key].config.push({
      from: '',
      target: '',
    });
    state.formData[item.formName].push([]);
  };

  const handleRemove = (formKey, index, formName) => {
    state.pushOrderConfig.formInfo[formKey].config.splice(index, 1);
    state.formData[formName].splice(index, 1);
  };

  const handleFormSubmit = (info) => {
    state.pushOrderConfig.formInfo = info.map((item, index) => {
      if (!state.formData[item.formName]) {
        state.formData[item.formName] = [];
      }
      return {
        ...item,
        key: index,
        index,
        config: item.config || [],
      };
    });
    getFormComponents();
  };

  const handleSubmit = () => {
    state.pushOrderConfig.apiConfig = state.apiConfigInfo;
    emit('update:pushOrderConfig', state.pushOrderConfig);
    emit('update:pushOrderDialog', false);
  };

  const handleSuccess = (config) => {
    config.script = undefined;
    state.apiConfigInfo = config;
    state.apiConfigInfo?.apiParams.forEach((para) => {
      if (!!para.tableInfo && para.tableInfo.length) {
        para.tableInfo?.map((item) => {
          return (item.bindType = !!item.value && !item.bindType ? 'value' : '');
        });
      }
    });
    state.apiSelectDialog = false;
  };

  const handleData = (val, formName, index) => {
    if (!val) return;

    const selectedData = state.currentFormData[formName].find((data) => {
      return data.children.find((child) => child.value === val);
    });
    const isSubForm = selectedData?.isSubForm;

    state.formData[formName][index] = state.defaultFormData[formName].filter(
      (x) => x.isSubForm === isSubForm,
    );
  };
</script>

<style lang="less" scoped>
  .list-title {
    font-size: 14px;
    line-height: 16px;
    margin-bottom: 10px;
  }

  .required-icon {
    color: red;
  }

  .footer-container {
    display: flex;
    justify-content: space-between;
  }

  :deep(.ant-tabs-nav) {
    margin: 10px 0 5px 10px;
  }
</style>
