<!-- =============================================================================
// 企微IT智能服务台 — 对话区组件
// =============================================================================
// 说明：坐席工作台中间的对话区
// 功能：
//   1. 顶部 UserInfoBar（替代原标题栏，含6卡片展开详情）
//   2. 排查步骤栏（UserInfoBar 下方，始终可见）
//   3. 协作信息行
//   4. 消息列表
//   5. 底部回复输入框
// ============================================================================= -->

<template>
  <div style="height: 100%; display: flex; flex-direction: column;">
    <!-- ================================================================== -->
    <!-- 顶部：用户信息栏（替代原标题栏） -->
    <!-- ================================================================== -->
    <UserInfoBar
      ref="userInfoBarRef"
      :conversation="conversationStore.currentConversation"
      :available-agents="agentStore.availableAgents"
      :can-invite-collaborator="canInviteCollaborator"
      @assign="handleAssign"
      @resolve="handleResolve"
      @toggle-pin="handleTogglePin"
      @toggle-todo="handleToggleTodo"
      @transfer="handleTransfer"
      @invite="inviteDialogVisible = true"
    />

    <!-- ================================================================== -->
    <!-- 排查步骤栏（紧跟用户信息栏下方，始终可见） -->
    <!-- ================================================================== -->
    <TroubleshootBar />

    <!-- ================================================================== -->
    <!-- 参与者面板（有参与者时显示） -->
    <!-- ================================================================== -->
    <ParticipantBar
      v-if="hasAnyParticipants"
      :participants="currentConv?.participants || []"
      :agent-name="currentConv?.assigned_agent_name || '坐席'"
      :is-primary-agent="isPrimaryAgent"
      :collaborating-agent-ids="currentConv?.collaborating_agent_ids || []"
      :collaborating-agent-names="currentConv?.collaborating_agent_names || {}"
      @invite="showInviteParticipantDialog = true"
      @remove="handleRemoveParticipant"
    />

    <!-- ================================================================== -->
    <!-- 协作信息行（仅展示） -->
    <!-- ================================================================== -->
    <div
      v-if="collaborationInfoText"
      style="
        padding: 4px 20px;
        background: var(--bg-accent-soft);
        border-bottom: 1px solid var(--border-light);
        font-size: 12px;
        color: var(--text-secondary);
        flex-shrink: 0;
      "
    >
      {{ collaborationInfoText }}
    </div>

    <!-- ================================================================== -->
    <!-- 消息列表（flex: 1 占满剩余空间） -->
    <!-- ================================================================== -->
    <div ref="messageListRef" class="message-list-scroll">

      <!-- 加载中 -->
      <div v-if="conversationStore.loadingMessages" style="text-align: center; padding: 20px;">
        <el-icon class="is-loading" :size="20"><Loading /></el-icon>
        <div style="margin-top: 8px; color: var(--text-tertiary); font-size: 12px;">加载消息中...</div>
      </div>

      <!-- 消息列表 -->
      <template v-else>
        <MessageBubble
          v-for="msg in conversationStore.messages"
          :key="msg.id"
          :message="msg"
          @reply="handleReplyTo"
          @scroll-to-message="scrollToMessage"
        />

        <!-- 空消息 -->
        <div
          v-if="conversationStore.messages.length === 0"
          style="text-align: center; padding: 40px; color: var(--text-tertiary);"
        >
          暂无消息
        </div>
      </template>
    </div>

    <!-- ================================================================== -->
    <!-- 输入指示器（某人在输入时显示） -->
    <!-- ================================================================== -->
    <div v-if="typingText" class="typing-indicator">
      <span class="typing-dots">
        <span class="dot"></span>
        <span class="dot"></span>
        <span class="dot"></span>
      </span>
      <span class="typing-text">{{ typingText }}</span>
    </div>

    <!-- ================================================================== -->
    <!-- 回复输入框（在消息列表下方、排查步骤上方） -->
    <!-- ================================================================== -->
    <ReplyBox
      v-if="conversationStore.currentConversation?.status !== 'resolved'"
      :reply-to-message="replyToMessage"
      @send="handleSend"
      @cancel-reply="replyToMessage = null"
    />
    <!-- 已结单提示 -->
    <div
      v-else
      style="
        padding: 12px 16px;
        border-top: 1px solid var(--border-color);
        text-align: center;
        color: var(--text-tertiary);
        font-size: 13px;
        background-color: var(--bg-tertiary);
      "
    >
      该会话已结单，无法发送消息
    </div>

    <!-- 摇人弹窗 -->
    <InviteDialog
      v-model="inviteDialogVisible"
      :exclude-agent-ids="excludeAgentIds"
      @confirm="handleInvite"
    />

    <!-- 邀请员工弹窗 -->
    <InviteParticipantDialog
      v-model="showInviteParticipantDialog"
      :conversation-id="conversationStore.currentConversation?.id || ''"
      :existing-participant-ids="existingParticipantIds"
      @success="onInviteParticipantSuccess"
    />

    <!-- 结单摘要确认弹窗 -->
    <el-dialog
      v-model="summaryDialogVisible"
      title="会话摘要确认"
      width="480px"
      :close-on-click-modal="false"
    >
      <div v-if="conversationStore.loadingSummary" style="text-align: center; padding: 20px;">
        <el-icon class="is-loading" :size="20"><Loading /></el-icon>
        <div style="margin-top: 8px; color: var(--text-tertiary);">正在生成 AI 摘要...</div>
      </div>
      <div v-else>
        <p style="font-size: 13px; color: var(--text-secondary); margin-bottom: 12px;">
          以下为 AI 自动生成的会话摘要，请确认或修改后提交：
        </p>
        <el-form label-position="top" size="small">
          <el-form-item label="问题">
            <el-input v-model="summaryForm.problem" type="textarea" :rows="2" />
          </el-form-item>
          <el-form-item label="原因">
            <el-input v-model="summaryForm.cause" type="textarea" :rows="2" />
          </el-form-item>
          <el-form-item label="解决方案">
            <el-input v-model="summaryForm.solution" type="textarea" :rows="2" />
          </el-form-item>
        </el-form>
      </div>
      <template #footer>
        <el-button @click="summaryDialogVisible = false">取消结单</el-button>
        <el-button type="primary" @click="handleConfirmSummary">确认结单</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
// ============================================================================
// 导入
// ============================================================================
import { ref, computed, watch, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Loading } from '@element-plus/icons-vue'
import { useConversationStore } from '@/stores/conversation'
import { useAgentStore } from '@/stores/agent'
import { useKeyboardShortcuts } from '@/composables/useKeyboardShortcuts'
import type { Message } from '@/api/message'
import MessageBubble from './MessageBubble.vue'
import ReplyBox from './ReplyBox.vue'
import InviteDialog from '@/components/conversation/InviteDialog.vue'
import InviteParticipantDialog from '@/components/conversation/InviteParticipantDialog.vue'
import ParticipantBar from '@/components/conversation/ParticipantBar.vue'
import UserInfoBar from './UserInfoBar.vue'
import TroubleshootBar from './TroubleshootBar.vue'

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

const conversationStore = useConversationStore()
const agentStore = useAgentStore()

/** 当前会话（简化空值检查） */
const currentConv = computed(() => conversationStore.currentConversation)

/** 消息列表DOM引用（用于自动滚动） */
const messageListRef = ref<HTMLElement | null>(null)

/** UserInfoBar 组件引用 */
const userInfoBarRef = ref<InstanceType<typeof UserInfoBar> | null>(null)

/** 摇人弹窗可见性 */
const inviteDialogVisible = ref(false)

/** 邀请员工弹窗可见性 */
const showInviteParticipantDialog = ref(false)

/** 引用回复：当前正在回复的消息（null 表示普通发送） */
const replyToMessage = ref<Message | null>(null)

/** 结单摘要确认弹窗可见性 */
const summaryDialogVisible = ref(false)

/** 结单摘要表单 */
const summaryForm = ref({
  problem: '',
  cause: '',
  solution: '',
})

// ============================================================================
// 计算属性
// ============================================================================

/** 是否可以摇人（邀请协作坐席） */
const canInviteCollaborator = computed(() => {
  const conv = conversationStore.currentConversation
  if (!conv || conv.status !== 'serving') return false
  return conv.is_mine || conv.is_collaborator
})

/** 当前坐席是否为主责坐席（邀请功能权限控制） */
const isPrimaryAgent = computed(() => {
  const conv = conversationStore.currentConversation
  if (!conv) return false
  return conv.assigned_agent_id === agentStore.userId
})

/** 是否有参与者或协作坐席（决定是否显示 ParticipantBar） */
const hasAnyParticipants = computed(() => {
  const conv = conversationStore.currentConversation
  if (!conv) return false
  return (conv.participants?.length || 0) > 0 || (conv.collaborating_agent_ids?.length || 0) > 0
})

/** 排除的坐席ID列表（主责坐席 + 已在协作中的坐席 + 自己） */
const excludeAgentIds = computed(() => {
  const conv = conversationStore.currentConversation
  if (!conv) return []
  const exclude = new Set<string>()
  if (conv.assigned_agent_id) exclude.add(conv.assigned_agent_id)
  for (const aid of conv.collaborating_agent_ids || []) {
    exclude.add(aid)
  }
  exclude.add(agentStore.userId)
  return Array.from(exclude)
})

/** 协作信息文本（主责 + 协作坐席） */
const collaborationInfoText = computed(() => {
  const conv = conversationStore.currentConversation
  if (!conv || conv.status !== 'serving') return ''

  const parts: string[] = []
  if (conv.assigned_agent_name) {
    parts.push(`主责：${conv.assigned_agent_name}`)
  }
  const collabIds = conv.collaborating_agent_ids || []
  if (collabIds.length > 0) {
    const names = collabIds.map(
      aid => conv.collaborating_agent_names?.[aid] || '未知'
    )
    parts.push(`协作：${names.join('、')}`)
  }
  return parts.join(' | ')
})

/** 输入指示器文本（如 "张三正在输入..."） */
const typingText = computed(() => {
  const convId = conversationStore.currentConversationId
  if (!convId) return ''
  return conversationStore.getTypingText(convId)
})

// ============================================================================
// 快捷键
// ============================================================================

useKeyboardShortcuts({
  // AI 推荐已移至右边栏，快捷键在 AiAssistantPanel 中处理
})

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

/**
 * 接单
 */
async function handleAssign(): Promise<void> {
  if (!conversationStore.currentConversation) return
  try {
    await conversationStore.assignConv(
      conversationStore.currentConversation.id,
      agentStore.userId
    )
    ElMessage.success('接单成功')
  } catch (error) {
    console.error('接单失败:', error)
  }
}

/**
 * 结单
 * 先确认 → 生成 AI 摘要 → 弹出摘要确认对话框 → 最终结单
 */
async function handleResolve(): Promise<void> {
  if (!conversationStore.currentConversation) return
  try {
    await ElMessageBox.confirm('确定要结单吗？结单后无法继续回复。', '确认结单', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })

    const convId = conversationStore.currentConversation.id

    summaryDialogVisible.value = true

    await conversationStore.fetchSummary(convId)

    if (conversationStore.currentSummary) {
      summaryForm.value.problem = conversationStore.currentSummary.problem
      summaryForm.value.cause = conversationStore.currentSummary.cause
      summaryForm.value.solution = conversationStore.currentSummary.solution
    } else {
      summaryForm.value = { problem: '', cause: '', solution: '' }
    }
  } catch {
    // 用户取消
  }
}

/**
 * 确认摘要并完成结单
 */
async function handleConfirmSummary(): Promise<void> {
  if (!conversationStore.currentConversation) return
  try {
    await conversationStore.resolveConv(conversationStore.currentConversation.id)
    summaryDialogVisible.value = false
    ElMessage.success('已结单')
  } catch (error) {
    console.error('结单失败:', error)
  }
}

/**
 * 置顶/取消置顶
 */
async function handleTogglePin(): Promise<void> {
  if (!conversationStore.currentConversation) return
  try {
    await conversationStore.togglePinConv(conversationStore.currentConversation.id)
  } catch (error) {
    console.error('切换置顶失败:', error)
  }
}

/**
 * 代办/取消代办
 */
async function handleToggleTodo(): Promise<void> {
  if (!conversationStore.currentConversation) return
  try {
    await conversationStore.toggleTodoConv(conversationStore.currentConversation.id)
  } catch (error) {
    console.error('切换代办失败:', error)
  }
}

/**
 * 转接
 */
async function handleTransfer(targetAgentId: string): Promise<void> {
  if (!conversationStore.currentConversation) return
  try {
    await ElMessageBox.confirm('确定要转接给其他坐席吗？', '确认转接', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })
    await conversationStore.transferConv(
      conversationStore.currentConversation.id,
      targetAgentId
    )
    ElMessage.success('转接成功')
  } catch {
    // 用户取消
  }
}

/**
 * 摇人（邀请协作坐席）
 */
async function handleInvite(agentId: string): Promise<void> {
  if (!conversationStore.currentConversation) return
  try {
    await conversationStore.inviteToConversation(
      conversationStore.currentConversation.id,
      agentId
    )
    inviteDialogVisible.value = false
    ElMessage.success('已发送摇人邀请')
  } catch (error: any) {
    ElMessage.error(error?.message || '摇人失败')
  }
}

/** 已在参与者列表中的ID（排除，避免重复邀请） */
const existingParticipantIds = computed(() => {
  const conv = conversationStore.currentConversation
  if (!conv) return []
  const ids: string[] = [conv.employee_id]
  conv.participants?.forEach(p => ids.push(p.id))
  return ids
})

/** 邀请员工成功回调 */
function onInviteParticipantSuccess(): void {
  conversationStore.fetchConversations()
}

/** 移除参与者 */
async function handleRemoveParticipant(userId: string): Promise<void> {
  if (!conversationStore.currentConversation) return
  try {
    await ElMessageBox.confirm('确定移除该参与者？', '移除确认', {
      type: 'warning',
    })
    await conversationStore.removeParticipantFromConv(
      conversationStore.currentConversation.id,
      userId
    )
    ElMessage.success('已移除参与者')
  } catch {
    // 用户取消
  }
}

/**
 * 处理消息回复（点击消息气泡上的回复按钮）
 * 做什么：设置 replyToMessage，在输入框上方显示引用摘要
 */
function handleReplyTo(message: Message): void {
  replyToMessage.value = message
}

/**
 * 发送消息（含引用回复）
 * 如果 replyToMessage 不为空，在发送时附带 reply_to_id
 */
async function handleSend(content: string): Promise<void> {
  const replyToId = replyToMessage.value?.id || undefined
  await conversationStore.sendReply(content, replyToId)
  // 发送成功后清除引用回复
  replyToMessage.value = null
}

/**
 * 滚动到指定消息（点击引用回复摘要时触发）
 */
function scrollToMessage(messageId: string): void {
  const msgIndex = conversationStore.messages.findIndex(m => m.id === messageId)
  if (msgIndex >= 0 && messageListRef.value) {
    const messageEls = messageListRef.value.querySelectorAll('.message-row')
    const targetEl = messageEls[msgIndex] as HTMLElement
    if (targetEl) {
      targetEl.scrollIntoView({ behavior: 'smooth', block: 'center' })
      targetEl.style.transition = 'background 0.3s'
      targetEl.style.background = 'var(--accent-soft)'
      setTimeout(() => {
        targetEl.style.background = ''
      }, 1500)
    }
  }
}

/**
 * 自动滚动到底部
 */
function scrollToBottom(): void {
  nextTick(() => {
    if (messageListRef.value) {
      messageListRef.value.scrollTop = messageListRef.value.scrollHeight
    }
  })
}

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

// 消息变化时自动滚动到底部
watch(
  () => conversationStore.messages.length,
  () => {
    scrollToBottom()
  }
)

// 切换会话时自动滚动到底部 + 重置 UserInfoBar
watch(
  () => conversationStore.currentConversationId,
  () => {
    scrollToBottom()
    agentStore.loadAvailableAgents()
    // 重置 UserInfoBar 的展开状态
    userInfoBarRef.value?.resetForNewConversation()
  }
)
</script>

<style scoped>
/* 组件样式在 global.css 中定义 */

/* 输入指示器样式 */
.typing-indicator {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 16px;
  font-size: 12px;
  color: var(--text-tertiary);
  background: var(--bg-primary);
  flex-shrink: 0;
  min-height: 24px;
}

.typing-dots {
  display: inline-flex;
  gap: 2px;
  align-items: center;
}

.typing-dots .dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--text-tertiary);
  animation: typing-bounce 1.4s infinite ease-in-out both;
}

.typing-dots .dot:nth-child(1) { animation-delay: 0s; }
.typing-dots .dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dots .dot:nth-child(3) { animation-delay: 0.4s; }

@keyframes typing-bounce {
  0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
  40% { transform: scale(1); opacity: 1; }
}

.typing-text {
  font-style: italic;
}
</style>
