<template>
  <BasicModal
    v-bind="$attrs"
    @register="registerModal"
    :title="t('脚本配置')"
    @ok="handleSubmit"
    @visible-change="visibleChange"
    width="70%"
  >
    <div class="config-box">
      <div>
        <a-tabs
          v-model:activeKey="configTab"
          style="margin-bottom: 8px; background: #fff; height: 100%"
        >
          <a-tab-pane key="widget" :tab="t('脚本示例')">
            <div>
              <div
                v-for="(item, index) in example"
                :key="index"
                :class="['script-name', { 'active-name': activeIndex === index }]"
                @click="handleScriptClick(index)"
              >
                {{ item.name }}
              </div>
            </div>
          </a-tab-pane>
          <a-tab-pane key="component" :tab="t('选择组件')">
            <a-collapse v-model:activeKey="tableActiveKey" expand-icon-position="right">
              <a-collapse-panel
                v-for="(item, index) in widgetFormList"
                :key="index"
                :header="item.label"
              >
                <draggable
                  v-model="item.children"
                  item-key="item.key"
                  :group="{ name: 'script', pull: false, put: false }"
                  @end="dragEnd"
                  :sort="false"
                >
                  <template #item="{ element }">
                    <a-tag color="blue">{{
                      `${element.label}(${
                        ['button', 'modal'].includes(element.type) ? element.key : element.bindField
                      })`
                    }}</a-tag>
                  </template>
                </draggable>
              </a-collapse-panel>
            </a-collapse>
          </a-tab-pane>
        </a-tabs>
      </div>
      <div>
        <div class="box-top">
          <NodeHead nodeName="脚本示例代码" />
        </div>
        <div style="height: calc(100% - 40px)">
          <CodeEditor :value="example[activeIndex].script" language="js" readonly />
        </div>
      </div>
      <div>
        <div class="box-top">
          <NodeHead nodeName="自定义脚本" />
        </div>
        <div style="height: calc(100% - 40px)">
          <CodeEditor v-model:value="definedScript" language="js" :readonly="disabled" />
        </div>
      </div>
    </div>
    <a-drawer
      :title="t('组件列表(可将组件拖入自定义脚本当中)')"
      placement="left"
      :visible="componentVisible"
      :get-container="false"
      :style="{ position: 'absolute' }"
      :mask="false"
      width="50%"
      :closable="false"
    >
      <Draggable
        v-model="widgetFormList"
        :group="{ name: 'script', pull: false, put: false }"
        item-key="key"
        @end="dragEnd"
        :sort="false"
      >
        <template #item="{ element }">
          <a-tag color="blue">{{
            `${element.label}(${
              ['button', 'modal'].includes(element.type) ? element.key : element.bindField
            })`
          }}</a-tag>
        </template>
      </Draggable>
      <template #extra>
        <CloseOutlined @click="componentVisible = false" />
      </template>
    </a-drawer>
  </BasicModal>
</template>

<script lang="ts" setup>
  import { ref, inject, onMounted } from 'vue';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { CodeEditor } from '/@/components/CodeEditor';
  import Draggable from 'vuedraggable';
  import { CloseOutlined } from '@ant-design/icons-vue';
  import { camelCaseString } from '/@/utils/event/design';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { noHaveTableAndField } from '/@/components/Designer/src/types';
  import { getScriptDemoList, getScriptDemoInfo } from '/@/api/system/script';
  import { ScriptResultModel } from '/@/api/system/script/model';
  import { NodeHead } from '/@/components/ModalPanel/index';
  import { cloneDeep } from 'lodash-es';

  interface ExampleModel {
    script?: string;
  }
  type Example = ExampleModel & ScriptResultModel;
  defineProps({
    disabled: { type: Boolean, default: false },
  });

  const { t } = useI18n();
  const eventType = ref('');
  const definedScript = ref(``);
  const emit = defineEmits(['success', 'register']);
  const activeIndex = ref(0);
  const componentVisible = ref<boolean>(false);
  const configIndex = ref();
  const configTab = ref('widget');
  const tableActiveKey = ref([0]);
  const example = ref<Example[]>([]);

  const widgetFormList = ref<any>([]); //整个表单json配置
  const isCustomForm = inject<boolean>('isCustomForm', false);
  // const example = reactive([
  //   {
  //     title: t('读写组件值'),
  //     code: `const value = formModel.bindField //主表获取组件值
  //     formModel.bindField = 1 //主表修改组件值
  //     // bindField: 组件的绑定字段

  //     const value = formModel.表名[索引].字段名 //子表获取组件值
  //     formModel.表名[索引].字段名 = 1 //子表修改组件值

  //     // 例：table52477Child2409List[0].danXingWenBen3280
  //     // 索引表示第几行对应字段的值，索引从0开始，第一行索引为0，第二行索引为1，以此类推`,
  //   },
  //   {
  //     title: t('ajax加载服务器数据'),
  //     code: `formActionType.httpRequest({
  //         requestType: 'get', //请求方式有: get、post、put、delete
  //         requestUrl: '/system/dictionary-detail', //请求地址
  //         params: {
  //           itemId: '1419276800524423168'
  //         },//请求参数
  //         errorMessageMode: 'none' //错误提示方式，默认为none
  //     })
  //           // errorMessageMode='message' 错误提示为消息提示
  //           // errorMessageMode='modal' 显示modal错误弹窗，用于一些比较重要的错误
  //           // errorMessageMode='none'  一般是调用时明确表示不希望自动弹出错误提示
  //       `,
  //   },
  //   {
  //     title: t('修改组件样式'),
  //     code: `formActionType.changeStyle(schema, { border:'2px solid #5e95ff' },'bindField')

  //     // schema:必须要写
  //     // 中间对象为需要修改的样式
  //     // bindField:需要修改组件的绑定字段（字符串），如修改本组件 则不填`,
  //   },
  //   {
  //     title: t('弹出对话框'),
  //     code: `formActionType.showModal({
  //         title: '我是标题', // 对话框标题
  //         content: '我是内容', // 对话框内容
  //         onOk() {
  //           console.log('onOk') // 点击确定按钮的处理逻辑
  //         },
  //         onCancel() {
  //           console.log('onCancel') // 点击取消按钮的处理逻辑
  //         },
  //     });`,
  //   },
  //   {
  //     title: t('if判断'),
  //     code: `const value = 3
  //     if(value === 3){ /* 括号内为判断条件 */
  //       console.log('value为3')
  //       /* 处理逻辑 */
  //     }`,
  //   },
  //   {
  //     title: t('循环'),
  //     code: `for(let i=0; i<3; i++){ /* 括号内为循环条件 */
  //       console.log('i的值为', i)
  //       /* 处理逻辑 */
  //     }`,
  //   },
  //   {
  //     title: t('正则校验'),
  //     code: `formActionType.regTest({
  //         regExpression: /^[0-9]/,// 正则表达式
  //         testValue: 123,// 需要进行校验的值
  //         successMessage: '校验成功',// 校验成功的提示信息
  //         errorMessage: '校验失败'// 校验失败的提示信息
  //     })`,
  //   },
  //   {
  //     title: t('刷新API'),
  //     code: `formActionType.refreshAPI('bindField')

  //     // bindField:需要刷新API组件的绑定字段（字符串）`,
  //   },
  // ]);

  onMounted(async () => {
    example.value = await getScriptDemoList();
    handleScriptClick(activeIndex.value);
  });

  const getTableComponents = (list, tableName, key?) => {
    list.forEach((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.layout!) {
          getTableComponents(child.list, tableName);
        }
      } else if (item.type === 'table-layout') {
        for (const child of item.layout!) {
          for (const list of child.list) {
            getTableComponents(list.children, tableName, key);
          }
        }
      } else if (item.type === 'one-for-one' || item.type === 'form' || item.type === 'sun-form') {
        widgetFormList.value.push({
          label: `${item.label}-${item.key}`,
          key: key,
          children: [
            { label: item.label, bindField: item.key, bindTable: item.bindTable, type: 'form' },
          ],
        });
        getTableComponents(item.children, `${item.label}-${item.key}`, item.key);
      } else if (
        !noHaveTableAndField.includes(item.type) ||
        item.type === 'button' ||
        item.type === 'modal'
      ) {
        const index = widgetFormList.value.findIndex((x) => x.label === tableName);
        const isRange = ['time-range', 'date-range'].includes(item.type);
        let rangeItem: any[] = [];
        if (isRange) {
          //时间范围、日期范围需改为两个字段
          rangeItem = [
            {
              ...item,
              label: t(`{name}开始时间`, { name: item.label }),
              bindField: item.bindStartTime,
            },
            {
              ...item,
              label: t(`{name}结束时间`, { name: item.label }),
              bindField: item.bindEndTime,
            },
          ];
        }
        if (index !== -1) {
          if (isRange) {
            widgetFormList.value[index].children.push(...rangeItem);
          } else {
            widgetFormList.value[index].children.push(item);
          }
        } else {
          const tableChildren = isRange ? [...rangeItem] : [item];
          if (tableName === t('主表组件列表')) {
            widgetFormList.value.unshift({
              label: tableName,
              key: '1',
              children: tableChildren,
            });
          } else {
            widgetFormList.value.push({
              label: tableName,
              key: key,
              children: tableChildren,
            });
          }
        }
      }
    });
  };
  const [registerModal, { closeModal, setModalProps }] = useModalInner(async (data) => {
    if (data.formList.list.length) {
      widgetFormList.value = [];
      getTableComponents(cloneDeep(data.formList.list), t('主表组件列表'));
    }
    if (data.formList.hiddenComponent?.length) {
      widgetFormList.value.push({
        key: 'hiddenComponent',
        label: '隐藏组件',
        children: data.formList.hiddenComponent.map((x) => {
          return {
            label: x.label,
            bindField: x.bindField,
          };
        }),
      });
    }

    eventType.value = data.type;
    //如果已经设置过当前事件代码  则显示已经设置的值 反之  显示默认值
    definedScript.value = data.content;
    configIndex.value = data.index;
    setModalProps({
      fixedHeight: true,
      destroyOnClose: true,
    });
  });

  const handleScriptClick = async (index) => {
    activeIndex.value = index;
    const info = example.value[index];
    if (!!info.script) return;
    if (info.id) {
      const data = await getScriptDemoInfo(info.id);
      info.script = data.scriptContent;
    }
  };

  const dragEnd = ({ item }) => {
    const component = item._underlying_vm_;
    const label = component.label;
    const bindField = component.bindField;
    const bindTable = component.bindTable;
    const transTable = isCustomForm ? bindTable + 'List' : camelCaseString(bindTable) + 'List';
    const transField = isCustomForm ? bindField : camelCaseString(bindField);
    if (component.isSubFormChild || component.isSingleFormChild) {
      definedScript.value = definedScript.value.replace(
        `${label}(${bindField})`,
        `${transTable}[0].${transField}`,
      );
    } else {
      if (['button', 'modal'].includes(component.type)) {
        definedScript.value = definedScript.value.replace(
          `${label}(${component.key})`,
          component.key,
        );
      } else {
        definedScript.value = definedScript.value.replace(
          `${label}(${bindField})`,
          component.type == 'form' ? transField + ',' + transTable : transField,
        );
      }
    }
  };
  const handleSubmit = () => {
    emit('success', eventType.value, definedScript.value, configIndex.value);
    closeModal();
  };

  const visibleChange = (visible: boolean) => {
    if (!visible) componentVisible.value = false;
  };
</script>

<style lang="less" scoped>
  .config-box {
    display: flex;
    height: 100%;

    > div:nth-child(1) {
      width: 30%;
      border-right: 1px solid #ddd;
    }

    > div:nth-child(2) {
      width: 35%;
      border-right: 1px solid #ddd;
    }

    > div:nth-child(3) {
      width: 35%;
    }

    .box-top {
      display: flex;
      justify-content: space-between;
      height: 30px;
      border-bottom: 1px solid #f0f0f0;
      padding: 25px 20px;
    }

    .script-name {
      cursor: pointer;
      padding: 10px 0 10px 15px;

      &:hover {
        background: #f7fbff;
      }
    }

    .active-name {
      background: #f7fbff;
      border-right: 4px solid #1c8dff;
    }
  }

  :deep(.ant-drawer-title) {
    font-size: 16px;
    height: 20px;
    line-height: 18px;
    padding-left: 6px;
    border-left: 6px solid #5e95ff;
  }

  :deep(.ant-tag) {
    padding: 8px;
    font-size: 13px;
    margin-bottom: 7px;
    cursor: move;
  }

  :deep(.ant-tabs-content) {
    height: 100%;
    overflow: auto;
  }

  :deep(.ant-tabs-nav) {
    width: 100%;
    height: 51px;
    margin-bottom: 0;
  }

  :deep(.ant-collapse) {
    background-color: #f7fbff !important;
  }
</style>
