<template>
  <a-modal
    :width="900"
    v-model:visible="state.apiConfigDia"
    :title="title"
    :maskClosable="false"
    :bodyStyle="state.modalBodyStyle"
    destroyOnClose
    @cancel="handleClose"
  >
    <NodeHead nodeName="API信息" />
    <a-row type="flex" align="middle" gutter="20" class="mt-2.5">
      <a-col flex="90px"><em class="required-icon">*</em>{{ t('接口地址') }}</a-col>
      <a-col flex="auto">
        <a-input
          v-model:value="state.apiConfigInfo.path"
          :placeholder="t('点击选择接口')"
          @click="state.apiSelectDialog = true"
        >
          <template #addonAfter>
            <Icon icon="ant-design:ellipsis-outlined" />
          </template>
        </a-input>
      </a-col>
      <a-col flex="90px">{{ t('请求方式') }}</a-col>
      <a-col flex="auto">
        <a-input
          v-model:value="state.apiConfigInfo.method"
          :placeholder="t('选择接口后自动显示接口请求方式')"
          disabled
        />
      </a-col>
    </a-row>
    <a-tabs v-model:activeKey="state.activeKey">
      <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 #emptyText>
            <div class="table-empty">
              <img :src="emptyPng" />
              <div>暂无数据</div>
            </div>
          </template>
          <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>

    <template #footer>
      <div :class="['footer-container', hasExample ? '' : '!justify-end']">
        <a-button type="primary" v-if="hasExample" @mouseenter="state.isShowExample = true">{{
          t('返回出参格式')
        }}</a-button>
        <div>
          <a-button key="back" @click="handleCancel" class="cancel-api">{{
            '取消API配置'
          }}</a-button>
          <a-button key="back" @click="handleClose">{{ t('取消') }}</a-button>
          <a-button key="submit" type="primary" @click="handleSubmit">{{ t('确定') }}</a-button>
        </div>
      </div>
    </template>
    <div class="editor-box" v-if="state.isShowExample">
      <CodeEditor :value="example" language="json" readonly style="font-size: 12px" />
      <span class="editor-close" @click="state.isShowExample = false"> x </span>
      <span class="editor-copy" @click="copy">{{ t('复制代码') }}</span>
    </div>
  </a-modal>
  <ApiSelect
    v-if="state.apiSelectDialog"
    v-model:apiSelectDialog="state.apiSelectDialog"
    v-model:selectedApiId="state.apiConfigInfo.apiId"
    :example="example"
    @success="handleSuccess"
  />
</template>

<script lang="ts" setup>
  import { reactive, inject, onMounted, computed } from 'vue';
  import { Icon } from '/@/components/Icon';
  import { ColumnProps } from 'ant-design-vue/lib/table/Column';
  import ApiSelect from './components/ApiConfigSelect.vue';
  import { cloneDeep } from 'lodash-es';
  import { CodeEditor } from '/@/components/CodeEditor';
  import useClipboard from 'vue-clipboard3';
  import { message } from 'ant-design-vue';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { isValidJSON } from '/@/utils/event/design';
  import { NodeHead } from '/@/components/ModalPanel/index';
  import emptyPng from '/@/assets/images/empty.png';
  import { infoMap } from '../../Designer/src/types';

  const { t } = useI18n();

  const props = defineProps({
    apiConfig: {
      type: Object as PropType<any>,
    },
    apiConfigDialog: { type: Boolean },
    title: { type: String },
    isCascader: {
      type: Boolean,
      default: false,
    },
    isQrcode: {
      type: Boolean,
      default: false,
    },
    isLeftMenu: {
      type: Boolean,
      default: false,
    },
    isSubForm: {
      type: Boolean,
      default: false,
    },
    isLabelComponent: {
      type: Boolean,
      default: false,
    },
    formItem: {
      type: Object as PropType<any>,
    },
    hasExample: {
      type: Boolean,
      default: true,
    },
  });
  const emit = defineEmits(['update:apiConfigDialog', 'update:apiConfig']);
  const widgetForm = inject('widgetForm') as any;

  const { toClipboard } = useClipboard();

  const state = reactive({
    apiSelectDialog: false as boolean,
    apiConfigDia: props.apiConfigDialog as boolean,
    activeKey: '1' as string,
    isShowExample: false as boolean,
    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[],
    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,
  });
  const infoExample = JSON.stringify({
    code: 0,
    msg: t('提示信息'),
    data: [
      {
        label: t('选项一'),
        value: 1,
      },
      {
        label: t('选项二'),
        value: 2,
      },
      {
        label: t('选项三'),
        value: 3,
      },
    ],
  });
  const cascaderInfoExample = JSON.stringify({
    code: 0,
    msg: t('提示信息'),
    data: [
      {
        label: t('选项一'),
        value: 1,
        children: [
          {
            label: t('选项1-1'),
            value: '1-1',
          },
        ],
      },
      {
        label: t('选项二'),
        value: 2,
        children: [
          {
            label: t('选项2-1'),
            value: '2-1',
          },
        ],
      },
      {
        label: t('选项三'),
        value: 3,
        children: [
          {
            label: t('选项3-1'),
            value: '3-1',
          },
        ],
      },
    ],
  });
  const qrcodeExample = JSON.stringify({
    code: 0,
    msg: t('提示信息'),
    data: t('内容'),
  });
  const leftMenuExample = JSON.stringify({
    code: 0,
    msg: t('提示信息'),
    data: [
      {
        id: '1419276791701966848',
        parentId: '0',
        label: '总部',
        value: '10000',
        children: [
          {
            id: '1650072830909132801',
            parentId: '1419276791701966848',
            label: '测试部门',
            value: '测试部门',
          },
          {
            id: '1650072830909132801',
            parentId: '1419276791701966848',
            label: '开发部门',
            value: '开发部门',
          },
        ],
      },
      {
        id: '1650072999666954241',
        parentId: '0',
        label: '售后部门',
        value: '售后部门',
        children: [],
      },
    ],
  });
  const labelComponentInfoExample = JSON.stringify({
    code: 0,
    msg: t('提示信息'),
    data: [
      {
        label: t('选项一'),
      },
      {
        label: t('选项二'),
      },
      {
        label: t('选项三'),
      },
    ],
  });
  const example = computed(() => {
    return !props.hasExample
      ? ''
      : props.isCascader
      ? cascaderInfoExample
      : props.isQrcode
      ? qrcodeExample
      : props.isLabelComponent
      ? labelComponentInfoExample
      : props.isLeftMenu
      ? leftMenuExample
      : infoExample;
  });

  onMounted(() => {
    if (props.isLeftMenu) {
      state.dataInfo.splice(0, 2);
    }
    if (props.isSubForm) {
      state.dataInfo.splice(2, 1);
    }

    if (!!widgetForm?.value && !props.isLeftMenu) {
      widgetForm?.value?.hiddenComponent?.map((com) => {
        let obj = {
          bindField: com.bindField,
          bindTable: '',
          tableKey: '',
          fieldKey: com.key,
        };
        state.dataInfo[1].children.push({
          title: com.label,
          value: JSON.stringify(obj),
        });
      });
      if (widgetForm?.value?.list.length) {
        if (props.isSubForm) {
          getFormSelectedList(widgetForm.value.list);
        } else {
          getSelectedList(widgetForm.value.list);
        }
      }
    }

    if (!!props.apiConfig) {
      state.apiConfigInfo = cloneDeep(props.apiConfig);
      if (!props.apiConfig?.apiParams?.length) {
        state.apiConfigInfo.apiParams = [];
        state.apiConfigInfo.apiParams = state.interfaceInfo;
      }
    }
    // if (props.isSubForm) {
    //   state.bindType = [
    //     {
    //       label: t('值'),
    //       value: 'value',
    //     },
    //   ];
    // }
  });
  const filtercomps = [
    'divider',
    'upload',
    'image',
    'qrcode',
    'button',
    'map',
    'opinion',
    'title',
    'ai-answer',
  ];
  const getFormSelectedList = (list, bindTable?, key?) => {
    list?.map((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.layout!) {
          getFormSelectedList(child.list);
        }
      } else if (item.type === 'table-layout') {
        for (const child of item.layout!) {
          for (const el of child.list) {
            getFormSelectedList(el.children);
          }
        }
      } else if (item.type == 'one-for-one') {
        getFormSelectedList(item.children, item.bindTable, item.key);
      } else if (item.type == 'form') {
        let child: any[] = [];
        if (item.bindTable == props.formItem.bindTable) {
          item.children.map((o) => {
            if (!filtercomps.includes(o.type)) {
              let params: string[] = [];
              if (o.options.datasourceType == 'api' && o.options.apiConfig.apiParams) {
                o.options.apiConfig.apiParams.forEach((p) => {
                  p.tableInfo &&
                    p.tableInfo.forEach((o) => {
                      const value = isValidJSON(o.value);
                      if (value) params.push(value.fieldKey);
                    });
                });
              }
              if (o.key !== props.formItem.key && !params.includes(props.formItem.key)) {
                let bindField = o.bindField;
                if (o.type == 'time-range' || o.type == 'date-range') {
                  bindField = o.bindStartTime + ',' + o.bindEndTime;
                }
                let obj = {
                  bindField: bindField,
                  bindTable: props.formItem.bindTable,
                  tableKey: item.key,
                  fieldKey: o.key,
                };
                child.push({
                  title: o.label,
                  value: JSON.stringify(obj),
                });
              }
            }
          });
          state.dataInfo[0].children.push({
            title: item.label,
            value: item.bindTable,
            disabled: true,
            children: child,
          });
        }
      } else if (!filtercomps.includes(item.type)) {
        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 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) {
            getFormSelectedList(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);
              });
          });
        }
        if (item.key !== props.formItem?.key && !params.includes(props.formItem?.key)) {
          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 handleSelect = ({ value }, record) => {
    if (!value) {
      message.error(t('请先选择该组件的绑定表及绑定字段'));
      record.value = null;
    }
  };

  const handleCancel = () => {
    state.apiConfigInfo.apiId = '';
    state.apiConfigInfo.path = '';
    emit('update:apiConfig', state.apiConfigInfo);
    emit('update:apiConfigDialog', false);
  };

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

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

  const handleSuccess = (config) => {
    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' : '');
        });
      }
    });
  };

  const copy = async () => {
    try {
      await toClipboard(infoExample);
    } catch (e) {
      console.error(e);
    }
  };
</script>

<style lang="less" scoped>
  .required-icon {
    color: red;
  }

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

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

  .editor-box {
    width: 300px;
    position: absolute;
    height: 350px;
    left: 140px;
    bottom: 13px;
    border: 1px solid #ccc;
    box-shadow: 0 0 6px 3px #ccc;

    .editor-close {
      position: absolute;
      top: -3px;
      right: 13px;
      font-size: 16px;
      cursor: pointer;
    }

    .editor-copy {
      position: absolute;
      bottom: 5px;
      right: 15px;
      cursor: pointer;
      z-index: 999;
      color: #5e95ff;
    }
  }

  .cancel-api {
    background: #f70;
    border-color: #f70;
    color: #fff;
  }

  .table-empty {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
  }

  .ant-table-thead > tr > th {
    background: #f7fbff;
    border-bottom: 1px solid #ddd;
    font-weight: bold;

    &:not(
        :last-child,
        .ant-table-selection-column,
        .ant-table-row-expand-icon-cell,
        [colspan]
      )::before {
      background-color: #ddd;
    }
  }

  :deep(.ant-table-empty .ant-table-tbody > tr.ant-table-placeholder td) {
    border-bottom: 0;
  }
</style>
