<template>
  <a-modal
    :open="open"
    title="添加来源"
    width="640px"
    @cancel="$emit('close')"
    destroy-on-close
  >
    <template #footer>
      <template v-if="activeTab === 'search' && selectedDocs.size > 0">
        <a-button @click="$emit('close')">取消</a-button>
        <a-button type="primary" :loading="adding" @click="handleAddSelected">
          添加已选 ({{ selectedDocs.size }})
        </a-button>
      </template>
      <template v-else>
        <a-button @click="$emit('close')">关闭</a-button>
      </template>
    </template>

    <a-tabs v-model:activeKey="activeTab">
      <!-- Tab 1: Search -->
      <a-tab-pane key="search" tab="文档检索">
        <div class="search-tab">
          <a-input-search
            v-model:value="searchQuery"
            placeholder="搜索文档…"
            @search="handleSearch"
            :loading="searching"
            allow-clear
          />
          <div class="search-results" v-if="searchResults.length">
            <div
              v-for="doc in searchResults"
              :key="doc.doc_id"
              class="search-result-item"
              :class="{ 'result-selected': selectedDocs.has(doc.doc_id), 'result-added': isAlreadyAdded(doc.doc_id) }"
              @click="toggleSelect(doc)"
            >
              <a-checkbox
                :checked="selectedDocs.has(doc.doc_id)"
                :disabled="isAlreadyAdded(doc.doc_id)"
                @click.stop
                @change="toggleSelect(doc)"
              />
              <div class="result-info">
                <div class="result-title">{{ cleanTitle(doc.title || doc.doc_id) }}</div>
                <div class="result-meta" v-if="doc.doc_number">{{ doc.doc_number }}</div>
              </div>
              <a-tag v-if="isAlreadyAdded(doc.doc_id)" size="small" color="default">已添加</a-tag>
            </div>
          </div>
          <a-empty v-else-if="searched && !searching" description="未找到文档" />
        </div>
      </a-tab-pane>

      <!-- Tab 2: Upload -->
      <a-tab-pane key="upload" tab="上传文件">
        <div class="upload-tab">
          <a-upload-dragger
            :before-upload="handleUpload"
            :show-upload-list="false"
            accept=".pdf,.docx,.doc,.xlsx,.xls,.txt,.rtf,.csv"
          >
            <p class="ant-upload-drag-icon">
              <InboxOutlined />
            </p>
            <p class="ant-upload-text">点击或拖拽文件到此区域</p>
            <p class="ant-upload-hint">支持 PDF、Word、Excel、TXT 等格式，单文件最大 50MB</p>
          </a-upload-dragger>
        </div>
      </a-tab-pane>

      <!-- Tab 3: Paste -->
      <a-tab-pane key="paste" tab="粘贴文字">
        <div class="paste-tab">
          <a-input
            v-model:value="pasteTitle"
            placeholder="来源标题"
            style="margin-bottom: 12px"
          />
          <a-textarea
            v-model:value="pasteContent"
            placeholder="粘贴文字内容…"
            :rows="8"
            :maxlength="200000"
            show-count
          />
          <a-button
            type="primary"
            style="margin-top: 12px"
            :disabled="!pasteTitle.trim() || !pasteContent.trim()"
            :loading="pasting"
            @click="handlePaste"
          >
            添加
          </a-button>
        </div>
      </a-tab-pane>
    </a-tabs>
  </a-modal>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { InboxOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { searchDocuments } from '@/api/search'
import { useNotebookStore } from '@/stores/notebook'

const props = defineProps<{
  open: boolean
  notebookId: string
}>()

const emit = defineEmits<{
  close: []
  added: []
}>()

const store = useNotebookStore()

const activeTab = ref('search')

// ── Search ──────────────────────────────────────────

const searchQuery = ref('')
const searchResults = ref<Array<{ doc_id: string; title?: string; doc_number?: string }>>([])
const searching = ref(false)
const searched = ref(false)
const selectedDocs = ref<Map<string, { doc_id: string; title: string }>>(new Map())
const adding = ref(false)

// IDs of sources already in this notebook
const existingDocIds = computed(() => new Set(store.sources.map((s) => s.doc_id).filter(Boolean)))

function isAlreadyAdded(docId: string): boolean {
  return existingDocIds.value.has(docId)
}

function cleanTitle(title: string): string {
  return title.replace(/<\/?em>/g, '')
}

async function handleSearch() {
  if (!searchQuery.value.trim()) return
  searching.value = true
  searched.value = true
  try {
    const result = await searchDocuments({
      query: searchQuery.value,
      page_size: 20,
    })
    searchResults.value = result.documents || []
  } catch (e: any) {
    message.error('搜索失败')
  } finally {
    searching.value = false
  }
}

function toggleSelect(doc: { doc_id: string; title?: string }) {
  if (isAlreadyAdded(doc.doc_id)) return
  if (selectedDocs.value.has(doc.doc_id)) {
    selectedDocs.value.delete(doc.doc_id)
  } else {
    selectedDocs.value.set(doc.doc_id, { doc_id: doc.doc_id, title: cleanTitle(doc.title || doc.doc_id) })
  }
  // Force reactivity
  selectedDocs.value = new Map(selectedDocs.value)
}

async function handleAddSelected() {
  if (selectedDocs.value.size === 0) return
  adding.value = true
  let successCount = 0
  let failCount = 0
  for (const [, doc] of selectedDocs.value) {
    try {
      await store.addSourceBySearch(props.notebookId, doc.doc_id, doc.title)
      successCount++
    } catch {
      failCount++
    }
  }
  adding.value = false
  selectedDocs.value = new Map()
  if (successCount > 0) {
    message.success(`已添加 ${successCount} 个来源`)
  }
  if (failCount > 0) {
    message.warning(`${failCount} 个添加失败（可能已达上限或重复）`)
  }
  emit('added')
}

// ── Upload ──────────────────────────────────────────

async function handleUpload(file: File) {
  try {
    await store.addSourceByUpload(props.notebookId, file)
    message.success('文件已上传，正在处理')
    emit('added')
  } catch (e: any) {
    message.error(e?.response?.data?.detail || '上传失败')
  }
  return false
}

// ── Paste ───────────────────────────────────────────

const pasteTitle = ref('')
const pasteContent = ref('')
const pasting = ref(false)

async function handlePaste() {
  if (!pasteTitle.value.trim() || !pasteContent.value.trim()) return
  pasting.value = true
  try {
    await store.addSourceByPaste(props.notebookId, pasteTitle.value, pasteContent.value)
    message.success('已添加来源，正在处理')
    pasteTitle.value = ''
    pasteContent.value = ''
    emit('added')
  } catch (e: any) {
    message.error(e?.response?.data?.detail || '添加失败')
  } finally {
    pasting.value = false
  }
}
</script>

<style scoped lang="less">
.search-tab {
  .search-results {
    margin-top: 12px;
    max-height: 340px;
    overflow-y: auto;
  }

  .search-result-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.15s;

    &:hover {
      background: #f5f5f5;
    }

    &.result-selected {
      background: #e6f4ff;
    }

    &.result-added {
      opacity: 0.5;
      cursor: not-allowed;
    }

    .result-info {
      flex: 1;
      overflow: hidden;
    }

    .result-title {
      font-size: 13px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .result-meta {
      font-size: 12px;
      color: #8c8c8c;
    }
  }
}

.paste-tab {
  padding: 4px 0;
}
</style>
