import {
  buildApplicationPreviewFooterMessage,
  buildApplicationPreviewRows,
  buildLocalApplicationPreviewMessage,
  normalizeApplicationPreview
} from '../../utils/expenseApplicationPreview.js'
import {
  buildAiApplicationPrecheck,
  buildAiApplicationSubmitConflictMessage,
  isAiApplicationPrecheckBlocking
} from '../../utils/aiApplicationPrecheckModel.js'
import { fetchExpenseClaims } from '../../services/reimbursements.js'
import {
  AI_APPLICATION_ACTION_SAVE_DRAFT,
  AI_APPLICATION_ACTION_SUBMIT,
  createAiApplicationRequestId,
  registerAiApplicationPreviewDecision,
  runAiApplicationPreviewAction
} from '../../services/aiApplicationPreviewActions.js'
import {
  buildFailedInlineApplicationSubmitThinkingEvents,
  buildInitialInlineApplicationSubmitThinkingEvents,
  buildInlineApplicationDetailAction,
  buildInlineApplicationPreview,
  buildInlineApplicationPreviewActionResultText,
  buildInlineApplicationSubmitPrecheckPayload,
  buildInlineApplicationSubmitThinkingEvents,
  completeInlineThinkingEvents,
  extractInlineApplicationDraftPayload
} from './workbenchAiApplicationPreviewModel.js'
import { AI_ATTACHMENT_ASSOCIATION_CONFIRM_ACTION } from './workbenchAiMessageModel.js'
import {
  completeWorkbenchAiThinkingEvents,
  mergeWorkbenchAiThinkingEvents
} from './workbenchAiPlanningThinkingModel.js'
import {
  isOrphanInlineApplicationPreviewMessage,
  resolveInlineApplicationPreviewTextAction,
  resolveLatestApplicationPreviewMessage,
  resolveLatestOrphanApplicationPreviewMessage
} from './workbenchAiApplicationGateModel.js'

function isApplicationPreviewEstimatePendingPreview(applicationPreview = {}) {
  const fields = normalizeApplicationPreview(applicationPreview).fields || {}
  return [
    fields.transportPolicy,
    fields.policyEstimate,
    fields.transportEstimatedAmount,
    fields.amount
  ].some((value) => /正在|查询中/.test(String(value || '')))
}

function shouldRefreshInlineApplicationPreviewEstimate(fieldKey = '') {
  return ['transportMode', 'time', 'time_return', 'location', 'days'].includes(String(fieldKey || '').trim())
}

export function useWorkbenchAiApplicationPreviewFlow({
  activateInlineConversation,
  applicationPreviewEditor,
  applicationSubmitConfirmContext,
  applicationSubmitConfirmOpen,
  assistantDraft,
  cancelApplicationPreviewEditor,
  clearAiModeFiles,
  closeWorkbenchDatePicker,
  commitApplicationPreviewEditor: commitBaseApplicationPreviewEditor,
  conversationId,
  conversationMessages,
  conversationStarted,
  createInlineMessage,
  currentUser,
  handleApplicationPreviewEditorKeydown,
  inlineConversationAutoScrollPinned,
  isApplicationPreviewEditing,
  openApplicationPreviewEditor,
  persistCurrentConversation,
  pushInlineApplicationActionUserMessage,
  pushInlineUserMessage,
  refreshApplicationPreviewEstimate,
  removeWorkbenchDateTag,
  replaceInlineMessage,
  resolveApplicationPreviewEditorDateMax,
  resolveApplicationPreviewEditorDateMin,
  resolveApplicationPreviewEditorControl,
  resolveApplicationPreviewEditorOptions,
  resolveInlineThinkingEvents,
  resolveLatestInlineUserPrompt,
  scrollInlineConversationToBottom,
  sending,
  toast,
  onApplicationActionCompleted = null
}) {
  function isApplicationPreviewEstimatePending(message = {}) {
    return Boolean(message?.applicationPreview && isApplicationPreviewEstimatePendingPreview(message.applicationPreview))
  }

  function canShowInlineSuggestedActions(message = {}) {
    return Boolean(message?.suggestedActions?.length) && !isApplicationPreviewEstimatePending(message)
  }

  function isInlineSuggestedActionDisabled(action = {}, message = {}) {
    const actionType = String(action?.action_type || '').trim()
    return (
      Boolean(action?.disabled) ||
      (actionType === AI_ATTACHMENT_ASSOCIATION_CONFIRM_ACTION && sending.value) ||
      (
        [AI_APPLICATION_ACTION_SAVE_DRAFT, AI_APPLICATION_ACTION_SUBMIT].includes(actionType) &&
        isApplicationPreviewEstimatePending(message)
      )
    )
  }

  function resolveInlineApplicationPreviewRows(message) {
    return buildApplicationPreviewRows(message?.applicationPreview || {})
  }

  function resolveInlineApplicationPreviewMissingFields(message) {
    return normalizeApplicationPreview(message?.applicationPreview || {}).missingFields || []
  }

  function resolveInlineApplicationPreviewEditorControl(fieldKey) {
    return resolveApplicationPreviewEditorControl(fieldKey)
  }

  function resolveInlineApplicationPreviewEditorDateMin(message, fieldKey) {
    return resolveApplicationPreviewEditorDateMin?.(message, fieldKey) || ''
  }

  function resolveInlineApplicationPreviewEditorDateMax(message, fieldKey) {
    return resolveApplicationPreviewEditorDateMax?.(message, fieldKey) || ''
  }

  function buildInlineApplicationPreviewSuggestedActions(applicationPreview = {}, draftPayload = null) {
    if (isApplicationPreviewEstimatePendingPreview(applicationPreview)) {
      return []
    }
    const normalized = normalizeApplicationPreview(applicationPreview)
    const actions = [{
      label: '保存草稿',
      description: '先保存当前申请表，后续可以继续补充或提交。',
      icon: 'mdi mdi-content-save-outline',
      action_type: AI_APPLICATION_ACTION_SAVE_DRAFT,
      payload: { draftPayload }
    }]
    if (normalized.readyToSubmit) {
      actions.push({
        label: '直接提交',
        description: '提交前先核查相同日期申请单，确认通过后进入审批流程。',
        icon: 'mdi mdi-send-check-outline',
        action_type: AI_APPLICATION_ACTION_SUBMIT,
        payload: { draftPayload }
      })
    }
    return actions
  }

  function syncInlineApplicationPreviewMessageContent(message) {
    if (!message?.applicationPreview) {
      return
    }
    const nextContent = buildLocalApplicationPreviewMessage(message.applicationPreview)
    message.content = nextContent
    message.text = nextContent
    message.suggestedActions = buildInlineApplicationPreviewSuggestedActions(message.applicationPreview, message.draftPayload)
  }

  async function commitInlineApplicationPreviewEditor(message) {
    const shouldLockForEstimate = shouldRefreshInlineApplicationPreviewEstimate(applicationPreviewEditor.value.fieldKey)
    if (shouldLockForEstimate) {
      message.suggestedActions = []
      persistCurrentConversation()
    }
    const committed = await commitBaseApplicationPreviewEditor(message)
    syncInlineApplicationPreviewMessageContent(message)
    persistCurrentConversation()
    return committed
  }

  function handleInlineApplicationPreviewEditorKeydown(event, message) {
    if (event.key === 'Enter') {
      event.preventDefault()
      void commitInlineApplicationPreviewEditor(message)
      return
    }
    if (event.key === 'Escape') {
      event.preventDefault()
      cancelApplicationPreviewEditor()
      return
    }
    handleApplicationPreviewEditorKeydown(event, message)
  }

  function buildInlineApplicationPreviewFooterText(message) {
    const normalized = normalizeApplicationPreview(message?.applicationPreview || {})
    if (isApplicationPreviewEstimatePending(message)) {
      return '费用测算正在同步，请稍等，完成后才能保存草稿或直接提交。'
    }
    if (normalized.validationIssues?.length || normalized.missingFields?.length) {
      return buildApplicationPreviewFooterMessage(normalized)
    }
    if (message?.submitRequiresConfirmation) {
      return '已识别到您希望直接提交。系统不会自动提交申请，请先核对申请核对表；确认无误后，点击下方“直接提交”按钮再进入提交确认。'
    }
    return '申请核对表已补齐，费用测算已同步。您仍可点击表格继续修改；确认无误后，可以点击下方按钮保存草稿或直接提交，也可以直接回复“保存草稿”或“提交”。'
  }

  function buildInlineApplicationActionFailureText(error, isSubmit) {
    return [
      isSubmit ? '### 申请提交失败' : '### 申请草稿保存失败',
      error?.message || (isSubmit ? '申请提交失败，请稍后重试。' : '申请草稿保存失败，请稍后重试。'),
      '我已保留当前申请核对表，您可以修改后重试，也可以稍后再次保存。'
    ].join('\n\n')
  }

  function hasSavedInlineApplicationDraft(message = {}, options = {}) {
    const draftPayload = message?.draftPayload || options.draftPayload || null
    if (!draftPayload || typeof draftPayload !== 'object') {
      return false
    }
    const claimId = String(draftPayload.claim_id || draftPayload.claimId || '').trim()
    const claimNo = String(draftPayload.claim_no || draftPayload.claimNo || '').trim()
    const status = String(draftPayload.status || '').trim().toLowerCase()
    return Boolean((claimId || claimNo) && status !== 'submitted')
  }

  function isContextualInlineApplicationSubmitText(text = '') {
    const normalized = String(text || '').replace(/\s+/g, '').trim()
    return Boolean(
      normalized &&
        /提交/.test(normalized) &&
        /(这个|这张|当前|上面|上述|刚才|申请单|单据|草稿|领导|审核|审批)/.test(normalized)
    )
  }

  function resolveLatestInlineApplicationPreviewMessage() {
    return resolveLatestApplicationPreviewMessage(conversationMessages.value)
  }

  function resolveLatestOrphanInlineApplicationPreviewMessage() {
    return resolveLatestOrphanApplicationPreviewMessage(conversationMessages.value)
  }

  function requestInlineApplicationSubmitConfirmation(targetMessage, options = {}) {
    applicationSubmitConfirmContext.value = {
      messageId: String(targetMessage?.id || '').trim(),
      draftPayload: targetMessage?.draftPayload || options.draftPayload || null,
      userText: String(options.userText || '直接提交').trim() || '直接提交'
    }
    applicationSubmitConfirmOpen.value = true
    persistCurrentConversation()
  }

  function cancelInlineApplicationSubmitConfirm() {
    applicationSubmitConfirmOpen.value = false
    applicationSubmitConfirmContext.value = null
  }

  function confirmInlineApplicationSubmit() {
    const context = applicationSubmitConfirmContext.value || {}
    applicationSubmitConfirmOpen.value = false
    applicationSubmitConfirmContext.value = null
    const sourceMessage = conversationMessages.value.find((message) => message.id === context.messageId)
    if (!sourceMessage?.applicationPreview) {
      toast('当前申请表已变化，请重新点击直接提交。')
      return
    }
    void executeInlineApplicationPreviewAction(AI_APPLICATION_ACTION_SUBMIT, sourceMessage, {
      confirmed: true,
      skipUserMessage: false,
      draftPayload: context.draftPayload || null,
      userText: context.userText || '直接提交'
    })
  }

  async function runInlineApplicationSubmitPrecheck(targetMessage, pendingMessage, normalizedPreview, options = {}) {
    try {
      const claimsPayload = await fetchExpenseClaims({ page: 1, pageSize: 100 })
      const precheck = buildAiApplicationPrecheck(normalizedPreview, {
        claimsPayload: buildInlineApplicationSubmitPrecheckPayload(
          claimsPayload,
          targetMessage.draftPayload || options.draftPayload || null
        ),
        currentUser: currentUser.value || {},
        expenseType: 'travel'
      })
      const thinkingEvents = buildInlineApplicationSubmitThinkingEvents(precheck)
      const blocked = isAiApplicationPrecheckBlocking(precheck)

      if (blocked) {
        replaceInlineMessage(
          pendingMessage.id,
          createInlineMessage('assistant', buildAiApplicationSubmitConflictMessage(normalizedPreview, precheck), {
            id: pendingMessage.id,
            stewardPlan: {
              streamStatus: 'completed',
              thinkingEvents
            }
          })
        )
        persistCurrentConversation()
        scrollInlineConversationToBottom({ force: inlineConversationAutoScrollPinned.value })
        return false
      }

      const message = conversationMessages.value.find((item) => item.id === pendingMessage.id) || pendingMessage
      message.content = '提交前核查通过，正在提交申请并进入审批流程...'
      message.paragraphs = ['提交前核查通过，正在提交申请并进入审批流程...']
      message.stewardPlan = {
        ...(message.stewardPlan || {}),
        streamStatus: 'streaming',
        thinkingEvents
      }
      scrollInlineConversationToBottom({ force: inlineConversationAutoScrollPinned.value })
      return true
    } catch (error) {
      replaceInlineMessage(
        pendingMessage.id,
        createInlineMessage('assistant', [
          '### 提交前核查失败',
          '系统未能完成相同日期申请单查询，所以本次申请没有提交。',
          '请稍后重试；如果仍然失败，请先到单据中心核对是否已有同日期申请单。'
        ].join('\n\n'), {
          id: pendingMessage.id,
          stewardPlan: {
            streamStatus: 'failed',
            thinkingEvents: buildFailedInlineApplicationSubmitThinkingEvents(error)
          }
        })
      )
      toast('提交前核查失败，已暂停提交。')
      persistCurrentConversation()
      return false
    }
  }

  function buildApplicationPreviewNextTaskAction(targetMessage) {
    // 多 task 串行推进:申请草稿保存/提交成功后,检查是否有剩余 task(如报销),
    // 有则生成"继续处理下一个任务"按钮,让用户一键推进。
    const remainingTasks = Array.isArray(targetMessage?.stewardRemainingTasks)
      ? targetMessage.stewardRemainingTasks
      : []
    const nextTask = remainingTasks[0]
    if (!nextTask || !nextTask.task_type) {
      return null
    }
    const taskType = String(nextTask.task_type || '').trim()
    const isApplication = taskType === 'expense_application'
    const flowId = isApplication ? 'travel_application' : 'travel_reimbursement'
    const taskLabel = isApplication ? '出差申请' : '费用报销'
    const ontologyFields = nextTask.ontology_fields || nextTask.ontologyFields || {}
    // 透传去掉当前 nextTask 之后的剩余 task 列表,保证 task2 完成后 task3 也能继续推进,
    // 避免 3+ task 场景在 task2 处断链。
    const furtherRemainingTasks = remainingTasks.slice(1)
    return {
      label: `继续处理${taskLabel}`,
      description: `接下来处理${taskLabel}：${String(nextTask.summary || nextTask.title || '').slice(0, 40)}`,
      icon: isApplication ? 'mdi mdi-file-plus-outline' : 'mdi mdi-receipt-text-plus-outline',
      action_type: 'steward_continue_next_task',
      payload: {
        steward_confirm_flow: true,
        flow_id: flowId,
        steward_current_task: nextTask,
        expense_type: String(ontologyFields.expense_type || 'travel').trim() || 'travel',
        expense_type_label: String(ontologyFields.expense_type_label || '差旅费').trim() || '差旅费',
        ontology_fields: ontologyFields,
        original_message: String(nextTask.summary || nextTask.title || `继续处理${taskLabel}`).trim(),
        steward_remaining_tasks: furtherRemainingTasks
      }
    }
  }

  async function executeInlineApplicationPreviewAction(actionType, sourceMessage = null, options = {}) {
    const targetMessage = sourceMessage?.applicationPreview ? sourceMessage : resolveLatestInlineApplicationPreviewMessage()
    if (!targetMessage?.applicationPreview) {
      toast('当前没有可提交的申请表。')
      return false
    }

    let normalizedPreview = normalizeApplicationPreview(targetMessage.applicationPreview)
    const isSubmit = actionType === AI_APPLICATION_ACTION_SUBMIT
    const userText = String(options.userText || (isSubmit ? '直接提交' : '保存草稿')).trim()
    const actionRequestId = String(
      normalizedPreview.decisionActionRequestId || createAiApplicationRequestId('action')
    ).trim()
    if (normalizedPreview.decisionId) {
      normalizedPreview = normalizeApplicationPreview({
        ...normalizedPreview,
        decisionActionRequestId: actionRequestId
      })
      targetMessage.applicationPreview = normalizedPreview
      persistCurrentConversation()
    }

    if (isSubmit && !normalizedPreview.readyToSubmit) {
      if (!options.skipUserMessage) {
        pushInlineApplicationActionUserMessage(userText)
      }
      const missingText = normalizedPreview.missingFields?.length
        ? `当前还缺少：${normalizedPreview.missingFields.join('、')}。`
        : ''
      const validationText = normalizedPreview.validationIssues?.length
        ? normalizedPreview.validationIssues.map((item) => item.message).join('；')
        : ''
      conversationMessages.value.push(createInlineMessage('assistant', [
        '### 暂不能提交申请',
        missingText || validationText || '当前申请表还未通过提交校验。',
        '请先点击表格中的字段补充或修正，补齐后我会开放“直接提交”入口。'
      ].filter(Boolean).join('\n\n')))
      persistCurrentConversation()
      scrollInlineConversationToBottom()
      return true
    }

    const shouldSubmitSavedDraftDirectly = isSubmit &&
      !options.confirmed &&
      hasSavedInlineApplicationDraft(targetMessage, options) &&
      isContextualInlineApplicationSubmitText(userText)

    if (isSubmit && !options.confirmed && !shouldSubmitSavedDraftDirectly) {
      requestInlineApplicationSubmitConfirmation(targetMessage, { ...options, userText })
      return true
    }

    if (!options.skipUserMessage) {
      pushInlineApplicationActionUserMessage(userText)
    }

    sending.value = true
    const pendingMessage = createInlineMessage(
      'assistant',
      isSubmit ? '正在提交前核查相同日期申请单...' : '正在保存申请草稿...',
      {
        pending: true,
        stewardPlan: {
          streamStatus: 'streaming',
          thinkingEvents: isSubmit
            ? buildInitialInlineApplicationSubmitThinkingEvents()
            : [
                {
                  eventId: 'application-save-draft',
                  title: '保存申请草稿',
                  content: '正在按当前申请表内容保存草稿。',
                  status: 'running'
                }
              ]
        }
      }
    )
    conversationMessages.value.push(pendingMessage)
    scrollInlineConversationToBottom()

    try {
      if (isSubmit) {
        const precheckPassed = await runInlineApplicationSubmitPrecheck(
          targetMessage,
          pendingMessage,
          normalizedPreview,
          options
        )
        if (!precheckPassed) {
          return true
        }
      }

      const payload = await runAiApplicationPreviewAction({
        actionType,
        applicationPreview: normalizedPreview,
        currentUser: currentUser.value || {},
        conversationId: conversationId.value,
        draftPayload: targetMessage.draftPayload || options.draftPayload || null,
        requestId: actionRequestId
      })
      const draftPayload = extractInlineApplicationDraftPayload(payload)
      if (draftPayload) {
        targetMessage.draftPayload = draftPayload
      }
      const nextDecisionId = String(payload?.result?.decision_id || '').trim()
      targetMessage.applicationPreview = normalizeApplicationPreview({
        ...(targetMessage.applicationPreview || normalizedPreview),
        ...(nextDecisionId
          ? {
              decisionId: nextDecisionId,
              decisionExpiresAt: String(payload?.result?.decision_expires_at || '').trim(),
              decisionTrackingStatus: 'registered'
            }
          : {
              decisionTrackingStatus: normalizedPreview.decisionId ? 'consumed' : 'legacy'
            }),
        decisionActionRequestId: ''
      })
      targetMessage.suggestedActions = []
      const detailActions = buildInlineApplicationDetailAction(draftPayload)
      const nextTaskAction = buildApplicationPreviewNextTaskAction(targetMessage)
      const actionCompletedHandler = typeof options.onApplicationActionCompleted === 'function'
        ? options.onApplicationActionCompleted
        : onApplicationActionCompleted
      const shouldAutoContinueNextTask = Boolean(
        nextTaskAction &&
        typeof actionCompletedHandler === 'function' &&
        Array.isArray(targetMessage.stewardRemainingTasks) &&
        targetMessage.stewardRemainingTasks.length
      )
      replaceInlineMessage(
        pendingMessage.id,
        createInlineMessage('assistant', buildInlineApplicationPreviewActionResultText(actionType, payload), {
          id: pendingMessage.id,
          stewardPlan: {
            streamStatus: 'completed',
            thinkingEvents: completeInlineThinkingEvents(resolveInlineThinkingEvents(pendingMessage))
          },
          suggestedActions: shouldAutoContinueNextTask
            ? detailActions
            : (nextTaskAction ? [...detailActions, nextTaskAction] : detailActions)
        })
      )
      persistCurrentConversation()
      scrollInlineConversationToBottom({ force: inlineConversationAutoScrollPinned.value })
      if (shouldAutoContinueNextTask) {
        actionCompletedHandler(targetMessage.stewardRemainingTasks, targetMessage)
      }
      return true
    } catch (error) {
      replaceInlineMessage(
        pendingMessage.id,
        createInlineMessage('assistant', buildInlineApplicationActionFailureText(error, isSubmit), {
          id: pendingMessage.id,
          applicationPreview: targetMessage.applicationPreview,
          draftPayload: targetMessage.draftPayload || options.draftPayload || null,
          suggestedActions: buildInlineApplicationPreviewSuggestedActions(
            targetMessage.applicationPreview,
            targetMessage.draftPayload || options.draftPayload || null
          ),
          stewardPlan: {
            streamStatus: 'failed',
            thinkingEvents: resolveInlineThinkingEvents(pendingMessage).map((item) => ({
              ...item,
              status: 'failed'
            }))
          }
        })
      )
      toast(error?.message || (isSubmit ? '申请提交失败。' : '申请草稿保存失败。'))
      persistCurrentConversation()
      return true
    } finally {
      sending.value = false
      scrollInlineConversationToBottom({ force: inlineConversationAutoScrollPinned.value })
    }
  }

  function handleInlineApplicationPreviewTextAction(prompt, applicationPreviewEstimatePending) {
    if (applicationPreviewEstimatePending.value) {
      toast('请等待费用测算完成后再继续操作。')
      return true
    }
    const actionType = resolveInlineApplicationPreviewTextAction(prompt)
    if (!actionType) {
      return false
    }
    if (!resolveLatestInlineApplicationPreviewMessage()) {
      const orphanPreviewMessage = resolveLatestOrphanInlineApplicationPreviewMessage()
      if (!orphanPreviewMessage) {
        return false
      }
      const previewSourceText = resolveLatestInlineUserPrompt()
      pushInlineApplicationActionUserMessage(prompt)
      toast('当前申请核对表状态不完整，我先重新生成可编辑表格。')
      void startAiApplicationPreview('travel', '差旅费', previewSourceText, {
        pushUserMessage: false
      })
      return true
    }
    void executeInlineApplicationPreviewAction(actionType, null, { userText: prompt })
    return true
  }

  async function startAiApplicationPreview(expenseType, expenseTypeLabel, sourceText = '', options = {}) {
    if (!conversationStarted.value) {
      activateInlineConversation({ title: String(expenseTypeLabel || expenseType || '申请').trim().slice(0, 18) || '申请' })
    }
    const previewSourceText = String(sourceText || resolveLatestInlineUserPrompt()).trim()
    assistantDraft.value = ''
    removeWorkbenchDateTag()
    closeWorkbenchDatePicker()
    clearAiModeFiles()
    if (options.pushUserMessage !== false) {
      pushInlineUserMessage(options.userMessage || '确认发起出差申请')
    }

    const existingPendingMessage = options.pendingMessageId
      ? conversationMessages.value.find((item) => item.id === options.pendingMessageId)
      : null
    const previousThinkingEvents = completeWorkbenchAiThinkingEvents(resolveInlineThinkingEvents(existingPendingMessage))
    const pendingMessage = createInlineMessage('assistant', '正在生成申请核对表，请稍等...', {
      id: options.pendingMessageId,
      pending: true,
      stewardPlan: {
        streamStatus: 'streaming',
        thinkingEvents: mergeWorkbenchAiThinkingEvents(previousThinkingEvents, [
          {
            eventId: 'application-preview-build',
            title: '整理申请表字段',
            content: '正在把已识别的时间、地点、事由和差旅类型整理成可编辑表格。',
            status: 'running'
          },
          {
            eventId: 'application-preview-estimate',
            title: '同步费用测算',
            content: '正在刷新差旅规则和费用测算，完成后会直接展示核对表。',
            status: 'pending'
          }
        ])
      }
    })
    if (options.pendingMessageId) {
      replaceInlineMessage(options.pendingMessageId, pendingMessage)
    } else {
      conversationMessages.value.push(pendingMessage)
    }
    persistCurrentConversation()
    scrollInlineConversationToBottom()

    try {
      const preview = await refreshApplicationPreviewEstimate(
        buildInlineApplicationPreview(expenseTypeLabel || expenseType, previewSourceText, currentUser.value || {}, {
          ontologyFields: options.ontologyFields
        })
      )
      let registeredPreview = preview
      try {
        registeredPreview = await registerAiApplicationPreviewDecision({
          applicationPreview: preview,
          conversationId: conversationId.value,
          message: previewSourceText,
          requestId: createAiApplicationRequestId('preview')
        })
      } catch (error) {
        console.warn('Application preview decision registration failed:', error)
        registeredPreview = normalizeApplicationPreview({
          ...preview,
          decisionTrackingStatus: 'degraded'
        })
      }
      const content = buildLocalApplicationPreviewMessage(registeredPreview)
      const previewMessage = createInlineMessage('assistant', content, {
        id: pendingMessage.id,
        applicationPreview: registeredPreview,
        suggestedActions: buildInlineApplicationPreviewSuggestedActions(registeredPreview),
        requestedSubmit: Boolean(options.requestedSubmit),
        submitRequiresConfirmation: Boolean(options.submitRequiresConfirmation),
        stewardRemainingTasks: Array.isArray(options.stewardRemainingTasks) ? options.stewardRemainingTasks : [],
        stewardPlan: {
          streamStatus: 'completed',
          thinkingEvents: completeWorkbenchAiThinkingEvents(resolveInlineThinkingEvents(pendingMessage))
        },
        text: content
      })
      replaceInlineMessage(pendingMessage.id, previewMessage)
      if (options.autoSaveDraft) {
        await executeInlineApplicationPreviewAction(AI_APPLICATION_ACTION_SAVE_DRAFT, previewMessage, {
          skipUserMessage: true,
          userText: options.userMessage || '保存草稿',
          onApplicationActionCompleted: options.onApplicationActionCompleted
        })
      } else if (
        typeof options.onPreviewReadyForNextTask === 'function' &&
        Array.isArray(previewMessage.stewardRemainingTasks) &&
        previewMessage.stewardRemainingTasks.length
      ) {
        options.onPreviewReadyForNextTask(previewMessage.stewardRemainingTasks, previewMessage)
      }
    } catch (error) {
      replaceInlineMessage(pendingMessage.id, createInlineMessage('assistant', error?.message || '申请核对表生成失败，请稍后重试。', {
        id: pendingMessage.id,
        stewardPlan: {
          streamStatus: 'failed',
          thinkingEvents: resolveInlineThinkingEvents(pendingMessage).map((item) => ({
            ...item,
            status: 'failed'
          }))
        }
      }))
      toast(error?.message || '申请核对表生成失败。')
    } finally {
      persistCurrentConversation()
      scrollInlineConversationToBottom({ force: inlineConversationAutoScrollPinned.value })
    }
  }

  return {
    buildInlineApplicationPreviewFooterText,
    buildInlineApplicationPreviewSuggestedActions,
    canShowInlineSuggestedActions,
    cancelInlineApplicationSubmitConfirm,
    commitInlineApplicationPreviewEditor,
    confirmInlineApplicationSubmit,
    executeInlineApplicationPreviewAction,
    handleInlineApplicationPreviewEditorKeydown,
    handleInlineApplicationPreviewTextAction,
    isApplicationPreviewEditing,
    isApplicationPreviewEstimatePending,
    isInlineSuggestedActionDisabled,
    openApplicationPreviewEditor,
    resolveApplicationPreviewEditorOptions,
    resolveInlineApplicationPreviewEditorControl,
    resolveInlineApplicationPreviewEditorDateMax,
    resolveInlineApplicationPreviewEditorDateMin,
    resolveInlineApplicationPreviewMissingFields,
    resolveInlineApplicationPreviewRows,
    startAiApplicationPreview
  }
}
