/**
 * ToolCard 审批状态机 — 从 ToolCard.vue 抽离的审批 UI 逻辑。
 *
 * 职责:审批按钮 loading 态、审批挂起时长显示(BUG-260624-02)、
 * 审批超时兜底 toast(UX-260617-14)、approve/reject/path_auth 三选项处理、
 * status 变化自动复位 + pending 计时。
 *
 * 不含 store IPC 调用(useAiApproval 负责)和模板渲染——纯状态管理。
 */
import { ref, reactive, computed, watch, onBeforeUnmount, type Ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useConfirm } from '@/composables/useConfirm'
import { aiApi } from '@/api'
import type { AiToolCallInfo } from '@/api/types'

/**
 * 审批按钮 loading 超时兜底(B-260616-08)。
 * 后端回事件使 tc.status 离开 pending_approval → watch 复位。
 * 兜底计时到点复位 + toast 提示(后端 IPC 应在 1~3s 内返回;30s 兜底远足超时后允许用户重试)。
 * 与 stream 看门狗(130s)解耦:审批是按钮级交互,不是后台流,不需要对齐后端 120s 空闲超时。
 */
const APPROVE_LOADING_TIMEOUT_MS = 30_000

/** AE-2025-05:High 风险工具白名单(后端 tool_registry.rs RiskLevel::High 对齐) */
const HIGH_RISK_TOOLS = new Set<string>([
  'delete_task', 'delete_project', 'restore_project', 'purge_project', 'delete_file', 'run_command',
  'http_request',
])

/**
 * 审批 IPC 分派(共享):按 tc.kind 决定调 aiApi.authorizeDir(path 类)或 aiApi.approve(risk 类)。
 *
 * 抽离自 useAiApproval.approveToolCall 与 ApprovalPopup.onApprove/onReject 两处重复实现,
 * 供两调用方共用同一分派规则,消除「同语义两套逻辑」漂移风险。
 *
 * - kind='path'(路径授权挂起):调 aiApi.authorizeDir(toolCallId, decision)。decision 必传
 *   ('once'|'session'|'always'|'deny'),由调用方按按钮语义给出;缺省兜底 'deny'(安全侧拒绝)。
 * - 其余(risk/缺省,普通 RiskLevel 审批):调 aiApi.approve(toolCallId, approved)。
 *   approved=true 放行,false 拒绝。
 *
 * 不含状态机(loading/防抖/超时兜底)——那些是调用方各自的责任(ToolCard 走 useToolApproval
 * 状态机 + emit;ApprovalPopup 走 processingId 局部 ref;useAiApproval 走 _pendingApprovalIds 防抖)。
 * 本函数仅做「kind → IPC」一层映射,纯 IPC 调用,无 store 依赖,可在任意窗口/上下文调用。
 *
 * @returns invoke 的 Promise(调用方可 await 接力错误处理)
 */
export function dispatchApprovalIPC(
  tc: AiToolCallInfo,
  approved: boolean,
  decision?: 'once' | 'session' | 'always' | 'deny',
): Promise<string> {
  if (tc.kind === 'path') {
    return aiApi.authorizeDir(tc.id, decision ?? 'deny')
  }
  return aiApi.approve(tc.id, approved)
}

export function useToolApproval(tc: Ref<AiToolCallInfo>, emit: any) {
  const { t } = useI18n()
  const { confirmState, confirmDialog, answerConfirm } = useConfirm()

  // ── B-260616-08: 审批 loading 态 ──
  const approving = ref(false)
  let approvingTimer: ReturnType<typeof setTimeout> | null = null

  // ── BUG-260624-02: 审批挂起时长显示 ──
  const pendingSince = ref<number | null>(null)
  const waitSecs = ref(0)
  let waitTimer: ReturnType<typeof setInterval> | null = null

  function startPendingTimer() {
    if (pendingSince.value !== null) return
    pendingSince.value = Date.now()
    waitSecs.value = 0
    if (waitTimer) clearInterval(waitTimer)
    waitTimer = setInterval(() => {
      if (pendingSince.value !== null) {
        waitSecs.value = Math.floor((Date.now() - pendingSince.value) / 1000)
      }
    }, 1000)
  }

  function stopPendingTimer() {
    if (waitTimer) { clearInterval(waitTimer); waitTimer = null }
    pendingSince.value = null
    waitSecs.value = 0
  }

  function formatWaitTime(secs: number): string {
    const m = Math.floor(secs / 60)
    const s = secs % 60
    return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`
  }

  const waitLevel = computed<'normal' | 'long' | 'urgent'>(() => {
    if (waitSecs.value >= 300) return 'urgent'  // 5分钟
    if (waitSecs.value >= 120) return 'long'    // 2分钟
    return 'normal'
  })

  // ── UX-260617-14: 审批超时兜底 toast ──
  const approveToast = reactive({ visible: false, msg: '' })
  let _approveToastTimer: ReturnType<typeof setTimeout> | null = null

  function showApproveTimeoutToast(): void {
    approveToast.msg = t('aiTool.approveLoadingTimeout')
    approveToast.visible = true
    if (_approveToastTimer) clearTimeout(_approveToastTimer)
    _approveToastTimer = setTimeout(() => { approveToast.visible = false }, 3000)
  }

  /** AE-2025-05:High 风险工具的二次确认文案(按操作类型) */
  function highRiskConfirmMsg(name: string): string {
    if (name === 'run_command') return t('aiTool.confirmHighExec')
    if (name === 'http_request') return t('aiTool.confirmHighHttp')
    if (name === 'delete_task' || name === 'delete_project' || name === 'purge_project' || name === 'delete_file' || name === 'restore_project') {
      return t('aiTool.confirmHighDelete')
    }
    return t('aiTool.confirmHighGeneric')
  }

  /**
   * 批准按钮处理(risk 类专用)。
   * AE-2025-05:High 风险工具 → 先二次确认(useConfirm 弹层)。
   * loading + 超时兜底复用 B-260616-08 机制。
   */
  async function onApprove() {
    if (approving.value) return        // 防重入
    // AE-2025-05:High 风险 → 先二次确认
    if (HIGH_RISK_TOOLS.has(tc.value.name)) {
      const ok = await confirmDialog(highRiskConfirmMsg(tc.value.name))
      if (!ok) return
    }
    approving.value = true
    approvingTimer = setTimeout(() => {
      approving.value = false
      approvingTimer = null
      console.warn('[AI] 审批 loading 超时,后端可能未回执,已复位允许重试:', tc.value.id)
      showApproveTimeoutToast()
    }, APPROVE_LOADING_TIMEOUT_MS)
    emit('approve', { id: tc.value.id, approved: true })
  }

  /**
   * 拒绝按钮处理(risk 类专用)。
   * loading + 超时兜底复用 B-260616-08 机制。拒绝不做 High 风险二次确认(无害,加确认反增摩擦)。
   */
  async function onReject() {
    if (approving.value) return        // 防重入
    approving.value = true
    approvingTimer = setTimeout(() => {
      approving.value = false
      approvingTimer = null
      console.warn('[AI] 审批 loading 超时,后端可能未回执,已复位允许重试:', tc.value.id)
      showApproveTimeoutToast()
    }, APPROVE_LOADING_TIMEOUT_MS)
    emit('approve', { id: tc.value.id, approved: false })
  }

  /**
   * path_auth 审批链阶段3b:path 类「仅本次会话授权」处理。
   * 与 onApprove 同款 loading + 超时兜底,emit 带 decision='once'。
   * path 类不做 High 风险二次确认(路径授权是显式白名单写入,非破坏性操作,三选项本身就是用户明示决策)。
   */
  async function onAuthorizeOnce() {
    if (approving.value) return
    approving.value = true
    approvingTimer = setTimeout(() => {
      approving.value = false
      approvingTimer = null
      console.warn('[AI] 路径授权 loading 超时,后端可能未回执,已复位允许重试:', tc.value.id)
      showApproveTimeoutToast()
    }, APPROVE_LOADING_TIMEOUT_MS)
    emit('approve', { id: tc.value.id, approved: false, decision: 'once' })
  }

  /**
   * M4:path 类「当前会话授权」处理(decision='session')。
   * 对齐 DirAuthDialog 四按钮(once/session/always/deny)。session 写会话临时授权层,切会话清;
   * IPC authorizeDir 后端 'session' 全支持(api/ai.ts authorizeDir 签名 + 后端 ai_authorize_dir)。
   * 同 onAuthorizeOnce 同款 loading + 超时兜底;无 High 风险二次确认(同 once/always 语义,显式白名单写入)。
   */
  async function onAuthorizeSession() {
    if (approving.value) return
    approving.value = true
    approvingTimer = setTimeout(() => {
      approving.value = false
      approvingTimer = null
      console.warn('[AI] 路径授权 loading 超时,后端可能未回执,已复位允许重试:', tc.value.id)
      showApproveTimeoutToast()
    }, APPROVE_LOADING_TIMEOUT_MS)
    emit('approve', { id: tc.value.id, approved: false, decision: 'session' })
  }

  /**
   * path_auth 审批链阶段3b:path 类「写持久白名单」处理。
   * 同 onAuthorizeOnce,decision='always'。
   */
  async function onAuthorizeAlways() {
    if (approving.value) return
    approving.value = true
    approvingTimer = setTimeout(() => {
      approving.value = false
      approvingTimer = null
      console.warn('[AI] 路径授权 loading 超时,后端可能未回执,已复位允许重试:', tc.value.id)
      showApproveTimeoutToast()
    }, APPROVE_LOADING_TIMEOUT_MS)
    emit('approve', { id: tc.value.id, approved: false, decision: 'always' })
  }

  /**
   * path_auth 审批链阶段3b:path 类「拒绝」处理。
   * M5:拒绝前二次确认(useConfirm 弹层)。拒绝不可逆——工具返 Err、loop 续跑不再重试该工具,
   * 与放行(once/session/always 均可后续再授权)不对称,误点代价高;补确认与 approve(高风险)对称。
   * risk 类拒绝(onReject)不补确认:risk reject 是常规审批否决,语义明确且可重新触发;仅 path 类加。
   */
  async function onDeny() {
    if (approving.value) return
    const ok = await confirmDialog(t('aiChat.dirAuthDenyConfirm'))
    if (!ok) return
    approving.value = true
    approvingTimer = setTimeout(() => {
      approving.value = false
      approvingTimer = null
      console.warn('[AI] 路径授权 loading 超时,后端可能未回执,已复位允许重试:', tc.value.id)
      showApproveTimeoutToast()
    }, APPROVE_LOADING_TIMEOUT_MS)
    emit('approve', { id: tc.value.id, approved: false, decision: 'deny' })
  }

  // status 离开 pending_approval → 复位 approving(后端回执/转态时)。
  watch(() => tc.value.status, (s) => {
    if (s !== 'pending_approval') {
      approving.value = false
      if (approvingTimer) { clearTimeout(approvingTimer); approvingTimer = null }
      stopPendingTimer()
    } else {
      startPendingTimer()
    }
  }, { immediate: true })

  onBeforeUnmount(() => {
    if (approvingTimer) clearTimeout(approvingTimer)
    if (_approveToastTimer) clearTimeout(_approveToastTimer)
    stopPendingTimer()
  })

  return {
    approving,
    approveToast,
    waitSecs,
    waitLevel,
    formatWaitTime,
    onApprove,
    onReject,
    onAuthorizeOnce,
    onAuthorizeSession,
    onAuthorizeAlways,
    onDeny,
    // 供模板 ConfirmDialog 绑定
    confirmState,
    answerConfirm,
  }
}
