<template>
  <div class="chart-container">
    <div v-if="isShowYingBtn" class="div-header"><el-button type="primary" size="small" @click="goPage">进入应用专题</el-button></div>
    <div v-if="chartData.length > 0" class="exception-bar-chart">
      <div :id="chartDomId" ref="exceptionBarChart" class="exception-bar-chart" />
    </div>
    <div v-else class="exception-bar-chart">
      <div class="bar-header">
        <div class="bar-title">{{ title }}</div>
        <el-tooltip v-if="isShowTootip" effect="dark" :visible-arrow="false">
          <div slot="content">
            <i class="dot" />
            <span>异常事件：数据库异常 和 对外接口请求异常</span>
          </div>
          <div class="icon-box">
            <img class="icon-help" src="@/assets/icons/help.svg">
          </div>
        </el-tooltip>
      </div>
      <div class="chart-no-data">暂无异常</div>
    </div>
    <div v-if="isTableInDrawer">
      <div v-if="isShowAbnormalTable">
        <el-drawer
          title="异常剖析"
          :visible.sync="isShowDrawer"
          :direction="'rtl'"
          show-close
          size="60%"
          @close="drawerFireClose"
        >
          <el-table
            v-loading="fireLoading"
            :data="tableData"
            @row-click="handleRowClick"
          >
            <el-table-column label="异常类型" header-align="center" align="center" prop="error_type" :show-overflow-tooltip="true" />
            <el-table-column label="异常信息" header-align="center" align="center" prop="status_message" :show-overflow-tooltip="true" width="300">
              <template slot-scope="scope">
                <el-tooltip
                  placement="top"
                  popper-class="custom-tooltip"
                  :content="scope.row.status_message"
                >
                  <el-input readonly autosize type="texteara" :value="scope.row.status_message" style="width: 100%;" class="readonly-input" />
                </el-tooltip>
              </template>
            </el-table-column>
            <el-table-column label="异常数" header-align="center" align="center" prop="total" :show-overflow-tooltip="true" width="80" />
            <el-table-column label="服务名" header-align="center" align="center" prop="service_name_cn" width="200" :show-overflow-tooltip="true">
              <template slot-scope="scope">
                <el-tag size="mini">{{ scope.row.service_name_cn ? scope.row.service_name_cn: scope.row.service_name }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column
              label="操作"
              align="center"
              class-name="small-padding fixed-width"
              width="220"
            >
              <template slot-scope="scope">
                <el-button
                  size="mini"
                  type="text"
                  icon="el-icon-view"
                  @click="showReason(scope.row)"
                >异常诊断
                </el-button>
                <el-button
                  size="mini"
                  type="text"
                  icon="el-icon-connection"
                  @click="getServiceSpans(scope.row)"
                >调用链查询
                </el-button>
              </template>
            </el-table-column>
          </el-table>
          <pagination
            v-show="tableTotal>0"
            :total="tableTotal"
            :page.sync="query.pageIndex"
            :limit.sync="query.pageSize"
            @pagination="getList"
          />
        </el-drawer>
      </div>
      <div v-else>
        <DrawerTransTable
          v-if="isShowDrawerTable"
          :bis-type="bisType"
          :query-params-type="2"
          :drawer-title="'异常链路列表'"
          :is-show-trans="isShowDrawerTable"
          :start-time="columnStartTime"
          :end-time="columnEndTime"
          :service-name="serviceName"
          :route="route"
          @handleClose="handleCloseTable"
        />
      </div>
    </div>
    <div v-else class="abnormal-table">
      <el-table
        v-loading="fireLoading"
        :data="tableData"
        max-height="400"
        height="400"
        @row-click="handleRowClick"
      >
        <el-table-column label="异常类型" header-align="center" align="center" prop="error_type" :show-overflow-tooltip="true" />
        <el-table-column label="异常信息" header-align="center" align="center" prop="status_message" width="200">
          <template slot-scope="scope">
            <el-tooltip
              placement="top"
              popper-class="custom-tooltip"
              :content="scope.row.status_message"
            >
              <el-input readonly autosize type="texteara" :value="scope.row.status_message" style="width: 100%;" class="readonly-input" />
            </el-tooltip>
          </template>
        </el-table-column>
        <el-table-column label="异常数" header-align="center" align="center" prop="total" :show-overflow-tooltip="true" width="80" />
        <el-table-column label="服务名" header-align="center" align="center" prop="service_name_cn" width="200" :show-overflow-tooltip="true">
          <template slot-scope="scope">
            <el-tag size="mini">{{ scope.row.service_name_cn ? scope.row.service_name_cn: scope.row.service_name }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          align="center"
          class-name="small-padding fixed-width"
          width="220"
        >
          <template slot-scope="scope">
            <el-button
              size="mini"
              type="text"
              icon="el-icon-view"
              @click="showReason(scope.row)"
            >异常诊断
            </el-button>
            <el-button
              size="mini"
              type="text"
              icon="el-icon-connection"
              @click="getServiceSpans(scope.row)"
            >调用链查询
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="tableTotal>0"
        :total="tableTotal"
        :page.sync="query.pageIndex"
        :limit.sync="query.pageSize"
        @pagination="getList"
      />
    </div>
    <el-dialog
      class="dialog-self"
      append-to-body
      :visible.sync="dialogVisible"
      width="60%"
    >
      <!-- 使用 title slot 来自定义标题 -->
      <template v-slot:title>
        <div class="dialog-title-box">
          <span class="dialog-title-self">异常诊断</span>
          <span class="tags-ai">AI</span>
        </div>
      </template>
      <div v-loading="loading" class="message-content" v-html="htmlContent" />
    </el-dialog>
    <DrawerTable v-if="isShowSpanDrawer" :is-show-drawer="isShowSpanDrawer" :trace-kind="traceKind" :current-alias="currentAlias" :status-message="statusMessage" :current-bar-time="currentBarTime" @close="closeDrawer" />
  </div>
</template>

<script>
import storage from '@/utils/storage'
import moment from 'moment'
import { getAbnormalTable, abnormalAnalyst } from '@/api/mapping'
import DrawerTable from './DrawerTable.vue'
import DrawerTransTable from '../../business-topics/DrawerTransTable.vue'
export default {
  name: 'AbnormalChart',
  components: {
    DrawerTable,
    DrawerTransTable
  },
  props: {
    title: {
      type: String,
      default: '异常事件/每5分钟'
    },
    chartData: {
      type: Array,
      default() {
        return []
      }
    },
    isTableInDrawer: {
      type: Boolean,
      default: true
    },
    traceKind: {
      type: String,
      default: 'app'
    },
    currentAlias: {
      type: String,
      default: ''
    },
    chartDomId: {
      type: String,
      default: ''
    },
    appName: {
      type: String,
      default: ''
    },
    appId: {
      type: String,
      default: ''
    },
    isShowYingBtn: {
      type: Boolean,
      default: false
    },
    isShowTootip: {
      type: Boolean,
      default: false
    },
    serviceName: {
      type: String,
      default: ''
    },
    isShowAbnormalTable: { // 应用专题-异常
      type: Boolean,
      default: false
    },
    route: {
      type: String,
      default: ''
    },
    bisType: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      isShowDrawer: false,
      isShowDrawerTable: false,
      dialogVisible: false,
      loading: false, // 异常解析是否加载
      htmlContent: '',
      tableData: [],
      fireLoading: false,
      query: {
        pageIndex: 1,
        pageSize: 10
      },
      tableTotal: 0,
      appItem: {},
      spansList: [],
      isShowSpanDrawer: false,
      spansTotal: 0,
      currentBarTime: null,
      columnStartTime: 0,
      columnEndTime: 0,
      statusMessage: ''
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initExceptionBarChart(this.chartData)
    })
  },
  methods: {
    getServiceSpans(row) {
      this.statusMessage = row.status_message
      this.isShowSpanDrawer = true
    },
    handleRowClick(row, column, event) {
      if (column.label !== '操作') {
        this.$router.push({
          path: '/service/serviceDetail/index',
          query: {
            id: row.service_id,
            name: row.service_name_cn,
            service_name: row.service_name
          }
        })
      }
    },
    goPage() {
      const obj = {}
      const allAliasArr = this.$store.state.alias.allAliasArr
      const arr = allAliasArr.filter(item => item.alias === this.currentAlias)
      if (arr.length > 0) {
        obj.alias = this.currentAlias
        obj.live = false
        obj.name = this.appName
        obj.id = this.appId
        obj.start_time = this.$store.state.time.globalTimes.startTime
        obj.end_time = this.$store.state.time.globalTimes.endTime
        storage.set('appsItem', obj)
        this.$store.commit('alias/setCurrentAlias', this.currentAlias)
        this.$router.push({
          path: '/business-analysis/system-space/index',
          query: {
            id: this.appId,
            app_alias: this.currentAlias,
            name: this.appName,
            start_time: this.$store.state.time.globalTimes.startTime,
            end_time: this.$store.state.time.globalTimes.endTime
            // item: val,
            // live: val.live
          }
        }).catch(err => err)
      } else {
        this.$message.error('请先配置此应用')
      }
    },
    initExceptionBarChart(data) {
      if (data && data.length > 0) {
        const chart = this.$echarts5.init(document.getElementById(this.chartDomId))
        const succeData = data && data.map(item => new Date(item.start_time).toLocaleString()) || []
        const totalData = data && data.map(item => item.total) || []
        const _this = this
        const option = {
          title: {
            text: this.title,
            textStyle: {
              fontSize: 16, // 标题字体大小
              fontWeight: 'bold', // 标题字体粗细
              color: '#1a2233'
            }
          },
          tooltip: {
            trigger: 'axis',
            axisPointer: {
              type: 'shadow'
            }
          },
          color: ['#5470c6'],
          grid: {
            left: '3%',
            right: '4%',
            bottom: '20%',
            containLabel: true
          },
          dataZoom: [
            {
              type: 'slider',
              start: 0,
              end: 100
            }
          ],
          xAxis: [
            {
              type: 'category',
              data: succeData,
              axisTick: {
                alignWithLabel: true
              },
              axisLabel: {
                interval: 'auto', // 每间隔显示一个坐标
                formatter: function(params) {
                  const newParams = moment(params).format('YYYY-MM-DD HH:mm')
                  const newArr = newParams.split(' ')
                  const time = newArr[0] + '\n' + newArr[1]
                  return time
                }
              }
            }
          ],
          yAxis: [
            {
              type: 'value'
            }
          ],
          series: [
            {
              name: '异常',
              type: 'bar',
              itemStyle: {
                normal: {
                  // 随机显示
                  // 定制显示（按顺序）
                  color: function(params) {
                    return _this.isTableInDrawer === false ? (params.dataIndex === totalData.length - 1 ? 'red' : '#5470c6') : '#5470c6'
                  }
                }
              },
              data: totalData,
              // barWidth: '10', // 同时设置barWidth和barCategoryGap，barCategoryGap不生效
              barCategoryGap: '5',
              barMinWidth: '5',
              barMaxWidth: '24'
            }
          ]
        }

        if (!this.isTableInDrawer) { // 弹窗中的table 不在drawder中默认获取最后一条数据的table 数据
          this.getList(succeData[succeData.length - 1])
          this.currentBarTime = succeData[succeData.length - 1]
        }
        // 注册点击事件
        chart.on('click', function(params) {
          _this.currentBarTime = params.name
          if (_this.isTableInDrawer) {
            _this.columnStartTime = moment(params.name).unix()
            const originalMoment = moment(params.name)
            // 获取增加1小时后的时间戳
            const oneHourLater = originalMoment.add(1, 'hours')
            _this.columnEndTime = oneHourLater.unix()
            if (_this.isShowAbnormalTable) {
              _this.isShowDrawer = true
              _this.isShowDrawerTable = false
              _this.getList(params.name)
            } else {
              _this.isShowDrawerTable = true
              _this.isShowDrawer = false
            }
          } else {
            var dataIndex = params.dataIndex
            // 设置新的颜色
            var newColor = 'red' // 可以根据需要设置新的颜色
            // 更新系列列表中对应数据项的颜色
            chart.setOption({
              series: [{
                data: option.series[0].data.map(function(value, index) {
                  return {
                    value: value,
                    itemStyle: {
                      color: index === dataIndex ? newColor : '#5470c6'
                    }
                  }
                })
              }]
            })
            _this.getList(params.name)
          }
        })
        chart.setOption(option)
      }
    },
    drawerFireClose() {
      this.isShowDrawer = false
    },
    handleCloseTable() {
      this.isShowDrawerTable = false
    },
    async getList(time) { // 获取异常剖析table 数据
      this.fireLoading = true
      const timestamp = moment(time).unix()
      const originalMoment = moment(time)
      const fiveMinutesLaterMoment = originalMoment.add(5, 'minutes')
      const fiveMinutesLaterTimestamp = fiveMinutesLaterMoment.unix()
      const prams = {
        start_time: timestamp,
        end_time: fiveMinutesLaterTimestamp,
        app_alias: this.currentAlias,
        kind: this.traceKind,
        subcondition_value: this.currentAlias
      }
      const res = await getAbnormalTable(prams)
      if (res && res.code === 200) {
        this.tableData = res.data
      } else {
        this.tableData = []
      }
      this.fireLoading = false
    },
    // 使用正则表达式移除开头的 ```html 和结尾的 ```
    filterHtmlCode(content) {
      return content.replace(/^```html\n/, '').replace(/\n```$/, '')
    },
    // 实现使用正则表达式匹配每一行，并将每一行包裹在 <p> 标签中
    // 同时将换行符 \n 替换为 <br>
    wrapLinesWithDivs(inputString) {
      const regex = /(.+?(?=\n|$))/g
      const wrappedLines = inputString.replace(regex, '<p>$1<br></p>')
      // 由于最后一行后面没有换行符，所以我们需要手动添加一个封闭的 </p>
      return wrappedLines + '</p>'
    },
    // 显示AI原因解析
    async showReason(row) {
      this.dialogVisible = true
      this.htmlContent = ''
      this.loading = true
      const res = await abnormalAnalyst({ content: row.status_message })
      if (res && res.code === 200) {
        this.htmlContent = this.filterHtmlCode(res.data.choices[0].message.content)
      } else {
        this.htmlContent = '<p>暂无分析数据</p>'
      }
      this.loading = false
    },

    closeDrawer() {
      this.isShowSpanDrawer = false
    }
  }
}
</script>

<style scoped>
.message-content{
  height: 300px;
  overflow: auto;
}
.chart-container {
  width: 100%;
  height: 100%;
}
.exception-bar-chart {
  width: 100%;
  height: 100%;
}
.chart-no-data{
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  height: calc(100% - 20px);
  color:#999;
}
::v-deep .el-drawer__header{
  background: #4E5969;
  font-size: 24px;
  color: #FFFFFF;
  text-align: center;
  padding-bottom: 20px;
  margin-bottom: 0;
}
::v-deep .el-dialog__body{
  padding: 0px 20px 10px;
}
.dialog-title-box{
  display:flex;
  align-items: center;
}
.dialog-title-self{
  line-height: 24px;
  font-size: 18px;
  color: #303133;
}
.tags-ai{
  display: inline-block;
  padding: 3px 10px;
  margin-left: 10px;
  font-size: 12px;
  border-radius: 4px;
  background-color: #f4f4f5;
  border-color: #e9e9eb;
  color: #909399;
}
.abnormal-table{
  height: 400px;
}
.div-header{
  width: 100%;
  text-align: right;
  margin-top:8px;
}
.readonly-input ::v-deep .el-input__inner{
  background: #F5F7FA;
}
.icon-box{

  i{
    font-size: 16px;
  }
}
.icon-help{
  width: 18px;
  height: 18px;
}
.bar-title{
  font-size: 16px;
  font-weight: bold;
  color: #1a2233;
}
.bar-header{
  display: flex;
  align-items: center;
}
::v-deep .el-table tr{
  cursor: pointer;
}
</style>
<style >
.custom-tooltip{
  max-width: 300px !important;
}
</style>

