<!-- 证据工作区侧边栏：证据引用分组展示和导入资料管理 -->
<template>
  <aside class="evidence-panel">
    <a-tabs v-model:activeKey="localTab" size="small">
      <a-tab-pane key="evidence" :tab="`引用证据 ${references.length ? `(${references.length})` : ''}`">
        <section class="tab-shell">
          <div class="sidebar-list sidebar-list--sectioned">
            <a-empty v-if="references.length === 0" description="执行后会在这里沉淀证据" />
            <a-alert
              v-else-if="guideReferenceCount"
              type="warning"
              show-icon
              class="guide-alert"
              message="已命中办事指南结构化证据"
              :description="`当前共有 ${guideReferenceCount} 条 Guide 来源引用，适合核对材料、条件、收费、时限和办理窗口。`"
            />
            <div v-for="group in evidenceGroups" :key="group.key" class="evidence-group-shell">
              <div class="evidence-group__header" :class="{ 'evidence-group__header--guide': group.key === 'guide' }">
                <div class="evidence-group__title">{{ group.label }}</div>
                <a-tag>{{ group.items.length }}</a-tag>
              </div>
              <div class="evidence-group">
                <CitationCard
                  v-for="(reference, index) in group.items"
                  :key="`${reference.doc_id}-${index}`"
                  :reference="reference"
                  :index="index"
                  @open="emit('open-reference', $event)"
                />
              </div>
            </div>
          </div>
        </section>
      </a-tab-pane>

      <a-tab-pane key="materials" :tab="`导入资料 ${importedItems.length ? `(${importedItems.length})` : ''}`">
        <section class="tab-shell">
          <div class="sidebar-actions">
            <a-space>
              <a-button size="small" @click="emit('import-basket')" :disabled="!hasBasketItems || busy">
                导入资料篮全部
              </a-button>
              <a-button
                size="small"
                danger
                @click="emit('clear-imported')"
                :disabled="!importedItems.length || busy"
              >
                清空
              </a-button>
            </a-space>
          </div>

          <div class="sidebar-list sidebar-list--sectioned">
            <a-empty v-if="importedItems.length === 0" description="暂无导入资料" />
            <a-card
              v-for="(item, idx) in importedItems"
              :key="`${item.item_type}-${idx}-${item.title}`"
              size="small"
              class="material-card"
            >
              <div class="material-card__title-row">
                <a-tag color="blue" :bordered="false">{{ getItemTypeLabel(item.item_type) }}</a-tag>
                <div class="material-card__title">{{ item.title }}</div>
              </div>
              <div class="material-card__meta">
                来源：{{ (item as any).item_type === 'uploaded_file' ? '用户上传' : item.selected_from }}
                <span v-if="(item as any).char_count" style="margin-left: 4px; color: rgba(0,0,0,0.35)">
                  · {{ formatCharCount((item as any).char_count) }}
                </span>
                <span v-if="item.note"> · {{ item.note }}</span>
              </div>
              <div class="material-card__actions">
                <a-button
                  v-if="(item as any).item_type === 'uploaded_file'"
                  size="small"
                  @click="emit('download-file', (item as any).file_id, item.title)"
                >
                  <DownloadOutlined /> 下载源文件
                </a-button>
                <a-button
                  v-else-if="item.item_type === 'document' || item.item_type === 'snippet'"
                  size="small"
                  @click="emit('open-document', item.doc_id)"
                >
                  打开文档
                </a-button>
                <a-button
                  v-else-if="item.item_type === 'matter'"
                  size="small"
                  @click="emit('open-matter', item.matter_id)"
                >
                  打开事项
                </a-button>
                <a-button type="link" danger size="small" :disabled="busy" @click="emit('remove-imported', item)">
                  移除
                </a-button>
              </div>
            </a-card>
          </div>
        </section>
      </a-tab-pane>
    </a-tabs>
  </aside>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { DownloadOutlined } from '@ant-design/icons-vue'
import CitationCard from '@/components/CitationCard.vue'
import type { BasketItem } from '@/types/basket'
import type { ResearchReference } from '@/types/document'
import { getItemTypeLabel } from '@/utils/basketKeys'

function formatCharCount(n: number): string {
  if (n >= 10000) return `${(n / 10000).toFixed(1)}万字`
  if (n >= 1000) return `${(n / 1000).toFixed(1)}k字`
  return `${n}字`
}

const props = defineProps<{
  /** 引用材料列表 */
  references: ResearchReference[]
  /** 导入的资料列表 */
  importedItems: BasketItem[]
  /** 资料篮中是否有资料 */
  hasBasketItems: boolean
  /** 是否忙碌 */
  busy: boolean
  /** 外部控制的活动标签页 */
  activeTab: string
}>()

const emit = defineEmits<{
  (e: 'import-basket'): void
  (e: 'clear-imported'): void
  (e: 'remove-imported', item: BasketItem): void
  (e: 'open-document', docId: string): void
  (e: 'open-matter', matterId: string): void
  (e: 'open-reference', reference: ResearchReference): void
  (e: 'download-file', fileId: string, fileName: string): void
  (e: 'update:activeTab', value: string): void
}>()

const localTab = ref(props.activeTab)

watch(() => props.activeTab, (v) => { localTab.value = v })
watch(localTab, (v) => { emit('update:activeTab', v) })

/** 将引用材料按来源分组（显式纳入 / 检索命中 / 图谱补充） */
const evidenceGroups = computed(() => {
  const order = ['guide', 'seed', 'search', 'graph']
  const groupMap = new Map<string, { key: string; label: string; items: ResearchReference[] }>()

  const defaultLabel = (key: string) => {
    if (key === 'guide') return '办事指南结构化证据'
    if (key === 'seed') return '显式纳入资料'
    if (key === 'graph') return '图谱补充材料'
    return '混合检索命中'
  }

  props.references.forEach((item) => {
    const key = item.source_group || 'search'
    if (!groupMap.has(key)) {
      groupMap.set(key, {
        key,
        label: item.source_label || defaultLabel(key),
        items: [],
      })
    }
    groupMap.get(key)?.items.push(item)
  })

  return [...groupMap.values()].sort((left, right) => {
    const leftIndex = order.includes(left.key) ? order.indexOf(left.key) : order.length
    const rightIndex = order.includes(right.key) ? order.indexOf(right.key) : order.length
    return leftIndex - rightIndex
  })
})

const guideReferenceCount = computed(() => props.references.filter((item) => item.source_group === 'guide').length)
</script>

<style scoped lang="less">
.evidence-panel {
  display: flex;
  flex-direction: column;
  padding: 16px;
  background: #ffffff;
  overflow: hidden;
}

.evidence-panel :deep(.ant-tabs) {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-height: 0;
}

.evidence-panel :deep(.ant-tabs-content-holder),
.evidence-panel :deep(.ant-tabs-content),
.evidence-panel :deep(.ant-tabs-tabpane) {
  min-height: 0;
  height: 100%;
}

.evidence-panel :deep(.ant-tabs-tabpane) {
  display: flex;
  flex-direction: column;
}

.tab-shell {
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 4px 0 0;
}

.sidebar-list {
  flex: 1;
  overflow-y: auto;
}

.sidebar-list--sectioned {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sidebar-actions {
  flex-shrink: 0;
  margin-bottom: 12px;
}

.guide-alert {
  border-radius: 12px;
}

.evidence-group-shell {
  padding: 14px;
  border-radius: 18px;
  background: #fbfcfe;
  border: 1px solid #edf2f7;
}

.evidence-group {
  margin-top: 12px;
}

.evidence-group__header {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  font-weight: 600;
  padding-bottom: 12px;
  border-bottom: 1px solid #edf2f7;

  &--guide {
    border-bottom: 1px solid #f6d58f;
    padding: 10px 12px 12px;
    border-radius: 12px;
    background: linear-gradient(180deg, #fff8e1 0%, #fffdf4 100%);
    color: #ad6800;
  }
}

.evidence-group__title {
  font-size: 13px;
  font-weight: 700;
}

.material-card {
  border-radius: 16px;
  border: 1px solid #edf2f7;
  box-shadow: none;
}

.material-card__title-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.material-card__title {
  min-width: 0;
  font-weight: 600;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.4;
}

.material-card__meta {
  margin-top: 8px;
  font-size: 12px;
  color: #667085;
  line-height: 1.6;
}

.material-card__actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}

@media (max-width: 720px) {
  .material-card__actions {
    flex-wrap: wrap;
    justify-content: flex-start;
  }
}
</style>
