<template>
  <div>
    <div class="page-mark-map">
      <div class="inner custom-scroll">
        <div class="mark-map-box" :style="{ height: leftBoxHeight + 'px' }">
          <h2>思维导图创作中心</h2>

          <div class="mark-map-params">
            <el-form label-width="80px" label-position="left">
              <div class="param-line">你的需求？</div>
              <div class="param-line">
                <el-input
                  v-model="prompt"
                  :autosize="{ minRows: 4, maxRows: 6 }"
                  type="textarea"
                  placeholder="请给AI输入提示词，让AI帮你完善"
                />
              </div>

              <div class="param-line">请选择生成思维导图的AI模型</div>
              <div class="param-line">
                <el-select v-model="modelID" placeholder="请选择模型" style="width: 100%">
                  <el-option
                    v-for="item in models"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                  >
                    <span>{{ item.name }}</span>
                    <el-tag
                      style="margin-left: 5px; position: relative; top: -2px"
                      type="info"
                      size="small"
                      >{{ item.power }}算力
                    </el-tag>
                  </el-option>
                </el-select>
              </div>

              <div class="text-info">
                <el-text type="primary"
                  >当前可用算力：<el-text type="warning">{{ loginUser.power }}</el-text></el-text
                >
              </div>

              <div class="p-4">
                <button
                  class="w-full py-3 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-xl disabled:from-gray-400 disabled:to-gray-400 disabled:cursor-not-allowed hover:from-blue-600 hover:to-purple-700 transition-all duration-200 flex items-center justify-center space-x-2 text-base"
                  type="button"
                  @click="generateAI"
                  :disabled="loading"
                >
                  <i v-if="loading" class="iconfont icon-loading animate-spin"></i>
                  <i v-else class="iconfont icon-chuangzuo"></i>
                  <span>生成思维导图</span>
                </button>
              </div>

              <div class="param-line">使用已有内容生成？</div>
              <div class="param-line">
                <el-input
                  v-model="content"
                  :autosize="{ minRows: 4, maxRows: 6 }"
                  type="textarea"
                  placeholder="请用markdown语法输入您想要生成思维导图的内容！"
                />
              </div>

              <div class="param-line">
                <button
                  class="w-full py-3 bg-gradient-to-r from-green-400 to-blue-500 text-white rounded-xl disabled:from-gray-400 disabled:to-gray-400 disabled:cursor-not-allowed hover:from-green-500 hover:to-blue-600 transition-all duration-200 flex items-center justify-center space-x-2 text-base"
                  @click="generate"
                  type="button"
                >
                  直接生成（免费）
                </button>
              </div>
            </el-form>
          </div>
        </div>

        <div class="chat-box">
          <!-- <div class="top-bar">
            <el-button @click="downloadImage" type="primary">
              <el-icon>
                <Download />
              </el-icon>
              <span>下载图片-</span>
            </el-button>
          </div> -->

          <div class="body" id="markmap">
            <svg ref="svgRef" :style="{ height: rightBoxHeight + 'px' }" />
            <div id="toolbar">
              <el-button @click="downloadImage" type="primary">
                <el-icon>
                  <Download />
                </el-icon>
                <span>下载图片</span>
              </el-button>
            </div>
          </div>
        </div>
        <!-- end task list box -->
      </div>
    </div>
  </div>
</template>

<script setup>
import { checkSession, getSystemInfo } from '@/store/cache'
import { useSharedStore } from '@/store/sharedata'
import { httpGet, httpPost } from '@/utils/http'
import { Download } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { Transformer } from 'markmap-lib'
import { Toolbar } from 'markmap-toolbar'
import { Markmap } from 'markmap-view'
import { nextTick, onMounted, ref } from 'vue'

const leftBoxHeight = ref(window.innerHeight - 105)
//const rightBoxHeight = ref(window.innerHeight - 115);
const rightBoxHeight = ref(window.innerHeight)

const prompt = ref('')
const text = ref('')
const content = ref(text.value)
const html = ref('')

const isLogin = ref(false)
const loginUser = ref({ power: 0 })
const transformer = new Transformer()
const store = useSharedStore()
const loading = ref(false)

const svgRef = ref(null)
const markMap = ref(null)
const models = ref([])
const modelID = ref(0)
const cacheKey = ref('MarkMapCache')

onMounted(async () => {
  const cache = localStorage.getItem(cacheKey.value)
  if (cache) {
    text.value = cache
  } else {
    const res = await httpGet('/api/config/get?key=mark_map')
    text.value = res.data?.content || ''
    content.value = text.value
  }

  initData()
  nextTick(() => {
    try {
      markMap.value = Markmap.create(svgRef.value)
      const { el } = Toolbar.create(markMap.value)
      document.getElementById('toolbar').append(el)
      update()
    } catch (e) {
      console.error(e)
    }
  })
})

const initData = () => {
  httpGet('/api/model/list')
    .then((res) => {
      for (let v of res.data) {
        models.value.push(v)
      }
      modelID.value = models.value[0].id
    })
    .catch((e) => {
      ElMessage.error('获取模型失败：' + e.message)
    })

  checkSession()
    .then((user) => {
      loginUser.value = user
      isLogin.value = true
    })
    .catch(() => {})
}

const update = () => {
  try {
    const { root } = transformer.transform(processContent(text.value))
    markMap.value.setData(root)
    markMap.value.fit()
  } catch (e) {
    console.error(e)
  }
}

const processContent = (text) => {
  if (!text) {
    return text
  }

  const arr = []
  const lines = text.split('\n')
  for (let line of lines) {
    if (line.indexOf('```') !== -1) {
      continue
    }
    line = line.replace(/([*_~`>])|(\d+\.)\s/g, '')
    arr.push(line)
  }
  return arr.join('\n')
}

window.onresize = () => {
  leftBoxHeight.value = window.innerHeight - 145
  rightBoxHeight.value = window.innerHeight - 85
}

const generate = () => {
  text.value = content.value
  update()
}

// 使用 AI 智能生成
const generateAI = () => {
  html.value = ''
  text.value = ''
  if (prompt.value === '') {
    return ElMessage.error('请输入你的需求')
  }
  if (!isLogin.value) {
    store.setShowLoginDialog(true)
    return
  }
  loading.value = true
  httpPost('/api/markMap/gen', {
    prompt: prompt.value,
    model_id: modelID.value,
  })
    .then((res) => {
      const raw = res?.data
      if (raw == null || String(raw).trim() === '') {
        ElMessage.error('生成结果为空，请重试或更换模型')
        loading.value = false
        return
      }
      text.value = typeof raw === 'string' ? raw : String(raw)
      content.value = processContent(text.value)
      const model = getModelById(modelID.value)
      loginUser.value.power -= model.power
      nextTick(() => update())
      loading.value = false
      // 缓存结果
      localStorage.setItem(cacheKey.value, text.value)
    })
    .catch((e) => {
      ElMessage.error('生成思维导图失败：' + e.message)
      loading.value = false
    })
}

const getModelById = (modelId) => {
  for (let m of models.value) {
    if (m.id === modelId) {
      return m
    }
  }
}

// download SVG to png file
const downloadImage = async () => {
  // 先自适应思维导图到可视化区域
  await markMap.value.fit()

  const svgElement = document.getElementById('markmap')
  const serializer = new XMLSerializer()
  const source =
    '<?xml version="1.0" standalone="no"?>\r\n' + serializer.serializeToString(svgRef.value)
  const image = new Image()
  image.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(source)

  // 分辨率倍数，越高图片越清晰，但文件越大
  const scale = 4
  const canvas = document.createElement('canvas')
  canvas.width = svgElement.offsetWidth * scale
  canvas.height = svgElement.offsetHeight * scale

  let context = canvas.getContext('2d')
  context.clearRect(0, 0, canvas.width, canvas.height)
  context.fillStyle = 'white'
  context.fillRect(0, 0, canvas.width, canvas.height)

  image.onload = function () {
    // 关键：缩放 context
    context.setTransform(scale, 0, 0, scale, 0, 0)
    context.drawImage(image, 0, 0)
    const a = document.createElement('a')
    a.download = 'geek-ai-xmind.png'
    a.href = canvas.toDataURL('image/png')
    a.click()
  }
}
</script>

<style lang="scss">
@use '../assets/css/mark-map.scss' as *;
@use '../assets/css/custom-scroll.scss' as *;
</style>
