<template>
  <div class="box d-flex pa-3">
    <div class="box-left mr-3">
      <v-card class="box-left-card d-flex flex-column">
        <div>
          <v-tabs v-model="tab">
            <v-tab>模型</v-tab>
            <v-tab>指标</v-tab>
          </v-tabs>
        </div>
        <div style="height: 0; flex: 1">
          <v-tabs-items v-model="tab">
            <v-tab-item>
              <data-list @use="handleChange"></data-list>
            </v-tab-item>
            <v-tab-item>
              <indicator-list @use="handleChangeIndicator"></indicator-list>
            </v-tab-item>
          </v-tabs-items>
        </div>
      </v-card>
    </div>
    <div class="box-right mr-3">
      <m-card class="box-right-card d-flex flex-column" :px5="false" title="指标设置" bodyStyle="height: 0;flex: 1;">
        <div class="box-right-card-content d-flex flex-column">
          <div class="pa-3 pb-0 flex-grow-1 flex-shrink-1">
            <div class="contenteditable-box">
              <div
                contenteditable="true"
                ref="contenteditable"
                class="contenteditable"
                @input="updateContent"
              >
              </div>
              <v-btn class="ml-3 contenteditable-box-btn1" color="primary" @click="handleRuleValidate" :loading="ruleValidateLoading">规则效验</v-btn>
              <v-btn class="contenteditable-box-btn" color="primary" @click="handleCodeGenerate" :loading="codeLoading">代码生成</v-btn>
              <div class="labelTxt" :class="{'active': indicator}">指标计算规则</div>
            </div>
          </div>
          <div class="pa-3">
            <v-textarea
              outlined
              no-resize
              hide-details
              rows="12"
              :disabled="codeLoading"
              v-model="pythonCode"
              label="指标计算代码段"
            >
            </v-textarea>
          </div>
        </div>
      </m-card>
    </div>
    <div class="box-base">
      <v-card class="box-base-content d-flex flex-column" elevation="5">
        <div class="box-base-content-control d-flex flex-column">
          <v-banner single-line>
            <div class="py-2 title">基础信息</div>
            <template #actions>
              <v-btn
                v-for="btn in sendBtn"
                :key="btn.text"
                text
                class="ml-3"
                :color="btn.color"
                :disabled="btn.loading"
                @click="btn.handle(btn)"
              >
                <v-progress-circular
                  v-if="btn.loading"
                  indeterminate
                  :size="18"
                  width="2"
                  color="primary"
                  class="mr-1"
                ></v-progress-circular>
                <v-icon left v-else>{{ btn.icon }}</v-icon>
                {{ btn.text }}
              </v-btn>
            </template>
          </v-banner>
          <div class="pt-3 box-base-content-control-edit">
            <edit-base ref="base" :item-data="itemData"></edit-base>
          </div>
        </div>
      </v-card>
    </div>
    <v-overlay :value="overlay">
      <div class="d-flex flex-column align-center justify-center" style="width: 300px;">
        <div class="mb-3">{{tip}}</div>
        <v-progress-linear
          color="primary"
          indeterminate
          rounded
          height="6"
        ></v-progress-linear>

      </div>
    </v-overlay>

    <!-- 指标规则效验结果 -->
    <v-navigation-drawer
      v-model="ruleValidateDrawer"
      absolute
      temporary
      right
      width="50%"
      style="z-index: var(--zIndex-drawers);"
    >
      <div class="pa-3" style="color: black;">规则效验结果</div>
      <v-divider></v-divider>
      <m-table
        class="px-3 mt-2"
        :headers="[
          { text: '变量名', value: 'variable' },
          { text: '匹配名称', value: 'name_zh' }
        ]"
        :loading="false"
        :items="ruleValidateItems"
        :disable-sort="true"
        :show-select="false"
        :is-tools="false"
      >
        <template #name_zh="{ item }">
          <v-tooltip v-if="item.findit === 1" left>
            <template v-slot:activator="{ on, attrs }">
              <span v-bind="attrs" v-on="on" class="defaultLink">{{ item.name_zh }}</span>
            </template>
            <span>{{ item.name_zh }}</span>
          </v-tooltip>
          <span v-else>{{ item.name_zh }}</span>
        </template>
      </m-table>
    </v-navigation-drawer>
  </div>
</template>

<script>
import MCard from '@/components/MCard'
import MTable from '@/components/List/table.vue'
import DataList from './dataList'
import IndicatorList from './indicatorList'
import EditBase from './editBase'
import { api } from '@/api/dataGovernance'
export default {
  name: 'indicator-edit',
  components: {
    MCard,
    EditBase,
    DataList,
    IndicatorList,
    MTable
  },
  props: {
    itemData: {
      type: Object,
      default: () => ({})
    }
  },
  data () {
    return {
      tab: 0,
      overlay: false,
      tip: '正在生成代码片段',
      panels: [],
      show: false,
      codeLoading: false,
      ruleValidateLoading: false,
      ruleValidateDrawer: false,
      indicator: '',
      readonly: true,
      sendBtn: [
        {
          icon: 'mdi-send-variant',
          key: 'submit',
          color: 'primary',
          loading: false,
          text: '确认提交',
          handle: this.handleSubmit
        }
      ],
      pythonCode: '',
      isEditRules: false,
      selected: [],
      ruleValidateItems: []
    }
  },
  mounted () {
    this.$nextTick(() => {
      if (!Object.keys(this.itemData).length) {
        return
      }
      this.indicator = this.itemData.metric_rules
      this.$refs.contenteditable.innerHTML = this.indicator
      this.pythonCode = this.itemData.code
    })
  },
  methods: {
    updateContent () {
      this.indicator = this.$refs.contenteditable.innerHTML
      // 更新之后自动代码段清空
      // if (this.pythonCode) {
      //   this.pythonCode = ''
      // }
      this.isEditRules = true
    },
    insertCode (text, attribute) {
      this.$refs.contenteditable.focus()
      const phrase = text
      const selection = window.getSelection()
      const range = selection.getRangeAt(0)

      const span = document.createElement('span')
      span.textContent = phrase
      span.classList.add('contenteditable-span')
      // span.setAttribute('contenteditable', 'false') // 不允许单独编辑
      attribute.forEach(e => {
        span.setAttribute(e.label, e.value)
      })

      range.deleteContents() // 删除选中的内容
      range.insertNode(span) // 插入新创建的词块

      // 将光标移动到词块后面
      range.setStartAfter(span)
      range.collapse(true)
      selection.removeAllRanges()
      selection.addRange(range)
    },
    handleChange (node, belong) {
      const attribute = [
        { label: 'data-id', value: node.id },
        { label: 'data-belong', value: belong.id },
        { label: 'contenteditable', value: 'false' }
      ]
      this.insertCode(`${node.name_zh}`, attribute)
      this.updateContent()
    },
    handleChangeIndicator (item) {
      const attribute = [
        { label: 'data-id', value: item.id },
        { label: 'contenteditable', value: 'false' }
      ]
      this.insertCode(`${item.name_zh}`, attribute)
      this.updateContent()
    },
    htmlStringToNode (htmlString) {
      const parser = new DOMParser()
      const doc = parser.parseFromString(htmlString, 'text/html')
      return doc.body
    },
    // 指标计算规则效验
    async handleRuleValidate () {
      if (!this.indicator) {
        this.$snackbar.error('请输入指标计算规则')
        return
      }
      this.ruleValidateLoading = true
      const oHtml = this.htmlStringToNode(this.indicator)
      try {
        const { data } = await api.dataIndicatorRuleValidate({ formula: oHtml.innerText })
        this.ruleValidateItems = data || []
        this.ruleValidateDrawer = true
      } catch (error) {
        this.$snackbar.error(error)
      } finally {
        this.ruleValidateLoading = false
      }
    },
    // 生成代码
    async handleCodeGenerate () {
      if (!this.indicator) {
        this.$snackbar.error('没有找到指标规则')
        return
      }
      this.codeLoading = true
      const oHtml = this.htmlStringToNode(this.indicator)
      const item = []
      const indicator = []
      oHtml.querySelectorAll('.contenteditable-span').forEach(e => {
        if (!e.dataset.belong) {
          indicator.push({
            id: +e.dataset.id,
            name: e.innerText
          })
          return
        }
        item.push({
          id: +e.dataset.id,
          name: e.innerText,
          belong: +e.dataset.belong
        })
      })
      // console.log(item)
      const relation = item.map(({ belong, ...obj }) => obj)
      try {
        const { data } = await api.dataIndicatorCodeGenerate({
          content: oHtml.innerText,
          relation: [
            ...relation,
            ...indicator
          ]
        })
        this.selected = item.reduce((r, v) => {
          const _item = r.find(e => e.id === v.belong)
          if (!_item) {
            r.push({
              id: v.belong,
              metaData: [v.id],
              type: 'model'
            })
            return r
          }
          _item.metaData.push(v.id)
          return r
        }, [...indicator.map(e => {
          return {
            id: e.id,
            metaData: null,
            type: 'metric'
          }
        })])
        this.pythonCode = data
        this.isEditRules = false
      } catch (error) {
        this.isEditRules = true
        this.$snackbar.error(error)
      } finally {
        this.codeLoading = false
      }
    },
    async handleSubmit (btn) {
      if (!this.indicator) {
        this.$snackbar.error('未指定指标规则')
        return
      }
      const obj = this.$refs.base.getValue()
      if (!obj) {
        return
      }
      btn.loading = true
      this.overlay = true
      try {
        if (!this.pythonCode || this.isEditRules) {
          this.tip = '正在生成代码片段'
          await this.handleCodeGenerate()
        }
        this.tip = '正在提交保存'
        const query = {
          ...obj,
          id_list: this.selected, // 传递元数据
          metric_rules: this.indicator,
          code: this.pythonCode
        }
        if (this.itemData.id) {
          Object.assign(query, {
            id: this.itemData.id,
            name_en: this.itemData.name_en
          })
          // console.log(query, this.itemData)
          // return
        }
        const subApi = this.itemData.id ? api.dataIndicatorUpdate : api.dataIndicatorAdd
        await subApi(query)
        this.$snackbar.success('保存成功')
        this.$emit('close')
      } catch (error) {
        this.$snackbar.error(error)
      } finally {
        btn.loading = false
        this.overlay = false
      }
    }
  }
}
</script>

<style lang="scss" scoped>

.th-title {
    font-size: 14px !important;
    font-weight: 600;
    color: #1976D2 !important;
  }
.box {
  width: 100%;
  &-left {
    width: 400px;
    &-card {
      height: 100%;
    }
  }
  &-right {
    width: 0;
    flex: 1;
    &-card {
      height: 100%;
      &-content {
        height: 100%;
        overflow: auto;
      }
    }
  }
  &-base {
    position: relative;
    width: 400px;
    height: 100%;
    &-content {
      height: 100%;
      &-control {
        height: 100%;
        &-edit {
          flex: 1;
          overflow: auto;
        }
      }
    }
  }
}
.point {
  cursor: pointer;
}
.title {
  color: #1976D2;
  font-weight: 600;
}
.contenteditable-box {
  $color: #1976D2;
  position: relative;
  height: 100%;
  &-btn {
    position: absolute;
    right: 10px;
    bottom: 10px;
  }
  &-btn1 {
    position: absolute;
    right: 116px;
    bottom: 10px;
  }
  .contenteditable {
    border: 1px solid #999;
    padding: 12px;
    border-radius: 4px;
    caret-color: $color; /* 设置光标颜色为红色 */
    height: 100%;
    box-sizing: border-box; /* 盒模型 */
    overflow: auto;
    &:focus {
      border-color: transparent; /* 隐藏默认边框颜色 */
      outline: 2px solid $color; /* 聚焦时使用 outline */
      outline-offset: -2px; /* 调整 outline 位置以保持设计一致性 */
      &+.labelTxt {
        background: #FFF;
        padding: 0 2px;
        top: 0;
        transform: translateY(-45%);
        font-size: 12px;
        color: $color;
        font-weight: 500;
      }
    }
  }
  .labelTxt {
    position: absolute;
    top: 18px;
    left: 12px;
    font-size: 16px;
    color: rgba(0, 0, 0, 0.6);
    transition: 0.3s;
    pointer-events: none;
    &.active {
      background: #FFF;
      padding: 0 2px;
      top: 0;
      transform: translateY(-45%);
      font-size: 12px;
      color: $color;
      font-weight: 500;
    }
  }
}
::v-deep .v-tabs-items {
  height: 100%;
  .v-window__container {
    height: 100%;
  }
  .v-window-item {
    height: 100%;
  }
}
</style>
<style lang="scss">
.contenteditable-span {
  /* background: #333; */
  // color: white;
  padding: 2px 18px;
  font-size : 14px;
  color: var(--v-side-darken5);
  display : inline-block;
  position: relative;
  z-index: 1; /* 让文字在 z 轴上位于伪元素之上 */
  &::after {
    content: '';
    position: absolute;
    top: 0;
    left: 5px;
    width: calc(100% - 10px);
    height: 100%;
    // background: #333;
    border-bottom: 1px dotted var(--v-side-darken5);
    // border-radius : 4px;
    z-index:-1;
  }
}
</style>
