<!-- =============================================================================
// 企微IT智能服务台 — 邀请员工/部门加入会话弹窗组件
// =============================================================================
// 说明：主责坐席点击「邀请」后弹出，选择要邀请的员工或部门
// 功能：
//   1. 搜索框：按姓名/工号模糊搜索员工
//   2. 已选列表：显示已选中的被邀请人
//   3. 历史共享模式选择：最近10条/全部/不共享
//   4. 确认邀请：发送企微卡片通知给被邀请人
// 区别：和「摇人」不同，摇人选的是坐席，这里选的是员工/部门
// ============================================================================= -->

<template>
  <el-dialog
    v-model="visible"
    title="📋 邀请 — 邀请员工/部门加入会话"
    width="520px"
    :close-on-click-modal="false"
    destroy-on-close
  >
    <!-- 搜索框 -->
    <el-input
      v-model="searchText"
      placeholder="搜索员工姓名或工号..."
      prefix-icon="Search"
      clearable
      style="margin-bottom: 12px;"
      @keyup.enter="handleSearch"
    />

    <!-- 搜索结果 / 手动输入 -->
    <div class="search-area">
      <div v-if="searchResults.length === 0 && searchText" class="empty-hint">
        未找到匹配的员工，可直接输入添加
      </div>
      <div v-if="searchResults.length === 0 && !searchText" class="empty-hint">
        请输入姓名或工号搜索，或直接手动添加
      </div>
      <div
        v-for="person in searchResults"
        :key="person.id"
        class="person-item"
        :class="{ selected: isSelected(person.id) }"
        @click="toggleSelect(person)"
      >
        <div class="person-avatar">
          <img
            v-if="person.avatar"
            :src="person.avatar"
            :alt="person.name"
            class="avatar-img"
            @error="onAvatarError($event)"
          />
          <span v-else class="avatar-letter">{{ getAvatar(person.name) }}</span>
        </div>
        <div class="person-info">
          <div class="person-name">{{ person.name }}</div>
          <div class="person-dept">{{ person.department || '未知部门' }}</div>
        </div>
        <el-icon v-if="isSelected(person.id)" class="check-icon" color="var(--accent)">
          <Check />
        </el-icon>
      </div>

      <!-- 手动添加 -->
      <div class="manual-add" v-if="searchText && searchResults.length === 0">
        <el-button type="primary" link @click="addManualPerson">
          <el-icon><Plus /></el-icon>
          手动添加「{{ searchText }}」
        </el-button>
      </div>
    </div>

    <!-- 已选列表 -->
    <div class="selected-area" v-if="selectedPeople.length > 0">
      <div class="selected-header">
        <span>已选 {{ selectedPeople.length }} 人</span>
        <el-button type="primary" link size="small" @click="selectedPeople = []">清空</el-button>
      </div>
      <div class="selected-tags">
        <el-tag
          v-for="p in selectedPeople"
          :key="p.id"
          closable
          effect="plain"
          @close="removeSelected(p.id)"
        >
          {{ p.name }}{{ p.department ? `(${p.department})` : '' }}
        </el-tag>
      </div>
    </div>

    <!-- 历史共享模式 -->
    <div class="history-mode">
      <span class="history-label">历史消息共享：</span>
      <el-radio-group v-model="historyMode" size="small">
        <el-radio-button value="recent10">最近10条</el-radio-button>
        <el-radio-button value="all">全部</el-radio-button>
        <el-radio-button value="none">不共享</el-radio-button>
      </el-radio-group>
    </div>

    <!-- 底部按钮 -->
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="visible = false">取消</el-button>
        <el-button
          type="primary"
          :disabled="selectedPeople.length === 0"
          :loading="submitting"
          @click="handleConfirm"
        >
          确认邀请（{{ selectedPeople.length }}人）
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
// ============================================================================
// 导入
// ============================================================================
import { ref, watch } from 'vue'
import { Check, Plus } from '@element-plus/icons-vue'
import { inviteParticipant } from '@/api/conversation'
import type { ParticipantInfo } from '@/api/conversation'
import { ElMessage } from 'element-plus'

// ============================================================================
// Props & Emits
// ============================================================================

interface Props {
  /** 弹窗是否可见（由父组件通过 v-model 控制） */
  modelValue: boolean
  /** 当前会话ID */
  conversationId: string
  /** 已在参与者列表中的ID（排除，避免重复邀请） */
  existingParticipantIds?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  existingParticipantIds: () => [],
})

const emit = defineEmits<{
  'update:modelValue': [value: boolean]
  'success': [conversation: any]
}>()

// ============================================================================
// 状态
// ============================================================================

/** 弹窗可见性 */
const visible = ref(props.modelValue)

/** 搜索关键词 */
const searchText = ref('')

/** 搜索结果（Mock 数据，阶段二对接企微通讯录API后替换） */
const searchResults = ref<ParticipantInfo[]>([])

/** 已选人员列表 */
const selectedPeople = ref<ParticipantInfo[]>([])

/** 历史共享模式 */
const historyMode = ref<'recent10' | 'all' | 'none'>('recent10')

/** 是否正在提交 */
const submitting = ref(false)

// ============================================================================
// Mock 员工数据（阶段二对接企微通讯录API后替换）
// ============================================================================

const mockEmployees: ParticipantInfo[] = [
  { id: 'zhangsan', name: '张三', department: '研发一部', type: 'employee', avatar: '' },
  { id: 'lisi', name: '李四', department: '市场部', type: 'employee', avatar: '' },
  { id: 'wangwu', name: '王五', department: '运维部', type: 'employee', avatar: '' },
  { id: 'zhaoliu', name: '赵六', department: '人力资源部', type: 'employee', avatar: '' },
  { id: 'qianqi', name: '钱七', department: '财务部', type: 'employee', avatar: '' },
  { id: 'sunba', name: '孙八', department: '产品部', type: 'employee', avatar: '' },
  { id: 'zhoujiu', name: '周九', department: '行政部', type: 'employee', avatar: '' },
  { id: 'wushi', name: '吴十', department: '法务部', type: 'employee', avatar: '' },
]

// ============================================================================
// 监听
// ============================================================================

watch(() => props.modelValue, (val) => {
  visible.value = val
  if (val) {
    // 打开弹窗时重置
    searchText.value = ''
    searchResults.value = []
    selectedPeople.value = []
    historyMode.value = 'recent10'
  }
})

watch(visible, (val) => {
  emit('update:modelValue', val)
})

// ============================================================================
// 方法
// ============================================================================

/** 头像文字（取姓名最后一个字） */
function getAvatar(name: string): string {
  if (!name) return '?'
  return name.charAt(name.length - 1)
}

/** 头像加载失败时隐藏 img，降级显示首字母 */
function onAvatarError(event: Event): void {
  const img = event.target as HTMLImageElement
  img.style.display = 'none'
}

/** 搜索员工（阶段一用 Mock 数据，阶段二替换为企微通讯录API） */
function handleSearch(): void {
  const keyword = searchText.value.trim().toLowerCase()
  if (!keyword) {
    searchResults.value = []
    return
  }
  // Mock: 按姓名/工号模糊匹配
  const existingSet = new Set(props.existingParticipantIds)
  searchResults.value = mockEmployees.filter(
    e => !existingSet.has(e.id) &&
    (e.name.toLowerCase().includes(keyword) || e.id.toLowerCase().includes(keyword))
  )
}

/** 判断是否已选中 */
function isSelected(id: string): boolean {
  return selectedPeople.value.some(p => p.id === id)
}

/** 切换选中状态 */
function toggleSelect(person: ParticipantInfo): void {
  const idx = selectedPeople.value.findIndex(p => p.id === person.id)
  if (idx >= 0) {
    selectedPeople.value.splice(idx, 1)
  } else {
    selectedPeople.value.push(person)
  }
}

/** 从已选列表移除 */
function removeSelected(id: string): void {
  const idx = selectedPeople.value.findIndex(p => p.id === id)
  if (idx >= 0) {
    selectedPeople.value.splice(idx, 1)
  }
}

/** 手动添加搜索不到的员工 */
function addManualPerson(): void {
  const name = searchText.value.trim()
  if (!name) return
  // 用搜索词作为姓名和ID
  const person: ParticipantInfo = {
    id: `manual_${Date.now()}`,
    name,
    department: '',
    type: 'employee',
  }
  if (!isSelected(person.id)) {
    selectedPeople.value.push(person)
  }
  searchText.value = ''
  searchResults.value = []
}

/** 确认邀请 */
async function handleConfirm(): Promise<void> {
  if (selectedPeople.value.length === 0) return

  submitting.value = true
  try {
    const result = await inviteParticipant(props.conversationId, {
      participants: selectedPeople.value.map(p => ({
        id: p.id,
        name: p.name,
        department: p.department,
        type: p.type,
      })),
      history_mode: historyMode.value,
    })

    ElMessage.success(`已邀请 ${selectedPeople.value.length} 人加入会话`)
    emit('success', result)
    visible.value = false
  } catch (err: any) {
    const msg = err?.response?.data?.message || err?.message || '邀请失败'
    ElMessage.error(msg)
  } finally {
    submitting.value = false
  }
}
</script>

<style scoped>
.search-area {
  max-height: 200px;
  overflow-y: auto;
  border: 1px solid var(--border-light);
  border-radius: 6px;
  margin-bottom: 12px;
}

.person-item {
  display: flex;
  align-items: center;
  padding: 10px 12px;
  cursor: pointer;
  border-bottom: 1px solid var(--border-light);
  transition: background 0.15s;
}

.person-item:last-child {
  border-bottom: none;
}

.person-item:hover {
  background: var(--bg-tertiary);
}

.person-item.selected {
  background: var(--accent-soft);
}

.person-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--bg-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 600;
  flex-shrink: 0;
  margin-right: 10px;
  overflow: hidden;
  position: relative;
}

.person-avatar .avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  position: absolute;
  top: 0;
  left: 0;
}

.person-avatar .avatar-letter {
  color: #fff;
  line-height: 1;
}

.person-info {
  flex: 1;
  min-width: 0;
}

.person-name {
  font-size: 14px;
  font-weight: 500;
}

.person-dept {
  font-size: 12px;
  color: var(--text-tertiary);
  margin-top: 2px;
}

.check-icon {
  font-size: 18px;
  flex-shrink: 0;
}

.empty-hint {
  padding: 20px;
  text-align: center;
  color: var(--text-tertiary);
  font-size: 13px;
}

.manual-add {
  padding: 8px 12px;
  border-top: 1px dashed var(--border-light);
}

.selected-area {
  margin-bottom: 12px;
  padding: 10px;
  border: 1px solid var(--border-light);
  border-radius: 6px;
  background: var(--bg-tertiary);
}

.selected-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
  font-size: 13px;
  color: var(--text-secondary);
}

.selected-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.history-mode {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.history-label {
  font-size: 13px;
  color: var(--text-secondary);
  white-space: nowrap;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
</style>
