<template>
  <div class="doc-block-crepe" :class="{ collapsed: isCollapsed }">
    <div class="doc-header">
      <div class="doc-icon">
        <svg v-if="docType === 'pdf'" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
          <polyline points="14 2 14 8 20 8"/>
          <path d="M9 15v-2h6v2"/>
          <path d="M12 13v4"/>
        </svg>
        <svg v-else-if="docType === 'doc'" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
          <polyline points="14 2 14 8 20 8"/>
          <path d="M16 13H8"/>
          <path d="M16 17H8"/>
          <path d="M10 9H8"/>
        </svg>
        <svg v-else-if="docType === 'ppt'" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <rect x="2" y="3" width="20" height="14" rx="2"/>
          <path d="M8 21h8"/>
          <path d="M12 17v4"/>
        </svg>
        <svg v-else width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
          <polyline points="14 2 14 8 20 8"/>
          <path d="M16 13H8"/>
          <path d="M16 17H8"/>
        </svg>
      </div>
      <div class="doc-name">{{ docName }}</div>
      <div class="doc-actions">
        <button @click="downloadDoc" class="action-btn" title="下载文档">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
            <polyline points="7 10 12 15 17 10"/>
            <line x1="12" y1="15" x2="12" y2="3"/>
          </svg>
        </button>
        <button @click="toggleCollapse" class="action-btn collapse-btn" :title="isCollapsed ? '展开' : '折叠'">
          <svg v-if="isCollapsed" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <polyline points="9 18 15 12 9 6"/>
          </svg>
          <svg v-else width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <polyline points="6 9 12 15 18 9"/>
          </svg>
        </button>
      </div>
    </div>
    <div class="doc-editor" v-show="!isCollapsed">
      <div ref="editorRoot" class="inner-crepe"></div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'
import { Crepe } from '@milkdown/crepe'
import { editorViewCtx, serializerCtx } from '@milkdown/kit/core'
import { copilotPlugin, copilotConfigCtx, setCopilotEnabled } from '../plugins/copilotPlugin'
import { fetchSuggestion } from '../utils/api.js'

const props = defineProps({
  docType: { type: String, default: 'text' },
  docName: { type: String, default: 'document.txt' },
  uploadTime: { type: String, default: '' },
  initialContent: { type: String, default: '' }
})

const emit = defineEmits(['update:content', 'delete'])

const editorRoot = ref(null)
const isCollapsed = ref(false)
let crepe = null
let internalChangeTimer = null

const toggleCollapse = () => {
  isCollapsed.value = !isCollapsed.value
}

const downloadDoc = () => {
  if (!crepe) return
  crepe.getMarkdown().then(markdown => {
    const blob = new Blob([markdown], { type: 'text/plain;charset=utf-8' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = props.docName
    document.body.appendChild(a)
    a.click()
    a.remove()
    URL.revokeObjectURL(url)
  })
}

const syncContent = () => {
  if (!crepe) return
  if (internalChangeTimer) clearTimeout(internalChangeTimer)
  internalChangeTimer = setTimeout(async () => {
    const markdown = await crepe.getMarkdown()
    emit('update:content', markdown)
  }, 120)
}

onMounted(async () => {
  if (!editorRoot.value) return
  crepe = new Crepe({
    root: editorRoot.value,
    defaultValue: props.initialContent || '',
    features: {
      [Crepe.Feature.Latex]: true,
      [Crepe.Feature.ImageBlock]: true,
      [Crepe.Feature.Table]: true,
      [Crepe.Feature.ListCheck]: true,
    },
    config: { showLineNumber: false }
  })
  
  crepe.editor.config(ctx => {
    ctx.set(copilotConfigCtx.key, {
      fetchSuggestion,
      debounceMs: 1000
    })
  })
  
  crepe.editor.use(copilotPlugin)
  await crepe.create()
  
  crepe.on(listener => {
    listener.updated(() => {
      syncContent()
    })
  })
  
  crepe.editor.action(ctx => {
    const view = ctx.get(editorViewCtx)
    setCopilotEnabled(view, true)
  })
})

watch(() => props.initialContent, (newVal) => {
  if (crepe && newVal !== undefined) {
    crepe.editor.action(ctx => {
      const view = ctx.get(editorViewCtx)
      const currentPos = view.state.selection.from
      view.dispatch(view.state.tr.insertText(newVal))
    })
  }
})

onUnmounted(() => {
  if (internalChangeTimer) clearTimeout(internalChangeTimer)
  if (crepe) {
    crepe.destroy()
    crepe = null
  }
})

defineExpose({
  getContent: () => crepe ? crepe.getMarkdown() : Promise.resolve(''),
  getEditor: () => crepe
})
</script>

<style scoped>
.doc-block-crepe {
  margin: 12px 0;
  border-radius: 8px;
  overflow: hidden;
  background: var(--crepe-color-surface-low);
  border: 1px solid var(--panel-border);
}

.doc-block-crepe.collapsed .doc-editor {
  display: none;
}

.doc-header {
  display: flex;
  align-items: center;
  padding: 10px 12px;
  background: var(--crepe-color-surface);
  border-bottom: 1px solid var(--panel-border);
  gap: 10px;
}

.doc-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--crepe-color-primary);
}

.doc-name {
  flex: 1;
  font-size: 14px;
  font-weight: 500;
  color: var(--crepe-color-on-surface);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.doc-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}

.action-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--crepe-color-on-surface-variant);
  cursor: pointer;
  border-radius: 4px;
  opacity: 0.7;
}

.action-btn:hover {
  background: var(--crepe-color-hover);
  opacity: 1;
}

.doc-editor {
  padding: 8px;
  background: var(--crepe-color-surface-low);
  min-height: 120px;
  max-height: 400px;
  overflow-y: auto;
}

.inner-crepe {
  width: 100%;
  height: 100%;
}

.inner-crepe :deep(.milkdown) {
  background: transparent !important;
}

.inner-crepe :deep(.ProseMirror) {
  min-height: 80px;
  padding: 8px !important;
}
</style>
