<template>
  <!-- L1 求助协议(aichat 体验与 agent 能力系统化重构 §2.3,2026-06-21):断路器熔断后展示的操作卡。
       触发:后端断路器连续同类失败达阈值 → emit AiHelpRequired(已 guard.reset,loop 终止)→
       useAiEvents handleLifecycleEvent 翻 pendingHelp(模块级 ref)→ 本卡渲染。
       复用 MaxRoundsCard 模式:per-conv 守卫(pendingHelp.conversationId === active)+ 行为已记入本地 ref。
       显 reason(原因)+ context(最近错误 sample)+ options 按钮供用户选(换思路/授权路径/人工接管)。
       选 option → 仅关闭求助卡(后端 loop 已终止,用户重新发消息即"换思路/人工接管"入口,
       路径授权走 DirAuthDialog 既有链路)。机制优先 prompt 说教:代码强制熔断 + 结构化求助,
       非"教 AI 失败就问用户"(LLM 不可靠)。 -->
  <div v-if="helpActive" ref="helpRef" class="ai-help-required">
    <span class="ai-help-required-text">{{ helpActive.reason }}</span>
    <span class="ai-help-required-hint">{{ helpActive.context }}</span>
    <div class="ai-help-required-options">
      <button
        v-for="opt in helpActive.options"
        :key="opt"
        class="ai-help-required-btn"
        @click="handleSelectOption(opt)"
      >{{ opt }}</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch, nextTick } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAiStore } from '../../stores/ai'
import { pendingHelp } from '../../composables/ai/useAiEvents'

// toast 经 emit 转父(保持单一 toast 源,与 MaxRoundsCard 一致)
const emit = defineEmits<{
  (e: 'toast', payload: { msg: string; type: 'error' | 'warning' | 'info' }): void
}>()

const store = useAiStore()
const { t } = useI18n()

// 当前挂起的求助(有值即后端发过 AiHelpRequired)。pendingHelp 由 useAiEvents 翻:
// AiHelpRequired 设值;AiCompleted/AiError 清值(重新发送或错误中断后求助卡消失)。
//
// helpActive 既做守卫(挂起会话===当前展示会话)又做模板取值源:返回 PendingHelp 非空或 null,
// 模板 v-if="helpActive" 取真值后 Vue 类型收窄为非 null,可直接访问 .reason/.context/.options。
// 显示守卫:仅当挂起求助属当前展示会话时显(F-09 多会话并发不串台)。
// 注:不依赖 streaming——求助事件后端已 guard.reset(generating=false),若依赖 isGenerating
// 会导致卡片不显(对齐 MaxRoundsCard F-260620 去 streaming 依赖的根治理)。
const helpActive = computed(() => {
  const p = pendingHelp.value
  if (p && p.conversationId === store.state.activeConversationId) return p
  return null
})

// M8:卡片根 ref。断路器熔断常发生在多轮迭代后,消息流已长,求助卡被挤出视口用户看不到 → 求助无声
// 卡死。卡片显示时 scrollIntoView 让 option 按钮组立即进入视口。
const helpRef = ref<HTMLElement | null>(null)

/** M8:helpActive 从 null→非 null(求助挂起出现)时 scrollIntoView 让操作入口立即可见。
 *  仅监 truthy 翻转,不监 reason/context 变化避免已可见时反复跳。 */
watch(helpActive, async (p) => {
  if (!p) return
  await nextTick()
  helpRef.value?.scrollIntoView({ block: 'center', behavior: 'smooth' })
})

/** 选 option:关求助卡即可。后端 loop 已在 AiHelpRequired 时终止(guard.reset + return),
 *  用户选 option 后的"换思路/授权路径/人工接管"由用户重新发消息/操作触发(无独立 IPC)。
 *  点"授权路径"提示用户路径授权链路(DirAuthDialog 自动触发,无需此卡代发)。
 *  选后清 pendingHelp,卡片隐藏(对齐 MaxRoundsCard 点继续/停止后由事件清的语义,此处无续跑事件故立即清)。 */
function handleSelectOption(opt: string): void {
  void opt // option 仅区分按钮文案,后端 loop 已终止无独立 IPC 续跑,选即清卡片
  pendingHelp.value = null
  emit('toast', { msg: t('aiChat.helpRequiredAck'), type: 'info' })
}
</script>

<style scoped>
/* 复用 MaxRoundsCard 样式基调(warning 色系,求助属"需用户介入"信号,视觉一致) */
.ai-help-required {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-bottom: 6px;
  padding: 6px 8px;
  background: color-mix(in srgb, var(--df-warning) 10%, transparent);
  border: 0.5px solid color-mix(in srgb, var(--df-warning) 40%, transparent);
  border-radius: var(--df-radius);
}
.ai-help-required-text {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--df-warning);
}
.ai-help-required-hint {
  font-size: 10.5px;
  color: var(--df-text-dim);
  opacity: 0.9;
  word-break: break-all;
  /* M7:context 含错误堆栈,长栈撑高卡片。等宽字体利堆栈行对齐;max-height + overflow-y:auto
     短内容自动不显滚动条,长堆栈滚动扫看(比折叠实用,无需展开按钮)。 */
  font-family: var(--df-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
  max-height: 200px;
  overflow-y: auto;
}
.ai-help-required-options {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 2px;
}
.ai-help-required-btn {
  border: 0.5px solid color-mix(in srgb, var(--df-warning) 60%, transparent);
  background: var(--df-warning);
  color: #000;
  cursor: pointer;
  font-size: 11px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: calc(var(--df-radius) - 2px);
  transition: filter 0.15s var(--df-ease);
}
.ai-help-required-btn:hover { filter: brightness(1.1); }
</style>
