<template>
  <div class="content">
    <div class="left">
      <h-form layout="vertical">
        <h-form-item
          label="编码方案"
          style="color: #333"
          :rules="[{ required: true, message: '请选择编码方案' }]"
        >
          <div class="form-item-code">
            <h-select :options="selectData" v-model:value="selectValue" @select="codeSelectClick" />
            <h-button class="form-item-code-btn" type="primary" @click="applyClick">
              申请编码
            </h-button>
            <h-button @click="showRightClick" class="form-item-code-btn-icon">
              <template #icon>
                <h-icon name="icp-encode-showRight" class="showRightIcon"></h-icon>
              </template>
            </h-button>
          </div>
        </h-form-item>

        <h-form-item
          label="编码预览"
          style="color: #333"
          :rules="[{ required: true, message: '' }]"
        >
          <div class="code-preview">
            <template v-for="(item, index) in codeValues" :key="item.key">
              <h-tool-tip :title="item.codeSegmentName">
                <span>
                  {{
                    index === codeValues.length - 1
                      ? item.codeValue
                      : item.codeValue + item.codeSeparator
                  }}
                </span>
              </h-tool-tip>
            </template>
          </div>
        </h-form-item>
      </h-form>
      <div class="encoder-tree-title">编码结构</div>
      <div class="encoder-tree">
        <h-input-search
          v-model:value="searchValue"
          style="margin-bottom: 8px"
          placeholder="请输入关键字搜索"
          @search="searchClick"
          @change="searchChangeClick"
        >
          <template #addonAfter>
            <h-button
              :disabled="nextAble === -1"
              type="primary"
              @click="searchPreEvent"
              style="border: none; outline: none; margin: 0 5px"
              class="search-button"
            >
              <template #icon>
                <caret-left-outlined />
              </template>
            </h-button>
            <h-button
              :disabled="nextAble === -1"
              type="primary"
              @click="searchNextEvent"
              style="border: none; outline: none"
              class="search-button"
            >
              <template #icon>
                <caret-right-outlined />
              </template>
            </h-button>
          </template>
        </h-input-search>
        <h-tree
          :key="keyNum"
          id="Encoder-queryTree"
          ref="treeRef"
          :show-icon="true"
          :tree-data="treeData"
          :show-line="false"
          :show-header="true"
          :show-tool-bar="true"
          :show-search="true"
          :is-scroll-x="true"
          block-node
          :expanded-keys="expandedKeys"
          :load-data="loadData"
          v-model:selectedKeys="selectedKeys"
          @select="selectOrg"
          @expand="expandClick"
        >
          <template #title="{ codeValue, key, describes }">
            <span
              v-if="
                searchValue &&
                searchValue.length > 0 &&
                (codeValue.indexOf(searchValue) > -1 ||
                  (describes && describes.indexOf(searchValue) > -1)) &&
                searchKey === key
              "
            >
              <span style="color: #f50">
                <span v-if="describes && describes.length > 0">
                  {{ codeValue }}-[{{ describes }}]
                </span>
                <span v-else>{{ codeValue }}</span>
              </span>
            </span>
            <span v-else>
              <span v-if="describes && describes.length > 0">
                {{ codeValue }}-[{{ describes }}]
              </span>
              <span v-else>{{ codeValue }}</span>
            </span>
          </template>
        </h-tree>
      </div>
    </div>
    <div class="right" v-if="showRight">
      <h-table
        id="CodeProgramme-queryTable"
        v-bind="appnoTableProps"
        rowKey="EID"
        :row-height="35"
        :show-header="false"
        :pagination="false"
        :show-size="false"
        :showExport="false"
        :animateRows="false"
        show-setting
        :custom-row="customRow"
        stripe
        :scroll="{
          // extra: 50,
          y: 520,
        }"
        ref="appnoGridRef"
      >
        <template #title>
          <div class="table-title">
            <div>编码列表</div>
            <h-icon name="icp-encode-showright"></h-icon>
            <div class="table-title-status">
              <h-tabs v-model:activeKey="activeKey">
                <h-tab-pane key="P_SYS_NUMBERING_APPLIED_LISTVIEW">
                  <template #tab>
                    <h-badge color="#666"></h-badge>
                    <span class="text">已申请</span>
                  </template>
                </h-tab-pane>
                <h-tab-pane key="P_SYS_NUMBERING_OCCUPIED_LISTVIEW">
                  <template #tab>
                    <h-badge color="#FCBA16 "></h-badge>
                    <span class="text">已占用</span>
                  </template>
                </h-tab-pane>
              </h-tabs>
            </div>
          </div>
        </template>
        <template #bodyCell="{ column, record, index }">
          <template v-if="column.dataIndex === 'ECODE'">
            <div :style="record.STATEID === '已占用' ? 'color: #FCBA16' : ''">
              <span class="table-body-index">{{ index + 1 }}</span>
              <span>{{ record.ECODE || '' }}</span>
            </div>
          </template>
        </template>
      </h-table>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, onMounted, reactive, ref, watch } from 'vue';
import { useTable } from '@crami/bui-platform';
import { getInfo, ICP_CONFIG, bus } from '@remote/icpx-platform/utils';

import {
  InputSearch as HInputSearch,
  Tree as HTree,
  Table as HTable,
  Form as HForm,
  FormItem as HFormItem,
  Select as HSelect,
  Button as HButton,
  ToolTip as HToolTip,
  message,
  HModal,
  Tabs as HTabs,
  TabPane as HTabPane,
  Badge as HBadge,
  Icon as HIcon,
} from '@crami/ui';
import { getByProjectAndType } from '@/api/platform/orgStructure/adminGroup';
import {
  UnorderedListOutlined,
  CaretLeftOutlined,
  CaretRightOutlined,
} from '@ant-design/icons-vue';
import { useHttp } from '@crami/http';
import type { TreeProps } from 'ant-design-vue';

/**控件对外数据*/
const props = {
  options: {
    type: Object,
  },
  componentProps: {
    type: Object,
  },
};

export default defineComponent({
  name: 'Encoder',
  props: props,
  components: {
    HTree,
    HTable,
    HToolTip,
    HSelect,
    HForm,
    HFormItem,
    HButton,
    HInputSearch,
    HTabs,
    HTabPane,
    HBadge,
    HIcon,
    UnorderedListOutlined,
    CaretLeftOutlined,
    CaretRightOutlined,
  },
  setup: (props: any, { emit }) => {
    const activeKey = ref('P_SYS_NUMBERING_APPLIED_LISTVIEW');
    const objectId = props.componentProps?.params.objectId || '';
    const keyNum = ref(0);
    const loadedKeys = ref([]);
    let treeViewName = ref('');
    let paramsData: any = ref({ treeView: '', link: {}, page: {}, menu: {} });

    const commonParams = computed(() => {
      return getInfo(ICP_CONFIG);
    });
    const showRight = ref(false);
    const selectData = reactive([]);
    const selectValue = ref();
    const expandedKeys = ref([]);
    const codeValues = ref([]);
    let selectCodeKey = undefined;
    let selectCodeData = [];
    const treeData = ref([]);
    const treeRef = ref();
    const searchValue = ref();
    const nextAble = ref(-1);
    let searchPositions = [];
    const selectedKeys = ref();
    const searchKey = ref();

    watch(activeKey, () => {
      refreshTable();
    });

    //控制显示内容
    const displayFormat = function (data: any) {
      return data.title;
    };

    const [appnoGridRef, appnoTableProps, appnoTableMethods] = useTable({
      configApi: {
        url: '/api/system/view/getData',
        method: 'post',
        params: {
          type: 'gridTitle',
          data: {
            lang: commonParams.value?.lang,
            connect: commonParams.value?.connect,
            companyId: commonParams.value?.companyId,
            viewName: 'P_SYS_NUMBERING_LISTVIEW',
          },
        },
      },
      dataSourceApi: {
        url: '/api/system/model/getGetOnePageGridDataList',
        method: 'post',
        studioParams: {
          viewName: activeKey.value,
          lang: commonParams.value.lang,
          connect: commonParams.value.connect,
          companyId: commonParams.value.companyId,
          objectType: '',
        },
      },
      beforeRequest: (type, params: any) => {
        if (type == 'column') {
          if (params && params.data && typeof params.data == 'object') {
            params.data = JSON.stringify(params.data);
          }
        }
        return {
          ...params,
          filter: [
            {
              andOrFlag: 'AND',
              field: 'CODE_VALUE_ID',
              operation: '=',
              value: selectCodeKey,
            },
          ],
        };
      },
    });

    //选择组织
    const selectOrg = async (value: any, e: any) => {
      if (e.node.pos !== '0-0') {
        const nodes = [];
        treeRef.value.getAllParentNode(nodes, e.node, treeData.value);
        if (e.node.dataRef.children && e.node.dataRef.children.length > 0) {
          selectCodeData = [];
          selectCodeKey = undefined;
        } else {
          const data = await useHttp({
            url: '/api/codemanagement/codeGenerator/getChildCodeValueTree',
            method: 'post',
            params: {
              pid: e.node.key,
              connect: commonParams.value?.connect,
              lang: commonParams.value?.lang,
              companyId: commonParams.value?.companyId,
            },
          });
          if (data.code === 200 && data.data.length === 0) {
            selectCodeData = nodes;
            selectCodeKey = e.node.key;
          }
        }
        const nodeTitles = nodes.filter((_, index) => {
          if (index === 0) {
            return false;
          }
          return true;
        });
        codeValues.value = nodeTitles;
      } else {
        codeValues.value = [];
        selectCodeData = [];
        selectCodeKey = undefined;
      }
      if (showRight.value) {
        refreshTable();
      }
    };
    const showRightClick = () => {
      showRight.value = !showRight.value;
      if (showRight.value) {
        refreshTable();
      }
    };

    const codeSelectClick = (event: any) => {
      keyNum.value++;
      expandedKeys.value = [];
      searchValue.value = undefined;
      nextAble.value = -1;
      searchPositions = [];
      // loadedKeys.value = [];
      codeValues.value = [];
      selectCodeData = [];
      selectCodeKey = undefined;
      refreshTable();
      getTreeData(event);
    };

    const refreshTable = () => {
      appnoTableMethods.query({ viewName: activeKey.value });
    };

    onMounted(() => {
      getByProjectAndTypeFun();
      getCodeProgramData();
      getHistoryEvent();
    });
    //获取treeViewName
    const getByProjectAndTypeFun = () => {
      getByProjectAndType({
        type: 'tree',
        productLine: commonParams.value.project,
        name: 'P_SYS_CODE_SCHEME_VALUE_TREE',
      }).then(res => {
        if (res.code == 200) {
          treeViewName.value = res.data?.treeView;
          paramsData.value = res.data || {};
          //   methods.refresh().then(() => {
          //     methods.defaultHandle();
          //   });
        }
      });
    };

    const getCodeProgramData = async () => {
      const data = await useHttp({
        url: '/api/codemanagement/codeGenerator/queryCodeSchemeListByObjectId',
        method: 'post',
        params: {
          objectId: objectId,
          connect: commonParams.value?.connect,
          lang: commonParams.value?.lang,
          companyId: commonParams.value?.companyId,
        },
      });
      if (data.code === 200) {
        selectData.length = 0;
        selectData.push(
          ...data.data.map(item => {
            return { label: item.name, value: item.id };
          }),
        );
      } else {
        message.error(data.msg);
      }
    };

    const getTreeData = async (codeSchemeId: string) => {
      const data = await useHttp({
        url: '/api/codemanagement/codeGenerator/getCodeValueTree',
        method: 'post',
        params: {
          codeSchemeId: codeSchemeId,
          connect: commonParams.value?.connect,
          lang: commonParams.value.lang,
          companyId: commonParams.value?.companyId,
        },
      });
      if (data.code === 200) {
        treeData.value.length = 0;
        treeData.value = [].concat(data.data);
      } else {
        message.error(data.msg);
      }
    };

    const loadData = (node: any) => {
      if (node.pos === '0-0') {
        return new Promise(resolve => {
          resolve(true);
          return;
        });
      }
      if (node.dataRef.children) {
        return new Promise(resolve => {
          resolve(true);
          return;
        });
      }

      return useHttp({
        url: '/api/codemanagement/codeGenerator/getChildCodeValueTree',
        method: 'post',
        params: {
          pid: node.key,
          connect: commonParams.value?.connect,
          lang: commonParams.value?.lang,
          companyId: commonParams.value?.companyId,
        },
      }).then(res => {
        if (res.code === 200) {
          node.dataRef.children = [...res.data];
          treeData.value = [...treeData.value];
        }
      });
    };

    const applyClick = async () => {
      if (selectValue.value === undefined) {
        message.warn('请选择编码方案');
        return;
      }
      if (selectCodeData.length == 0) {
        message.warn('所选码值非编码方案的最末端节点，请确认选中的码值是最末端节点！');
        return;
      }
      const generators = [];
      for (let i = 1; i < selectCodeData.length; i++) {
        const item = selectCodeData[i];
        generators.push(item.key);
      }
      const data = await useHttp({
        url: '/api/codemanagement/codeGenerator/generatorCode',
        method: 'post',
        params: {
          codeValueIds: generators.join(','),
          codeSchemeId: selectValue.value,
          connect: commonParams.value?.connect,
          lang: commonParams.value?.lang,
          companyId: commonParams.value?.companyId,
          userId: commonParams.value.user_id,
          objectId,
        },
      });
      if (data.code === 200) {
        message.success(data.msg);
        if (showRight.value) {
          refreshTable();
        }
      } else {
        message.error(data.msg);
      }
    };

    const expandClick = (keys: any) => {
      expandedKeys.value = keys;
    };

    const searchClick = async (event: any) => {
      if (event.replace(/ /g, '').length === 0) {
        message.warn('请输入搜索内容');
        return;
      }
      if (selectValue.value === undefined) {
        return;
      }
      const data = await useHttp({
        url: '/api/codemanagement/codeGenerator/queryCodeValuePath',
        method: 'post',
        params: {
          codeValue: event,
          codeSchemeId: selectValue.value,
          connect: commonParams.value?.connect,
          lang: commonParams.value?.lang,
          companyId: commonParams.value?.companyId,
        },
      });
      if (data.code === 200) {
        // message.success(data.msg);
        const result = data.data;
        if (result.length > 0) {
          nextAble.value = 0;
          searchPositions = result.map(item => {
            return item.split(',');
          });
          getExplainKey();
        } else {
          nextAble.value = -1;
        }
      } else {
        message.error(data.msg);
      }
    };

    const getExplainKey = async () => {
      const tempKeys = new Set();
      if (treeData.value.length === 0) {
        return;
      }
      if (searchPositions.length === 0) {
        nextAble.value = -1;
        return;
      }
      if (nextAble.value >= searchPositions.length) {
        nextAble.value = 0;
      }
      const searchPos = searchPositions[nextAble.value];
      let currentChilds = treeData.value;
      let currentNode = undefined;
      for (let i = 0; i < searchPos.length; i++) {
        const index = searchPos[i];
        if (currentChilds && currentChilds.length > 0) {
          currentNode = currentChilds[index];
          tempKeys.add(currentNode.key);
          currentChilds = currentNode.children;
          searchKey.value = currentNode.key;
        } else {
          const data = await useHttp({
            url: '/api/codemanagement/codeGenerator/getChildCodeValueTree',
            method: 'post',
            params: {
              pid: currentNode.key,
              connect: commonParams.value?.connect,
              lang: commonParams.value?.lang,
              companyId: commonParams.value?.companyId,
            },
          });
          if (data.code === 200) {
            if (data.data.length > 0) {
              currentNode.children = [...data.data];
              treeData.value = [...treeData.value];
              currentChilds = currentNode.children;
              currentNode = currentChilds[index];
              tempKeys.add(currentNode.key);
              searchKey.value = currentNode.key;
            }
          }
        }
      }

      expandedKeys.value = [...tempKeys];
    };

    const searchChangeClick = () => {
      if (searchValue.value.length === 0) {
        nextAble.value = -1;
        searchPositions = [];
        searchKey.value = undefined;
      }
    };

    const searchNextEvent = () => {
      nextAble.value++;
      getExplainKey();
    };

    const searchPreEvent = () => {
      if (nextAble.value === -1) {
        return;
      }
      nextAble.value--;
      if (nextAble.value < 0) {
        nextAble.value = searchPositions.length > 0 ? searchPositions.length - 1 : 0;
      }
      getExplainKey();
    };

    const customRow = (record: any) => {
      return {
        ondblclick: () => {
          if (record.STATEID && record.STATEID !== '已占用') {
            updateStateEvent(record);
          }
        },
      };
    };
    const updateStateEvent = async (event: any) => {
      const data = await useHttp({
        url: '/api/codemanagement/codeGenerator/updateState',
        method: 'post',
        params: {
          objectId: event.EID,
          stateId: 'OCCUPIED',
          connect: commonParams.value?.connect,
          lang: commonParams.value?.lang,
          companyId: commonParams.value?.companyId,
          userId: commonParams.value.user_id,
        },
      });
      if (data.code === 200) {
        if (showRight.value) {
          refreshTable();
        }
        HModal.destroyAll();
        bus.emit('encoderEvent', event.EID);
      } else {
        message.error(data.msg);
      }
    };

    const getHistoryEvent = async () => {
      const data = await useHttp({
        url: '/api/codemanagement/codeGenerator/getHistoryCodeValueTree',
        method: 'post',
        params: {
          objectId,
          connect: commonParams.value?.connect,
          lang: commonParams.value?.lang,
          companyId: commonParams.value?.companyId,
          userId: commonParams.value.user_id,
        },
      });
      if (data.code === 200) {
        if (data.data.tree === undefined) {
          return;
        }
        treeData.value = [].concat(data.data.tree);
        selectValue.value = data.data.codeSchemeId;
        selectCodeKey = data.data.codeValueId;
        expandedKeys.value = getAllKeys(selectCodeKey);
        selectedKeys.value = [].concat(selectCodeKey);
        const curNode = getNodeByKey(selectCodeKey, treeData.value);
        const nodes = [];
        treeRef.value.getAllParentNode(nodes, curNode, treeData.value);
        const nodeTitles = nodes.filter((_, index) => {
          if (index === 0) {
            return false;
          }
          return true;
        });
        codeValues.value = nodeTitles;
        selectCodeData = nodes;
      } else {
        message.error(data.msg);
      }
    };

    const getAllKeys = (nodeKey: string) => {
      const keys = [];
      keys.push(nodeKey);
      const parentKey = getParentKey(nodeKey, treeData.value);
      if (parentKey === undefined) {
        return keys;
      } else {
        keys.push(...getAllKeys(parentKey));
        return keys;
      }
    };

    const getParentKey = (
      key: string | number,
      tree: TreeProps['treeData'],
    ): string | undefined => {
      let parentKey;
      for (let i = 0; i < tree.length; i++) {
        const node = tree[i];
        if (node.children) {
          if (node.children.some(item => item.key === key)) {
            parentKey = node.key;
          } else if (getParentKey(key, node.children)) {
            parentKey = getParentKey(key, node.children);
          }
        }
      }
      return parentKey;
    };

    const getNodeByKey = (key: string, tree: TreeProps['treeData']) => {
      let finishNode;
      for (let i = 0; i < tree.length; i++) {
        const node = tree[i];
        if (node.key === key) {
          finishNode = node;
        } else if (node.children) {
          finishNode = getNodeByKey(key, node.children);
        }
      }
      return finishNode;
    };
    return {
      activeKey,
      appnoGridRef,
      appnoTableProps,
      appnoTableMethods,
      expandedKeys,
      codeValues,
      searchValue,
      loadData,
      treeRef,
      treeData,
      selectData,
      selectValue,
      selectedKeys,
      displayFormat,
      showRight,
      selectOrg,
      showRightClick,
      applyClick,
      codeSelectClick,
      expandClick,
      searchClick,
      searchChangeClick,
      searchNextEvent,
      searchPreEvent,
      keyNum,
      loadedKeys,
      customRow,
      nextAble,
      searchKey,
    };
  },
});
</script>

<style lang="less" scoped>
.content {
  height: 560px;
  display: flex;
  flex-direction: row;
  .left {
    width: 480px;
    flex: 1 auto;
    .form-item-code {
      display: flex;
      .form-item-code-btn {
        margin: 0 10px;
      }

      .form-item-code-btn-icon {
        border: none;
        outline: none;
        padding: 0;

        .showRightIcon {
          width: 32px;
          height: 32px;
          :deep(.h-svg-icon) {
            width: 32px !important;
            height: 32px !important;
            outline: none;
            &:focus {
              border-radius: 4px;
              border-color: #4e5a70;
            }
            &:hover {
              border-radius: 4px;
              border-color: #4e5a70;
            }
            // :deep(use):focus {
            //   border-radius: 4px;
            //   border-color: red;
            // }
            // :deep(use):hover {
            //   border-radius: 4px;
            //   border-color: #4e5a70;
            // }
          }
        }
      }
    }
    .encoder-tree-title {
      font-weight: 400;
      color: #333333;
      line-height: 22px;
      font-size: 14px;
      font-family: PingFangSC-Regular, PingFang SC;
      height: 22px;
      margin-bottom: 5px;
      &::before {
        display: inline-block;
        margin-right: 4px;
        color: #ff4d4f;
        font-size: 14px;
        font-family: SimSun, sans-serif;
        line-height: 1;
        content: '*';
      }
    }
    .encoder-tree {
      border: 1px solid #d9d9d9;
      padding: 10px 24px;
      height: 357px;
      overflow-y: scroll;
      :deep(.crami-hbtree-header) {
        width: 100%;
      }
      :deep(.ant-tree > .ant-tree-treenode) {
        width: 80%;
      }
      .search-button[disabled] {
        background-color: #f5f5f5;
        color: #999;
      }
      :deep(.ant-input-group-wrapper) {
        .ant-input-group-addon {
          background-color: #fff;
        }
      }
    }
    .code-preview {
      border-radius: 4px;
      padding: 0 10px;
      background-color: #f5f6f7;
      line-height: 40px;
      height: 40px;
      overflow-x: scroll;
      overflow-y: hidden;
      white-space: nowrap;
      border-radius: 4px;
      border: 1px solid #d9d9d9;
    }
    .code-preview::-webkit-scrollbar {
      height: 4px !important;
    }
    :deep(.ant-tree-switcher) {
      line-height: 32px;
      .ant-tree-switcher-icon {
        font-size: 14px;
        vertical-align: middle;
        color: #999;
      }
    }
  }
  .right {
    height: 576px;
    margin-left: 20px;
    width: 500px;
    padding-bottom: 0;
    flex: 1 auto;
    overflow: scroll;
    :deep(.surely-table-wrapper) {
      border: #e1e1e1 solid 1px;
      height: 563px;
    }
    :deep(.surely-table-title) {
      border-bottom: #e1e1e1 solid 1px;
      padding: 0 20px 0 20px;
      height: 40px;
      line-height: 40px;
    }
    :deep(.surely-table-empty-container) {
      border-bottom: 0px solid white;
    }
    .table-body-index {
      margin-right: 30px;
    }
    .table-title {
      display: flex;
      height: 40px;
      line-height: 40px;
      align-items: center;

      // height: 50px;
      & > div:nth-child(1) {
        flex: 1 auto;
      }
      .table-title-status {
        display: flex;
        :deep(.ant-tabs-top) {
          .ant-tabs-nav {
            margin: 0 0 6px 0 !important;
            .ant-tabs-nav-list {
              .ant-tabs-tab {
                .ant-badge-status-dot {
                  width: 8px;
                  height: 8px;
                }
                .text {
                  color: #999;
                  font-weight: 400;
                  font-size: 14px;
                }
              }
              .ant-tabs-tab-active {
                .text {
                  color: #333;
                  font-weight: 600;
                  font-size: 14px;
                }
              }
              // .ant-tabs-ink-bar {
              //   width: 50px !important;
              //   left: 12px !important;
              // }
            }
          }
        }

        .tab :nth-child(1) {
          &::before {
            content: '';
            width: 8px;
            height: 8px;
            background-color: #666666;
            border-radius: 4px;
            display: inline-block;
            margin-right: 5px;
          }
        }
        .tab:nth-child(2) {
          margin-left: 15px;
          &::before {
            content: '';
            width: 8px;
            height: 8px;
            background-color: #fcba16;
            border-radius: 4px;
            display: inline-block;
            margin-right: 5px;
          }
        }
      }
    }
  }
}
</style>
