<template>
  <div class="white content">
    <div class="white">
      <div v-loading="loading">
        <v-banner class="mb-3">
          Redis
          <template v-slot:actions>
            <v-btn
              text
              color="primary"
              @click="getConversationsStatus"
            >
              <v-icon left>mdi-refresh</v-icon>
              刷新
            </v-btn>
            <v-btn
              text
              color="deep-purple accent-4"
              @click="onClearRedisCache({ clear_all_agent_data: true })"
            >
              <v-icon left>mdi-trash-can-outline</v-icon>
              清空所有agent对话数据
            </v-btn>
            <v-btn
              text
              color="deep-purple accent-4"
              @click="onClearRedisCache({ cleanup_invalid_refs: true })"
            >
              <v-icon left>mdi-trash-can-outline</v-icon>
              清理无效引用
            </v-btn>
            <!-- <v-btn
              text
              color="deep-purple accent-4"
              @click="onClearRedisCache"
            >
              <v-icon left>mdi-trash-can-outline</v-icon>
              清除所有对话缓存
            </v-btn> -->
          </template>
        </v-banner>
        <v-container>
          <v-row >
            <v-col
              v-for="elevation in elevations"
              :key="elevation.value"
              cols="3"
            >
              <v-card
                class="pa-2"
                tile
                height="150"
              >
                <div class="d-flex align-center justify-center flex-column" style="height: 100%;">
                  <div class="text-h3" :class="`${elevation.textColor}--text`">{{ itemData[elevation.value] }}</div>
                  <div>{{ elevation.text }}</div>
                </div>
              </v-card>
            </v-col>
          </v-row>
        </v-container>
      </div>
      <!-- <v-divider></v-divider> -->

      <div v-loading="embLoading">
        <v-banner class="mb-3">
          embedding
          <template v-slot:actions>
            <v-btn
              text
              color="primary"
              @click="getEmbeddingStats"
            >
              <v-icon left>mdi-refresh</v-icon>
              刷新
            </v-btn>
            <v-btn
              text
              color="deep-purple accent-4"
              @click="onClearEmbeddingCache"
            >
              <v-icon left>mdi-trash-can-outline</v-icon>
              清除对话缓存
            </v-btn>
          </template>
        </v-banner>
        <v-container>
          <v-row >
            <v-col
              v-for="elevation in embeddingElevations"
              :key="elevation.value"
              cols="3"
            >
              <v-card
                class="pa-2"
                tile
                height="150"
              >
                <div class="d-flex align-center justify-center flex-column" style="height: 100%;">
                  <div class="text-h3" :class="`${elevation.textColor}--text`">{{ embeddingData[elevation.value] }}</div>
                  <div>{{ elevation.text }}</div>
                </div>
              </v-card>
            </v-col>
          </v-row>
        </v-container>
      </div>

      <div v-loading="checkpointLoading">
        <v-banner class="mb-3">
          Checkpoint
          <template v-slot:actions>
            <v-btn
              text
              color="primary"
              @click="getCheckpoint"
            >
              <v-icon left>mdi-refresh</v-icon>
              刷新
            </v-btn>
            <v-btn
              text
              color="deep-purple accent-4"
              @click="onClearCheckpoint"
            >
              <v-icon left>mdi-trash-can-outline</v-icon>
              清除对话缓存
            </v-btn>
          </template>
        </v-banner>
        <v-container>
          <v-row >
            <v-col
              v-for="elevation in checkpointElevations"
              :key="elevation.value"
              cols="3"
            >
              <v-card
                class="pa-2"
                tile
                height="150"
              >
                <div class="d-flex align-center justify-center flex-column" style="height: 100%;">
                  <div
                    class="text-h3"
                    :class="`${elevation.textColor}--text ${elevation.onClick ? 'cursor-pointer' : ''}`"
                    @click="elevation.onClick && elevation.onClick(elevation, checkpointData)"
                  >
                    {{ checkpointData[elevation.value] }}
                  </div>
                  <div>{{ elevation.text }}</div>
                </div>
              </v-card>
            </v-col>
          </v-row>
        </v-container>
      </div>
    </div>
    <MDialog :visible.sync="show" title="设置保留checkpoint数量" @submit="handleSubmit" widthType="2">
      <v-text-field
        v-model="checkpointParam.keep_count"
        dense
        label="checkpoint数量"
        placeholder="请输入每个线程保留的checkpoint数量"
        outlined
      ></v-text-field>
    </MDialog>
    <ModelDetails ref="userRefs" title="用户列表">
      <template #actions="{ item }">
        <v-btn
          text
          color="primary"
          @click="onClearCheckpoint({
            keep_count: 10,
            user_id: item.user_id,
            thread_id: undefined
          })"
        >清理Checkpoint</v-btn>
      </template>
    </ModelDetails>
    <ModelDetails ref="threadRefs" title="线程列表">
      <template #actions="{ item }">
        <v-btn
          text
          color="primary"
          @click="onClearCheckpoint({
            keep_count: 10,
            user_id: undefined,
            thread_id: item.thread_id
          })"
        >清理Checkpoint</v-btn>
      </template>
    </ModelDetails>
  </div>
</template>

<script>
import {
  getConversationsStatus,
  clearConversation,
  getEmbeddingStats,
  clearEmbeddingCache,
  getCheckpoint,
  clearCheckpoint
} from '@/api/dataChart'
import MDialog from '@/components/Dialog'
import ModelDetails from './modelDetails'
export default {
  name: 'modelHistory',
  components: {
    MDialog,
    ModelDetails
  },
  data () {
    return {
      showUser: false,
      show: false,
      loading: false,
      embLoading: false,
      checkpointLoading: false,
      elevations: [
        { value: 'connected_clients', text: '客户端连接数', textColor: 'primary' },
        { value: 'memory_usage_mb', text: 'redis占用内存(M)', textColor: 'primary' },
        { value: 'total_conversations', text: '会话总数', textColor: 'primary' },
        { value: 'total_users', text: '用户数', textColor: 'primary' }
      ],
      itemData: {},
      embeddingElevations: [
        { value: 'memory_usage_mb', text: 'embedding占用内存(M)', textColor: 'primary' },
        { value: 'total_count', text: '总数', textColor: 'primary' }
      ],
      checkpointElevations: [
        { value: 'total_users', text: '用户数量', textColor: 'primary', onClick: this.onClickUser },
        { value: 'total_threads', text: '线程总数', textColor: 'primary', onClick: this.onClickThread },
        { value: 'total_checkpoints', text: 'checkpoints总数', textColor: 'primary' }
      ],
      embeddingData: {},
      checkpointData: {},
      checkpointParam: {
        keep_count: 10,
        user_id: undefined,
        thread_id: undefined
      }
    }
  },
  created () {
    this.getConversationsStatus()
    this.getEmbeddingStats()
    this.getCheckpoint()
  },
  methods: {
    onClickUser (item, itemData) {
      this.$refs.userRefs.open([
        { text: '用户ID', value: 'user_id' },
        { text: '线程总数', value: 'thread_count' },
        { text: 'checkpoints数', value: 'total_checkpoints' },
        { text: '操作', value: 'actions' }
      ], itemData.users)
    },
    onClickThread (item, itemData) {
      this.$refs.threadRefs.open([
        { text: '线程ID', value: 'thread_id' },
        { text: 'checkpoints数', value: 'checkpoint_count' },
        { text: '用户ID', value: 'user_id' },
        { text: '操作', value: 'actions' }
      ], itemData.users.reduce((acc, cur) => {
        acc.push(...cur.threads.map(e => {
          return { ...e, user_id: cur.user_id }
        }))
        return acc
      }, []))
    },
    async getConversationsStatus () {
      this.loading = true
      try {
        const { data } = await getConversationsStatus()
        this.itemData = { ...data, ...data.redis_info }
      } catch (error) {
        this.$snackbar.error(error)
      } finally {
        this.loading = false
      }
    },
    async getEmbeddingStats () {
      this.embLoading = true
      try {
        const { data } = await getEmbeddingStats()
        this.embeddingData = data
      } catch (error) {
        this.$snackbar.error(error)
      } finally {
        this.embLoading = false
      }
    },
    async getCheckpoint () {
      this.checkpointLoading = true
      try {
        const { data } = await getCheckpoint()
        this.checkpointData = data
      } catch (error) {
        this.$snackbar.error(error)
      } finally {
        this.checkpointLoading = false
      }
    },
    onClearRedisCache (param) {
      this.$confirm('提示', '确定执行清除吗？').then(async () => {
        this.loading = true
        try {
          await clearConversation(param)
          this.$snackbar.success('清除成功')
          this.getConversationsStatus()
        } catch (error) {
          this.$snackbar.error(error)
        } finally {
          this.loading = false
        }
      })
    },
    onClearEmbeddingCache () {
      this.$confirm('提示', '确定清除embedding缓存吗？').then(async () => {
        this.loading = true
        try {
          await clearEmbeddingCache()
          this.$snackbar.success('清除成功')
          this.getEmbeddingStats()
        } catch (error) {
          this.$snackbar.error(error)
        } finally {
          this.loading = false
        }
      })
    },
    onClearCheckpoint (param = {
      keep_count: 10,
      user_id: undefined,
      thread_id: undefined
    }) {
      this.show = true
      this.checkpointParam = param
    },
    async handleSubmit () {
      if (!this.checkpointParam.keep_count) {
        this.$snackbar.error('请输入保留的checkpoint数量')
        return
      }
      try {
        this.checkpointParam.keep_count = Number(this.checkpointParam.keep_count)
        const { data } = await clearCheckpoint(this.checkpointParam)
        this.$snackbar.success(data.response)
        this.show = false
        this.getCheckpoint()
        this.$refs.userRefs.close()
        this.$refs.threadRefs.close()
      } catch (error) {
        this.$snackbar.error(error)
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.content {
  font-size: 16px;
}
.cursor-pointer {
  cursor: pointer;
}
</style>
