<template>
  <div
    v-if="mode"
    class="sticky-mode-header"
    :class="`sticky-mode-header--${mode}`"
    role="status"
    aria-live="polite"
  >
    <span class="sticky-mode-header__badge">{{ modeLabel }}</span>
    <span
      v-if="taskText"
      class="sticky-mode-header__task"
      :title="taskText"
    >{{ taskText }}</span>
    <ul class="sticky-mode-header__avatars">
      <li
        v-for="expert in visibleExperts"
        :key="expert.key"
        class="sticky-mode-header__avatar-item"
      >
        <a-popover
          trigger="click"
          placement="bottom"
          :open="openKey === expert.key"
          :overlay-class-name="`sticky-mode-header__popover sticky-mode-header__popover--${mode}`"
          @open-change="(open) => handleOpenChange(expert.key, open)"
        >
          <template #content>
            <div class="expert-detail">
              <div class="expert-detail__name">{{ expert.name }}</div>
              <div v-if="expert.description" class="expert-detail__desc">{{ expert.description }}</div>
              <div v-if="expert.persona" class="expert-detail__persona">{{ expert.persona }}</div>
            </div>
          </template>
          <button
            :ref="(el) => setTriggerRef(expert.key, el)"
            class="sticky-mode-header__avatar"
            :class="{ 'sticky-mode-header__avatar--lead': expert.isLead }"
            type="button"
            :style="{ background: expert.color, color: 'var(--text-inverse)', borderColor: expert.color }"
            :aria-label="`查看 ${expert.name} 详情`"
            :aria-expanded="openKey === expert.key"
          >
            <span class="sticky-mode-header__avatar-emoji">{{ expert.avatar }}</span>
          </button>
        </a-popover>
      </li>
      <li v-if="overflowCount > 0" class="sticky-mode-header__avatar-item">
        <a-popover
          trigger="click"
          placement="bottom"
          :open="openKey === OVERFLOW_KEY"
          overlay-class-name="sticky-mode-header__popover sticky-mode-header__popover--overflow"
          @open-change="(open) => handleOpenChange(OVERFLOW_KEY, open)"
        >
          <template #content>
            <ul class="expert-list">
              <li
                v-for="expert in overflowExperts"
                :key="expert.key"
                class="expert-list__item"
              >
                <span
                  class="expert-list__avatar"
                  :style="{ background: expert.color, color: 'var(--text-inverse)', borderColor: expert.color }"
                >{{ expert.avatar }}</span>
                <span class="expert-list__name">{{ expert.name }}</span>
                <span v-if="expert.isLead" class="expert-list__tag">Lead</span>
              </li>
            </ul>
          </template>
          <button
            :ref="(el) => setTriggerRef(OVERFLOW_KEY, el)"
            class="sticky-mode-header__avatar sticky-mode-header__avatar--overflow"
            type="button"
            :aria-label="`还有 ${overflowCount} 位专家`"
            :aria-expanded="openKey === OVERFLOW_KEY"
          >
            +{{ overflowCount }}
          </button>
        </a-popover>
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
import { computed, nextTick, ref } from 'vue'
import { Popover as APopover } from 'ant-design-vue'
import { useTeamStore } from '@/stores/team'
import { useChatStore } from '@/stores/chatStore'
import type { IBoardExpert, IExpertInfo, ITeamPlanPhase } from '@/api/types'

const teamStore = useTeamStore()
const chatStore = useChatStore()

/** 统一的专家展示数据（team / board 两种来源合并为同一形态） */
interface IExpertDisplay {
  key: string
  name: string
  avatar: string
  color: string
  persona: string
  description?: string
  isLead?: boolean
}

const MAX_VISIBLE = 5
const OVERFLOW_KEY = '__overflow__'

type Mode = 'team' | 'board' | null

const mode = computed<Mode>(() => {
  if (teamStore.isTeamMode) return 'team'
  if (chatStore.boardState && chatStore.boardState.status !== 'dissolved') return 'board'
  return null
})

const modeLabel = computed(() => {
  if (mode.value === 'team') return '专家团'
  if (mode.value === 'board') return '私董会'
  return ''
})

const taskText = computed(() => {
  if (mode.value === 'team') {
    // 优先团队级 task_description；回退到首个进行中阶段的 task_description 或 name
    const state = teamStore.teamState
    if (state?.task_description) return state.task_description
    const phase =
      state?.plan_phases?.find((p: ITeamPlanPhase) => p.status === 'in_progress') ??
      state?.plan_phases?.[0]
    return phase?.task_description ?? phase?.name ?? ''
  }
  if (mode.value === 'board') {
    return chatStore.boardState?.topic ?? ''
  }
  return ''
})

const allExperts = computed<IExpertDisplay[]>(() => {
  if (mode.value === 'team') {
    return teamStore.activeExperts.map((e: IExpertInfo) => ({
      key: e.id,
      name: e.name,
      avatar: e.avatar,
      color: e.color,
      persona: e.persona,
      description:
        e.bound_skills.length > 0 ? `技能: ${e.bound_skills.join(', ')}` : undefined,
      isLead: e.is_lead,
    }))
  }
  if (mode.value === 'board') {
    const list = chatStore.boardState?.experts ?? []
    // 颜色一致性：优先使用当前会话 messages 中最近的 board_speech/
    // round_summary 的 expert_color（与 MessageShell 头像同源），保证
    // 顶部卡片头像与对话头像颜色严格匹配；缺失时回退到 boardState
    // 中保存的 YAML color。
    const liveColorByName = new Map<string, string>()
    const liveAvatarByName = new Map<string, string>()
    const conv = chatStore.conversations?.find(
      (c: { id: string; messages?: unknown[] }) => c.id === chatStore.currentConversationId,
    )
    if (conv?.messages) {
      // walk from latest to earliest to capture the most recent identity
      for (let i = conv.messages.length - 1; i >= 0; i--) {
        const m = conv.messages[i] as {
          message_type?: string
          expert_name?: string
          expert_color?: string
          expert_avatar?: string
        }
        if (
          (m.message_type === 'board_speech' ||
            m.message_type === 'board_summary') &&
          m.expert_name &&
          !liveColorByName.has(m.expert_name)
        ) {
          if (m.expert_color) liveColorByName.set(m.expert_name, m.expert_color)
          if (m.expert_avatar) liveAvatarByName.set(m.expert_name, m.expert_avatar)
        }
      }
    }
    return list.map((e: IBoardExpert, idx: number) => ({
      key: `${e.name}-${idx}`,
      name: e.name,
      avatar: liveAvatarByName.get(e.name) ?? e.avatar,
      color: liveColorByName.get(e.name) ?? e.color,
      persona: e.persona,
      description: e.is_moderator ? '主持人' : undefined,
      isLead: false,
    }))
  }
  return []
})

const visibleExperts = computed(() => allExperts.value.slice(0, MAX_VISIBLE))
const overflowExperts = computed(() => allExperts.value.slice(MAX_VISIBLE))
const overflowCount = computed(() => overflowExperts.value.length)

// ── Popover 焦点管理 ──────────────────────────────────────────────
// a-popover trigger="click" 默认支持 Esc / 外击关闭，但关闭后焦点回归 body。
// 记录触发元素引用，关闭时手动 focus 回触发头像，恢复键盘浏览连续性。
const openKey = ref<string | null>(null)
const triggerEls = new Map<string, HTMLButtonElement>()

function setTriggerRef(key: string, el: unknown): void {
  // 函数式 ref：原生 <button> 传入 HTMLButtonElement | null
  const dom = (el && typeof el === 'object' && '$el' in el
    ? (el as { $el?: HTMLButtonElement }).$el
    : (el as HTMLButtonElement | null)) ?? null
  if (dom) {
    triggerEls.set(key, dom)
  } else {
    triggerEls.delete(key)
  }
}

function handleOpenChange(key: string, open: boolean): void {
  if (open) {
    openKey.value = key
    return
  }
  if (openKey.value === key) {
    openKey.value = null
    const el = triggerEls.get(key)
    if (el) {
      void nextTick(() => el.focus())
    }
  }
}
</script>

<style scoped>
.sticky-mode-header {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border-color);
  box-shadow: var(--shadow-sm);
}

.sticky-mode-header--team {
  border-top: 2px solid var(--accent-team);
}

.sticky-mode-header--board {
  border-top: 2px solid var(--accent-board);
}

.sticky-mode-header__badge {
  flex-shrink: 0;
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--font-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--text-inverse);
  letter-spacing: 0.5px;
}

.sticky-mode-header--team .sticky-mode-header__badge {
  background: var(--accent-team);
}

.sticky-mode-header--board .sticky-mode-header__badge {
  background: var(--accent-board);
}

.sticky-mode-header__task {
  flex: 1;
  min-width: 0;
  font-size: var(--font-sm);
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sticky-mode-header__avatars {
  list-style: none;
  display: flex;
  align-items: center;
  gap: calc(-1 * var(--space-1));
  margin: 0;
  padding: 0 var(--space-1) 0 0;
  flex-shrink: 0;
}

.sticky-mode-header__avatar-item {
  display: flex;
}

.sticky-mode-header__avatar {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-full);
  border: 2px solid var(--border-color);
  background: var(--bg-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  transition:
    transform var(--transition-fast),
    box-shadow var(--transition-fast);
}

.sticky-mode-header__avatar:hover,
.sticky-mode-header__avatar:focus-visible {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
  outline: none;
}

.sticky-mode-header__avatar--lead {
  border-width: 3px;
}

.sticky-mode-header__avatar-emoji {
  font-size: 14px;
  line-height: 1;
}

.sticky-mode-header__avatar--overflow {
  font-size: var(--font-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--text-secondary);
  background: var(--bg-tertiary);
}

/* Popover 内容（非 scoped，由 overlay-class-name 挂载到 body） */
:global(.sticky-mode-header__popover) {
  max-width: 320px;
}

:global(.sticky-mode-header__popover .ant-popover-inner-content) {
  padding: var(--space-3);
}

.expert-detail {
  max-width: 280px;
}

.expert-detail__name {
  font-size: var(--font-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  margin-bottom: var(--space-1);
}

.expert-detail__desc {
  font-size: var(--font-xs);
  color: var(--text-tertiary);
  margin-bottom: var(--space-1);
}

.expert-detail__persona {
  font-size: var(--font-xs);
  color: var(--text-secondary);
  line-height: var(--leading-normal);
}

.expert-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 260px;
  max-height: 280px;
  overflow-y: auto;
}

.expert-list__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) 0;
}

.expert-list__avatar {
  width: 22px;
  height: 22px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border-color);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  flex-shrink: 0;
}

.expert-list__name {
  font-size: var(--font-sm);
  color: var(--text-primary);
}

.expert-list__tag {
  margin-left: auto;
  padding: 0 var(--space-1);
  font-size: 10px;
  background: var(--accent-team);
  color: var(--text-inverse);
  border-radius: var(--radius-sm);
}

/* 移动端：viewport<768px 隐藏任务主题文本 */
@media (max-width: 767px) {
  .sticky-mode-header {
    gap: var(--space-2);
    padding: var(--space-2);
  }

  .sticky-mode-header__task {
    display: none;
  }
}
</style>
