<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import { NCard, NTag, NSkeleton, NInput, NEmpty, NButton, NIcon } from 'naive-ui'
import { ChevronDownOutline, ChevronForwardOutline } from '@vicons/ionicons5'
import { api } from '../../api/client'
import { trackAction } from '../../composables/useAnalytics'

const router = useRouter()

interface TagItem {
  id: string
  name_zh: string
  name_en: string | null
  path: string
  level: number
  parent_id: string | null
  article_count: number
  is_selectable: boolean
}

interface TreeNode extends TagItem {
  children: TreeNode[]
  expanded: boolean
}

const allTags = ref<TagItem[]>([])
const loading = ref(true)
const search = ref('')
const selectedTagId = ref<string | null>(null)
const selectedTagName = ref('')
const articles = ref<any[]>([])
const articlesLoading = ref(false)
const articleTotal = ref(0)
const articlePage = ref(1)
const expandedIds = ref<Set<string>>(new Set())

// ── Build tree from flat list ──
const tagTree = computed(() => {
  const map = new Map<string, TreeNode>()
  const roots: TreeNode[] = []
  const exp = expandedIds.value

  // Create nodes
  for (const t of allTags.value) {
    map.set(t.id, { ...t, children: [], expanded: exp.has(t.id) })
  }

  // Link children
  for (const node of map.values()) {
    if (node.parent_id && map.has(node.parent_id)) {
      map.get(node.parent_id)!.children.push(node)
    } else if (node.level === 1) {
      roots.push(node)
    }
  }

  sortTree(roots)
  return roots
})

function sortTree(nodes: TreeNode[]) {
  nodes.sort((a, b) => (b.article_count - a.article_count) || ((a.name_zh || a.name_en || '').localeCompare(b.name_zh || b.name_en || '')))
}

// ── Toggle expand (reactive: replaces the Set to trigger Vue update) ──
function toggleExpand(node: TreeNode) {
  const next = new Set(expandedIds.value)
  if (next.has(node.id)) {
    next.delete(node.id)
  } else {
    next.add(node.id)
  }
  expandedIds.value = next
}

// Default: level 1 sort_order 暂不可用，改为按 article_count 降序
// 在 sortTree 中已处理

// ── Search filtering ──
const filteredTree = computed(() => {
  if (!search.value) return tagTree.value
  const q = search.value.toLowerCase()
  const match = new Set<string>()

  function walk(nodes: TreeNode[]): TreeNode[] {
    return nodes.filter(n => {
      const selfMatch = n.name_zh.toLowerCase().includes(q) || (n.name_en ?? '').toLowerCase().includes(q)
      const filteredChildren = walk(n.children)
      if (selfMatch || filteredChildren.length > 0) {
        match.add(n.id)
        if (filteredChildren.length > 0) n.children = filteredChildren
        n.expanded = true
        return true
      }
      return false
    })
  }

  return walk(cloneTree(tagTree.value))
})

function cloneTree(nodes: TreeNode[]): TreeNode[] {
  return nodes.map(n => ({ ...n, children: cloneTree(n.children) }))
}

// ── Load articles by tag ──
async function selectTag(tag: TagItem) {
  if (!tag.is_selectable) {
    // Also expand the tree for grouping tags
    const node = findNode(tagTree.value, tag.id)
    if (node) toggleExpand(node)
  }
  selectedTagId.value = tag.id
  selectedTagName.value = tag.name_zh || tag.name_en || ''
  articlePage.value = 1
  await loadArticles()
  trackAction('browse_cancer', 'cancer_tag', tag.id)
}

function findNode(nodes: TreeNode[], id: string): TreeNode | null {
  for (const n of nodes) {
    if (n.id === id) return n
    const found = findNode(n.children, id)
    if (found) return found
  }
  return null
}

async function loadArticles() {
  if (!selectedTagId.value) return

  articlesLoading.value = true
  try {
    const { data } = await api.get('/public/feed', {
      params: { tag: selectedTagId.value, page: articlePage.value, page_size: 10 }
    })
    articles.value = data.items || []
    articleTotal.value = data.total || 0
  } catch {
    articles.value = []
    articleTotal.value = 0
  } finally {
    articlesLoading.value = false
  }
}

// ── Helpers ──
function treeCount(node: TreeNode): number {
  if (!node.children.length) return node.article_count
  let total = 0
  for (const c of node.children) total += treeCount(c)
  return total
}

onMounted(async () => {
  try {
    const { data } = await api.get('/public/cancer-tags')
    allTags.value = data.tags || []
  } catch {
    allTags.value = []
  } finally {
    loading.value = false
  }
})
</script>

<template>
  <div style="max-width:1200px;margin:0 auto;padding:32px 24px">
    <div style="text-align:center;margin-bottom:32px">
      <h1 style="font-size:28px;margin-bottom:8px">🔬 癌种浏览</h1>
      <p style="color:var(--text-secondary)">按肿瘤部位/类型浏览文献 · 点击标签查看相关文献</p>
    </div>

    <div style="display:flex;gap:24px;flex-wrap:wrap">
      <!-- 左侧标签树 -->
      <div style="flex:1;min-width:280px;max-width:360px">
        <NInput v-model:value="search" placeholder="搜索癌种..." size="small" style="margin-bottom:12px" clearable />
        <NSkeleton v-if="loading" text :repeat="10" />

        <div v-else-if="!filteredTree.length" style="text-align:center;padding:40px 0;color:var(--text-muted);font-size:14px">
          未找到匹配癌种
        </div>

        <div v-else class="tag-tree">
          <template v-for="node in filteredTree" :key="node.id">
            <!-- Level 1: category header -->
            <div class="tree-l1" @click="toggleExpand(node)" :style="{ cursor: 'pointer' }">
              <div style="display:flex;align-items:center;gap:4px;flex:1">
                <NIcon size="14" style="color:var(--text-muted)">
                  <ChevronDownOutline v-if="node.expanded" />
                  <ChevronForwardOutline v-else />
                </NIcon>
                <span style="font-weight:600;font-size:15px">{{ node.name_zh || node.name_en }}</span>
                <NTag size="tiny" :bordered="false" style="margin-left:auto">{{ treeCount(node) }}</NTag>
              </div>
            </div>

            <!-- Children -->
            <template v-if="node.expanded">
              <div v-for="child in node.children" :key="child.id"
                   class="tree-child"
                   :class="{ 'tree-child-active': selectedTagId === child.id }"
                   @click="selectTag(child)">
                <div style="display:flex;align-items:center;justify-content:space-between;width:100%">
                  <span style="font-size:13px;font-weight:500">
                    {{ child.name_zh || child.name_en }}
                  </span>
                  <span class="count-badge">{{ treeCount(child) }}</span>
                </div>

                <!-- Grandchildren -->
                <div v-if="child.children.length" style="margin-top:4px;margin-left:12px">
                  <div v-for="gc in child.children" :key="gc.id"
                       class="tree-grandchild"
                       :class="{ 'tree-child-active': selectedTagId === gc.id }"
                       @click.stop="selectTag(gc)">
                    <span style="font-size:12px;flex:1">{{ gc.name_zh || gc.name_en }}</span>
                    <span class="count-badge-sm">{{ gc.article_count }}</span>
                  </div>
                </div>
              </div>
            </template>
          </template>
        </div>
      </div>

      <!-- 右侧文献列表 -->
      <div style="flex:2;min-width:400px">
        <div v-if="loading" style="padding:40px">
          <NSkeleton text :repeat="6" />
        </div>
        <div v-else-if="!selectedTagId" style="text-align:center;padding:80px 0;color:var(--text-muted)">
          <div style="font-size:48px;margin-bottom:12px">🔬</div>
          <div style="font-size:14px">选择左侧癌种查看相关文献</div>
        </div>
        <div v-else>
          <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px">
            <h3 style="margin:0">{{ selectedTagName }}</h3>
            <span style="font-size:13px;color:var(--text-muted)">{{ articleTotal }} 篇文献</span>
          </div>
          <NSkeleton v-if="articlesLoading" text :repeat="5" />
          <NEmpty v-else-if="!articles.length" description="暂无文献" style="padding:60px 0" />
          <template v-else>
            <NCard v-for="item in articles" :key="item.pmid" size="small" class="article-card"
                    @click="router.push(`/literature/${item.pmid}`)">
              <div style="font-size:14px;font-weight:500">{{ item.title }}</div>
              <div style="font-size:12px;color:var(--text-muted);margin-top:4px;display:flex;gap:4px;flex-wrap:wrap">
                <span>{{ item.journal }}</span>
                <span v-if="item.first_author">· {{ item.first_author }} et al.</span>
                <span v-if="item.pub_date">· {{ item.pub_date.slice(0, 10) }}</span>
                <NTag v-for="t in (item.tags||[]).slice(0,3)" :key="t.id" size="tiny" style="margin-left:2px">{{ t.name_zh || t.name_en }}</NTag>
              </div>
            </NCard>

            <!-- Pagination -->
            <div v-if="articleTotal > 10" style="text-align:center;margin-top:12px;display:flex;justify-content:center;align-items:center;gap:12px">
              <NButton size="tiny" text :disabled="articlePage <= 1" @click="articlePage--; loadArticles()">上一页</NButton>
              <span style="font-size:12px;color:var(--text-muted)">{{ articlePage }} / {{ Math.ceil(articleTotal / 10) }}</span>
              <NButton size="tiny" text :disabled="articlePage * 10 >= articleTotal" @click="articlePage++; loadArticles()">下一页</NButton>
            </div>
          </template>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.tag-tree {
  border: 1px solid var(--border-color);
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg-card);
}

.tree-l1 {
  display: flex;
  align-items: center;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border-color);
  background: var(--bg-hover);
  transition: background .15s;
}
.tree-l1:hover { background: var(--bg-hover); }

.tree-child {
  display: flex;
  flex-direction: column;
  padding: 7px 12px 7px 32px;
  cursor: pointer;
  border-bottom: 1px solid var(--border-color);
  transition: background .15s;
}
.tree-child:hover { background: var(--bg-hover); }
.tree-child-active {
  background: var(--kw-pill-bg, #1a2a4a) !important;
  border-left: 3px solid var(--kw-pill-color, #1a5276);
}

.tree-grandchild {
  display: flex;
  align-items: center;
  padding: 4px 8px;
  border-radius: 4px;
  cursor: pointer;
  transition: background .15s;
}
.tree-grandchild:hover { background: var(--bg-hover); }

.count-badge {
  font-size: 12px;
  font-weight: 600;
  color: var(--kw-pill-color, #1a5276);
}
.count-badge-sm {
  font-size: 11px;
  font-weight: 600;
  color: var(--kw-pill-color, #1a5276);
}

.article-card {
  margin-bottom: 4px;
  cursor: pointer;
  transition: box-shadow .15s;
}
.article-card:hover { box-shadow: 0 1px 6px var(--shadow); }

@media (max-width: 768px) {
  div[style*="flex:2;min-width:400px"] { min-width: 100% !important; }
  div[style*="flex:1;min-width:280px;max-width:360px"] { max-width: 100% !important; }
}
</style>
