import {
  ASSISTANT_SCOPE_ACTION_SWITCH,
  ASSISTANT_SCOPE_ACTION_FILL_COMPOSER
} from '../../utils/assistantSessionScope.js'
import {
  SESSION_TYPE_APPLICATION,
  SESSION_TYPE_EXPENSE
} from './travelReimbursementConversationModel.js'
import {
  FLOW_EXPENSE_TYPE_LABELS,
  buildStewardFieldItems,
  filterStewardBlockingMissingFields,
  formatStewardMissingFieldList,
  formatStewardOntologyFields,
  formatStewardOntologyFieldsTable
} from './stewardPlanFields.js'

export {
  buildStewardFieldItems,
  filterStewardBlockingMissingFields,
  formatStewardMissingFieldList,
  formatStewardOntologyFields
}

const TASK_TYPE_LABELS = {
  expense_application: '费用申请',
  reimbursement: '费用报销',
  query_travel_standard: '差旅标准查询'
}

const AGENT_LABELS = {
  application_assistant: '申请助手',
  application: '申请助手',
  expense_application: '申请助手',
  reimbursement_assistant: '报销助手',
  reimbursement: '报销助手',
  expense: '报销助手',
  policy_query_assistant: '政策查询助手',
  query_travel_standard: '政策查询助手'
}

const EXECUTABLE_STEWARD_ACTION_TYPES = new Set([
  'save_application_draft',
  'submit_application',
  'create_reimbursement_draft',
  'associate_attachments',
  'execute_travel_standard_query'
])

export function buildStewardPlanRequest({
  rawText = '',
  files = [],
  currentUser = {},
  conversationId = '',
  stewardState = null
} = {}) {
  const safeFiles = Array.isArray(files) ? files : []
  const normalizedConversationId = String(conversationId || '').trim()
  return {
    message: String(rawText || '').trim(),
    user_id: String(currentUser.username || currentUser.name || 'anonymous').trim() || 'anonymous',
    client_now_iso: new Date().toISOString(),
    attachments: safeFiles.map((file) => ({
      name: String(file?.name || '').trim(),
      media_type: String(file?.type || '').trim()
    })).filter((item) => item.name),
    context_json: {
      entry_source: 'workbench',
      session_type: 'steward',
      conversation_id: normalizedConversationId,
      steward_state: stewardState && typeof stewardState === 'object' ? stewardState : null,
      role_codes: Array.isArray(currentUser.roleCodes) ? currentUser.roleCodes : [],
      username: currentUser.username || '',
      name: currentUser.name || currentUser.username || '',
      department_name: currentUser.departmentName || currentUser.department || '',
      employee_grade: currentUser.grade || ''
    }
  }
}

export function normalizeStewardPlan(rawPlan = {}, options = {}) {
  const visibleThinkingEventCount = Number.isFinite(options.visibleThinkingEventCount)
    ? Number(options.visibleThinkingEventCount)
    : Number(rawPlan.visibleThinkingEventCount || rawPlan.visible_thinking_event_count || 0)
  const pendingFlowConfirmation = normalizePendingFlowConfirmation(rawPlan)
  return {
    planId: String(rawPlan.plan_id || rawPlan.planId || ''),
    planStatus: String(rawPlan.plan_status || rawPlan.planStatus || ''),
    nextAction: String(rawPlan.next_action || rawPlan.nextAction || ''),
    conversationId: String(rawPlan.conversation_id || rawPlan.conversationId || ''),
    stewardState: rawPlan.steward_state || rawPlan.stewardState || null,
    summary: String(rawPlan.summary || ''),
    visibleThinkingEventCount,
    initialSummaryOnly: Boolean(rawPlan.initial_summary_only || rawPlan.initialSummaryOnly || options.initialSummaryOnly),
    thinkingEvents: Array.isArray(rawPlan.thinking_events)
      ? rawPlan.thinking_events.map((item) => ({
          eventId: String(item.event_id || item.eventId || ''),
          stage: String(item.stage || ''),
          title: String(item.title || ''),
          content: String(item.content || ''),
          status: String(item.status || 'completed')
        }))
      : [],
    tasks: Array.isArray(rawPlan.tasks)
      ? rawPlan.tasks.map((item) => {
          const taskType = String(item.task_type || item.taskType || '')
          const rawMissingFields = Array.isArray(item.missing_fields || item.missingFields)
            ? item.missing_fields || item.missingFields
            : []
          const missingFields = filterStewardBlockingMissingFields(rawMissingFields, taskType)
          return {
            taskId: String(item.task_id || item.taskId || ''),
            taskType,
            taskTypeLabel: TASK_TYPE_LABELS[taskType] || '财务任务',
            assignedAgent: String(item.assigned_agent || item.assignedAgent || ''),
            assignedAgentLabel:
              AGENT_LABELS[String(item.assigned_agent || item.assignedAgent || '')] ||
              AGENT_LABELS[taskType] ||
              '小财管家',
            title: String(item.title || ''),
            summary: String(item.summary || ''),
            status: String(item.status || ''),
            confidence: Number(item.confidence || 0),
            requestedAction: String(item.requested_action || item.requestedAction || ''),
            ontologyFields: item.ontology_fields || item.ontologyFields || {},
            missingFields,
            missingFieldItems: buildStewardFieldItems(missingFields, taskType),
            confirmationRequired: item.confirmation_required ?? item.confirmationRequired ?? true,
            actionSteps: normalizeStewardActionSteps(item.action_steps || item.actionSteps)
          }
        })
      : [],
    attachmentGroups: Array.isArray(rawPlan.attachment_groups)
      ? rawPlan.attachment_groups.map((item) => ({
          groupId: String(item.group_id || item.groupId || ''),
          targetTaskId: String(item.target_task_id || item.targetTaskId || ''),
          scene: String(item.scene || ''),
          sceneLabel: String(item.scene_label || item.sceneLabel || ''),
          attachmentNames: Array.isArray(item.attachment_names || item.attachmentNames)
            ? item.attachment_names || item.attachmentNames
            : [],
          excludedAttachmentNames: Array.isArray(item.excluded_attachment_names || item.excludedAttachmentNames)
            ? item.excluded_attachment_names || item.excludedAttachmentNames
            : [],
          confidence: Number(item.confidence || 0),
          rationale: String(item.rationale || ''),
          confirmationRequired: item.confirmation_required ?? item.confirmationRequired ?? true
        }))
      : [],
    confirmationGroups: Array.isArray(rawPlan.confirmation_groups)
      ? rawPlan.confirmation_groups
      : [],
    pendingFlowConfirmation,
    candidateFlows: pendingFlowConfirmation.candidateFlows,
    suggestedPrompts: Array.isArray(rawPlan.suggested_prompts)
      ? rawPlan.suggested_prompts.map((item) => String(item || '').trim()).filter(Boolean)
      : []
  }
}

function normalizeStewardActionSteps(rawSteps = []) {
  if (!Array.isArray(rawSteps)) {
    return []
  }
  return rawSteps
    .map((step) => ({
      step_id: String(step?.step_id || step?.stepId || ''),
      action_type: String(step?.action_type || step?.actionType || ''),
      label: String(step?.label || ''),
      target_task_id: String(step?.target_task_id || step?.targetTaskId || ''),
      status: String(step?.status || 'planned'),
      requires_confirmation: Boolean(step?.requires_confirmation ?? step?.requiresConfirmation),
      depends_on: Array.isArray(step?.depends_on || step?.dependsOn)
        ? step.depends_on || step.dependsOn
        : [],
      payload: step?.payload && typeof step.payload === 'object' ? step.payload : {}
    }))
    .filter((step) => step.step_id && step.action_type)
}

export function buildStewardPlanMessageText(plan) {
  const normalized = normalizeStewardPlan(plan)
  if (isOffTopicPlan(normalized)) {
    return buildOffTopicMessageText(normalized)
  }
  if (isPendingFlowConfirmationPlan(normalized)) {
    return buildPendingFlowConfirmationMessageText(normalized)
  }
  const genericReimbursementTask = normalized.tasks.find((task) => isGenericReimbursementTask(task))
  if (genericReimbursementTask && normalized.tasks.length === 1) {
    return buildGenericReimbursementIntentMessageText(genericReimbursementTask)
  }
  const nextContext = resolveNextActionContext(normalized)
  const orderedTasks = buildOrderedStewardTasks(normalized, nextContext?.task)
  const taskLines = orderedTasks.map((task, index) =>
    `${index + 1}. **${buildTaskOrderVerb(index)}${buildTaskOrderTarget(task)}**\n   - ${buildTaskOrderActionDescription(task)}`
  )
  return [
    '### 我先帮您把步骤理清楚',
    '',
    buildStewardPlanFriendlyIntro(normalized),
    '',
    ...taskLines,
    '',
    '您看这个顺序是否合适？如果没问题，回复 **确定** 即可。我会先带您进入第一步，需要补充的信息会在具体步骤里再温和提醒。'
  ].filter((line, index, lines) => line || lines[index - 1]).join('\n')
}

function resolveCandidateFlowExpenseType(flow = {}) {
  const rawType = String(flow?.ontologyFields?.expense_type || flow?.ontologyFields?.expenseType || '').trim()
  if (rawType === '差旅' || rawType === 'travel') {
    return 'travel'
  }
  return rawType
}

function normalizeStewardExpenseTypeCode(value = '') {
  const text = String(value || '').trim()
  if (text === '差旅' || text === '差旅费' || text === 'travel') {
    return 'travel'
  }
  return text
}

function resolveTaskExpenseType(task = null) {
  const fields = task?.ontologyFields || task?.ontology_fields || {}
  const explicitType = normalizeStewardExpenseTypeCode(
    fields.expense_type ||
      fields.expenseType ||
      fields.application_type ||
      fields.applicationType ||
      ''
  )
  if (explicitType) {
    return explicitType
  }
  const taskText = [
    task?.title,
    task?.summary,
    fields.reason,
    fields.location
  ].map((item) => String(item || '').trim()).join(' ')
  return /差旅|出差/.test(taskText) ? 'travel' : ''
}

function buildStewardApplicationPreviewRoutePayload(actionType, task = null) {
  if (actionType !== 'confirm_create_application') {
    return {}
  }
  const expenseType = resolveTaskExpenseType(task)
  if (expenseType !== 'travel') {
    return {}
  }
  return {
    steward_confirm_flow: true,
    flow_id: 'travel_application',
    expense_type: expenseType,
    expense_type_label: FLOW_EXPENSE_TYPE_LABELS[expenseType] || ''
  }
}

export function buildStewardSuggestedActions(plan) {
  const normalized = normalizeStewardPlan(plan)
  if (isOffTopicPlan(normalized)) {
    return normalized.suggestedPrompts.map((prompt) => ({
      label: prompt.length > 24 ? `${prompt.slice(0, 24)}...` : prompt,
      description: '点击填入输入框，可编辑后发送',
      icon: 'mdi mdi-comment-text-outline',
      action_type: ASSISTANT_SCOPE_ACTION_FILL_COMPOSER,
      payload: {
        steward_plan_id: normalized.planId,
        fill_text: prompt
      }
    }))
  }
  if (isPendingFlowConfirmationPlan(normalized)) {
    return normalized.candidateFlows.map((flow) => {
      const expenseType = resolveCandidateFlowExpenseType(flow)
      return {
        label: flow.label,
        description: flow.reason || '选择后小财管家会继续整理对应流程材料。',
        icon: flow.flowId === 'travel_application'
          ? 'mdi mdi-file-plus-outline'
          : 'mdi mdi-receipt-text-plus-outline',
        action_type: ASSISTANT_SCOPE_ACTION_SWITCH,
        payload: {
          steward_confirm_flow: true,
          steward_plan_id: normalized.planId,
          flow_id: flow.flowId,
          session_type: flow.flowId === 'travel_application'
            ? SESSION_TYPE_APPLICATION
            : SESSION_TYPE_EXPENSE,
          selected_flow_label: flow.label,
          expense_type: expenseType,
          expense_type_label: FLOW_EXPENSE_TYPE_LABELS[expenseType] || '',
          requires_application_before_reimbursement: flow.flowId === 'travel_reimbursement' && expenseType === 'travel',
          carry_text: flow.flowId === 'travel_reimbursement' && expenseType === 'travel' ? '我要报销' : flow.label,
          auto_submit: true,
          steward_state: normalized.stewardState || null
        }
      }
    })
  }
  const nextContext = resolveNextActionContext(normalized)
  if (!nextContext) {
    return []
  }
  const { action, actionType, task, group } = nextContext
  const targetSessionType = actionType === 'confirm_create_application'
    ? SESSION_TYPE_APPLICATION
    : SESSION_TYPE_EXPENSE
  const executableStep = resolveExecutableStewardActionStep(task)
  return [
    {
      label: buildNextActionLabel(actionType, task),
      description: buildNextActionDescription(actionType, normalized, task, group),
      icon: actionType === 'confirm_create_application'
        ? 'mdi mdi-file-plus-outline'
        : actionType === 'confirm_attachment_group'
          ? 'mdi mdi-folder-check-outline'
          : 'mdi mdi-receipt-text-plus-outline',
      action_type: ASSISTANT_SCOPE_ACTION_SWITCH,
      payload: {
        session_type: targetSessionType,
        ...buildStewardApplicationPreviewRoutePayload(actionType, task),
        carry_text: buildStewardCarryText(actionType, task, group, normalized),
        carry_files: actionType !== 'confirm_create_application',
        auto_submit: true,
        steward_confirmation_id: String(action.confirmation_id || action.confirmationId || ''),
        steward_plan_id: normalized.planId,
        steward_next_task_id: task?.taskId || '',
        ...buildStewardExecuteActionPayload(executableStep, task),
        steward_current_task: buildStewardTaskPayload(task),
        steward_remaining_task_count: normalized.tasks.filter((item) => item.taskId !== task?.taskId).length,
        steward_remaining_tasks: buildRemainingTaskPayload(normalized, task?.taskId)
      }
    }
  ]
}

function resolveExecutableStewardActionStep(task = null) {
  const steps = Array.isArray(task?.actionSteps || task?.action_steps)
    ? task.actionSteps || task.action_steps
    : []
  return [...steps].reverse().find((step) => EXECUTABLE_STEWARD_ACTION_TYPES.has(String(step.action_type || step.actionType || ''))) || null
}

function buildStewardExecuteActionPayload(step, task) {
  if (!step) {
    return {}
  }
  return {
    steward_execute_action: true,
    steward_action_type: String(step.action_type || step.actionType || ''),
    steward_action_step: step,
    steward_action_requires_confirmation: Boolean(step.requires_confirmation ?? step.requiresConfirmation),
    steward_action_task_id: task?.taskId || task?.task_id || ''
  }
}

function normalizePendingFlowConfirmation(rawPlan = {}) {
  const rawPending = rawPlan.pending_flow_confirmation || rawPlan.pendingFlowConfirmation || {}
  const rawCandidates = Array.isArray(rawPlan.candidate_flows || rawPlan.candidateFlows)
    ? rawPlan.candidate_flows || rawPlan.candidateFlows
    : rawPending?.candidate_flows || rawPending?.candidateFlows || []
  const candidateFlows = Array.isArray(rawCandidates)
    ? rawCandidates
        .map((item) => normalizeCandidateFlow(item))
        .filter((item) => item.flowId)
    : []
  return {
    status: String(rawPending?.status || '').trim(),
    sourceMessage: String(rawPending?.source_message || rawPending?.sourceMessage || '').trim(),
    reason: String(rawPending?.reason || '').trim(),
    candidateFlows
  }
}

function normalizeCandidateFlow(item = {}) {
  const flowId = String(item.flow_id || item.flowId || '').trim()
  if (!['travel_application', 'travel_reimbursement'].includes(flowId)) {
    return { flowId: '' }
  }
  return {
    flowId,
    label: String(item.label || (flowId === 'travel_application' ? '补办出差申请' : '发起费用报销')).trim(),
    confidence: Number(item.confidence || 0),
    reason: String(item.reason || '').trim(),
    ontologyFields: item.ontology_fields || item.ontologyFields || {},
    missingFields: Array.isArray(item.missing_fields || item.missingFields)
      ? item.missing_fields || item.missingFields
      : []
  }
}

function isPendingFlowConfirmationPlan(normalized) {
  return (
    String(normalized?.nextAction || '').trim() === 'confirm_flow' ||
    String(normalized?.planStatus || '').trim() === 'needs_flow_confirmation' ||
    String(normalized?.pendingFlowConfirmation?.status || '').trim() === 'pending'
  ) && Array.isArray(normalized?.candidateFlows) && normalized.candidateFlows.length > 0
}

function isOffTopicPlan(normalized) {
  return String(normalized?.planStatus || '').trim() === 'off_topic'
}

export function isOffTopicStewardPlan(rawPlan) {
  return isOffTopicPlan(normalizeStewardPlan(rawPlan))
}

function buildOffTopicMessageText(normalized) {
  // off_topic 计划的引导文案完全由后端生成（含 ### 标题 + 正文 + 引导句），
  // 前端透传 summary 即可，避免重复拼接导致与后端表达不一致。
  const summary = String(normalized?.summary || '').trim()
  if (summary) {
    return summary
  }
  return (
    '### 这句话我暂时没识别到财务事项\n\n' +
    '很抱歉主人，目前小财管家只能帮您整理**费用申请**和**费用报销**这两类事项。\n\n' +
    '要不您换种说法告诉我：'
  )
}

function buildPendingFlowConfirmationMessageText(normalized) {
  const fields = normalized.candidateFlows[0]?.ontologyFields || {}
  const knownTable = formatStewardOntologyFieldsTable(fields, 'expense_application')
  const candidateLines = normalized.candidateFlows.map((flow, index) =>
    `${index + 1}. **${flow.label}**${flow.reason ? `\n   - ${flow.reason}` : ''}`
  )
  const singleCandidate = normalized.candidateFlows.length === 1
  return [
    '### 需要先确认流程方向',
    '',
    knownTable
      ? ['我识别到这是一项财务事项，已提取到：', '', knownTable].join('\n')
      : '我识别到这是一项财务事项，但还需要确认您要进入哪个流程。',
    '',
    normalized.pendingFlowConfirmation.reason || normalized.summary || '当前还不能确定您是要补办申请，还是发起报销。',
    '',
    ...candidateLines,
    '',
    singleCandidate
      ? `请先点击下方 **${normalized.candidateFlows[0].label}**，我会继续整理对应材料。`
      : '请先选择一个方向，我会继续整理对应材料。'
  ].filter((line, index, lines) => line || lines[index - 1]).join('\n')
}

function buildGenericReimbursementIntentMessageText() {
  return [
    '### 我来带您发起报销',
    '',
    '您现在只说了要报销，还没告诉我具体是哪类费用。先不用一次性补全所有信息，我会按报销流程一步步带您填。',
    '',
    '1. **先选报销场景**',
    '   - 例如差旅费、交通费、住宿费、业务招待费或办公用品费，不同场景需要的材料不一样。',
    '2. **再补关键材料**',
    '   - 我会继续追问事由、发生时间、金额和票据附件；如果是差旅或招待，还会先帮您核对是否需要关联事前申请。',
    '',
    '点击下面的 **确定，选择报销场景**，我会进入报销助手继续引导。'
  ].join('\n')
}

function resolveNextActionContext(normalized) {
  const applicationTask = normalized.tasks.find((task) => task.taskType === 'expense_application')
  const applicationAction = applicationTask
    ? findConfirmationAction(normalized, 'confirm_create_application', applicationTask.taskId)
    : null
  if (applicationAction) {
    return {
      action: applicationAction,
      actionType: 'confirm_create_application',
      task: applicationTask,
      group: null
    }
  }

  const reimbursementTask = normalized.tasks.find((task) => task.taskType === 'reimbursement')
  const reimbursementAction = reimbursementTask
    ? findConfirmationAction(normalized, 'confirm_create_reimbursement_draft', reimbursementTask.taskId)
    : null
  if (reimbursementAction) {
    return {
      action: reimbursementAction,
      actionType: 'confirm_create_reimbursement_draft',
      task: reimbursementTask,
      group: findAttachmentGroupForTask(normalized, reimbursementTask.taskId)
    }
  }

  const attachmentAction = normalized.confirmationGroups.find((action) =>
    normalizeActionType(action) === 'confirm_attachment_group'
  )
  if (attachmentAction) {
    const groupId = String(attachmentAction.attachment_group_id || attachmentAction.attachmentGroupId || '').trim()
    const group = normalized.attachmentGroups.find((item) => item.groupId === groupId)
    const task = normalized.tasks.find((item) => item.taskId === group?.targetTaskId)
    return {
      action: attachmentAction,
      actionType: 'confirm_attachment_group',
      task,
      group
    }
  }

  const fallbackAction = normalized.confirmationGroups[0]
  if (!fallbackAction) {
    return null
  }
  const actionType = normalizeActionType(fallbackAction)
  const taskId = String(fallbackAction.target_task_id || fallbackAction.targetTaskId || '').trim()
  return {
    action: fallbackAction,
    actionType,
    task: normalized.tasks.find((task) => task.taskId === taskId),
    group: null
  }
}

function findConfirmationAction(normalized, actionType, taskId) {
  return normalized.confirmationGroups.find((action) =>
    normalizeActionType(action) === actionType
    && String(action.target_task_id || action.targetTaskId || '').trim() === taskId
  ) || normalized.confirmationGroups.find((action) => normalizeActionType(action) === actionType)
}

function findAttachmentGroupForTask(normalized, taskId) {
  return normalized.attachmentGroups.find((group) => group.targetTaskId === taskId)
    || normalized.attachmentGroups[0]
    || null
}

function normalizeActionType(action) {
  return String(action?.action_type || action?.actionType || '').trim()
}

function buildStewardExecutionSummary(normalized) {
  const attachmentCount = normalized.attachmentGroups
    .reduce((total, group) => total + group.attachmentNames.length, 0)
  const summary = [`我识别到 **${normalized.tasks.length} 个待处理任务**`]
  if (attachmentCount) {
    summary.push(`并形成 ${attachmentCount} 份附件的归集建议`)
  }
  summary.push(`。${buildTaskOrderDescription(normalized)}`)
  return summary.join('')
}

function buildOrderedStewardTasks(normalized, nextTask = null) {
  if (!nextTask?.taskId) {
    return normalized.tasks
  }
  return [
    nextTask,
    ...normalized.tasks.filter((task) => task.taskId !== nextTask.taskId)
  ]
}

function buildTaskOrderVerb(index) {
  if (index === 0) {
    return '先'
  }
  if (index === 1) {
    return '再'
  }
  return '然后'
}

function buildTaskOrderTarget(task) {
  const title = task.title || task.taskTypeLabel
  if (task.taskType === 'expense_application') {
    return `整理“${title}”`
  }
  if (task.taskType === 'reimbursement') {
    return `核对“${title}”`
  }
  return `处理“${title}”`
}

function buildTaskOrderActionDescription(task) {
  const agent = task.assignedAgentLabel || '对应助手'
  if (task.taskType === 'expense_application') {
    // 申请类：先给行动，再说目的，主语后置
    return `这步交给${agent}——先把申请单草稿拉出来给您过目，没问题了再往下走。`
  }
  if (task.taskType === 'reimbursement') {
    if (isGenericReimbursementTask(task)) {
      // 通用报销：换个句式，省掉主语，突出"先定方向"
      return `报销还差一个关键信息：具体是哪类费用。${agent}会先带您把报销场景定下来，再逐项补事由、时间、金额和票据。`
    }
    // 有明确场景的报销：直接说动作，不绕弯
    return `票据、金额和制度口径，${agent}会一并核清楚；前一步确认后才会继续，不会越级往下推。`
  }
  // 兜底：用"等您点头"的语气，区别于上面三条
  return `${agent}先把能核对的结果摆出来，真正动手前仍会等您点头。`
}

function buildStewardPlanFriendlyIntro(normalized) {
  const taskCountText = normalized.tasks.length > 1
    ? `${normalized.tasks.length} 个相关事项`
    : '1 个事项'
  return `我先看了一下，您这次主要是 **${taskCountText}**。为了不让步骤混在一起，我会先把要做的事拆开，让您每一步都能看清楚、确认后再继续。`
}

function buildTaskOrderDescription(normalized) {
  const hasApplication = normalized.tasks.some((task) => task.taskType === 'expense_application')
  const hasReimbursement = normalized.tasks.some((task) => task.taskType === 'reimbursement')
  if (hasApplication && hasReimbursement) {
    return '处理顺序是：先创建申请单，再引导填写报销单。'
  }
  if (hasApplication) {
    return '我会先引导创建申请单，并等待您确认。'
  }
  if (hasReimbursement) {
    return '我会引导填写报销单，并等待您确认。'
  }
  return '我会按识别顺序逐项推进，并在执行前等待您确认。'
}

function buildNextTaskLead(task) {
  if (task.taskType === 'expense_application') {
    return `先创建“${task.title || task.taskTypeLabel}”`
  }
  if (task.taskType === 'reimbursement') {
    return `继续填写“${task.title || task.taskTypeLabel}”`
  }
  return `处理“${task.title || task.taskTypeLabel}”`
}

function buildNextActionLabel(actionType, task = null) {
  if (actionType === 'confirm_create_application') {
    return '确定，先创建申请单'
  }
  if (actionType === 'confirm_attachment_group') {
    return '确定，确认附件归集'
  }
  if (isGenericReimbursementTask(task)) {
    return '确定，选择报销场景'
  }
  return '确定，继续填写报销单'
}

function buildNextActionDescription(actionType, normalized, task, group) {
  const remainingCount = normalized.tasks.filter((item) => item.taskId !== task?.taskId).length
  if (actionType === 'confirm_create_application') {
    return remainingCount > 0
      ? '申请助手会先生成申请单核对结果，完成后再继续引导后续报销。'
      : '申请助手会生成申请单核对结果，入库前仍需确认。'
  }
  if (actionType === 'confirm_attachment_group') {
    return group?.attachmentNames?.length
      ? `先归集 ${group.attachmentNames.length} 份附件，再进入报销核对。`
      : '先确认附件归集，再进入报销核对。'
  }
  return group?.attachmentNames?.length
    ? `报销助手会带入 ${group.attachmentNames.length} 份相关附件生成核对结果。`
    : isGenericReimbursementTask(task)
      ? '先进入报销助手选择具体费用类型，再按场景补齐事由、时间、金额和票据。'
      : '报销助手会根据当前任务生成报销核对结果。'
}

function isGenericReimbursementTask(task) {
  if (!task || task.taskType !== 'reimbursement') {
    return false
  }
  const fields = task.ontologyFields || {}
  const expenseType = String(fields.expense_type || '').trim()
  const hasSpecificField = ['time_range', 'location', 'amount', 'attachments', 'transport_mode']
    .some((key) => String(fields[key] || '').trim())
    || isSpecificReimbursementReason(fields.reason)
  return !hasSpecificField && (!expenseType || expenseType === 'other')
}

function isSpecificReimbursementReason(value) {
  const text = String(value || '').trim().replace(/\s+/g, '')
  if (!text) {
    return false
  }
  return !/^(?:我想要|我想|我要|还需要|需要|请帮我|帮我)?报销(?:费用|报销单|报销流程)?$/.test(text)
}

function buildStewardCarryText(actionType, task, group, normalized = null) {
  if (actionType === 'confirm_attachment_group' && group) {
    return [
      `我确认将以下附件归集为${group.sceneLabel || '当前报销任务'}，请继续整理报销核对信息。`,
      `附件：${group.attachmentNames.join('、') || '待确认'}`,
      group.excludedAttachmentNames.length
        ? `暂不归集：${group.excludedAttachmentNames.join('、')}`
        : ''
    ].filter(Boolean).join('\n')
  }

  if (!task) {
    return '我确认继续处理这项财务任务，请按现有流程核对信息。'
  }
  if (actionType === 'confirm_create_reimbursement_draft' && isGenericReimbursementTask(task)) {
    return '我要报销'
  }

  const fields = formatStewardOntologyFields(task.ontologyFields || {}, task.taskType)
  const missingFields = formatStewardMissingFieldList(
    task.missingFields || [],
    task.taskType,
    { includeHints: false }
  )
  const lines = [
    actionType === 'confirm_create_application'
      ? `小财管家已完成意图识别，请先创建申请单：${task.title || task.taskTypeLabel}。`
      : `小财管家已完成意图识别，请继续填写报销单：${task.title || task.taskTypeLabel}。`,
    task.summary ? `任务摘要：${task.summary}` : '',
    fields ? `已识别信息：${fields}` : '',
    group?.attachmentNames?.length ? `相关附件：${group.attachmentNames.join('、')}` : '',
    group?.excludedAttachmentNames?.length ? `暂不归集附件：${group.excludedAttachmentNames.join('、')}` : '',
    missingFields ? `还需要补充：${missingFields}` : '',
    actionType === 'confirm_create_application'
      ? missingFields
        ? '请先追问上述缺失信息，不要直接生成申请单核对表，也不要替用户默认填写。'
        : '请直接生成申请单核对结果；信息足够时生成申请单，但在入库或提交审批前仍需让我确认。'
      : missingFields
        ? '请先追问上述缺失信息，不要直接生成报销核对结果，也不要替用户默认填写。'
        : '请直接生成报销核对结果；需要创建草稿、绑定附件或提交审批前仍需让我确认。'
  ]
  const remainingTaskText = normalized ? buildRemainingTaskText(normalized, task.taskId) : ''
  if (remainingTaskText) {
    lines.push(remainingTaskText)
  }
  return lines.filter(Boolean).join('\n')
}

function buildRemainingTaskText(normalized, currentTaskId) {
  const remainingTasks = normalized.tasks.filter((task) => task.taskId !== currentTaskId)
  if (!remainingTasks.length) {
    return ''
  }
  const taskLines = remainingTasks.map((task, index) =>
    `${index + 1}. ${task.title || task.taskTypeLabel}（${task.assignedAgentLabel}）：${task.summary || '待继续核对'}`
  )
  return [
    '当前步骤完成后，请继续引导我处理后续任务：',
    ...taskLines
  ].join('\n')
}

function buildRemainingTaskPayload(normalized, currentTaskId) {
  return normalized.tasks
    .filter((task) => task.taskId !== currentTaskId)
    .map((task) => buildStewardTaskPayload(task))
}

function buildStewardTaskPayload(task) {
  if (!task) {
    return null
  }
  return {
    task_id: task.taskId || task.task_id || '',
    task_type: task.taskType || task.task_type || '',
    title: task.title || '',
    summary: task.summary || '',
    assigned_agent: task.assignedAgent || task.assigned_agent || '',
    requested_action: task.requestedAction || task.requested_action || '',
    ontology_fields: task.ontologyFields || task.ontology_fields || {},
    missing_fields: task.missingFields || task.missing_fields || [],
    action_steps: task.actionSteps || task.action_steps || []
  }
}
