import { ref } from 'vue'

import {
  buildApplicationTemplatePreview,
  buildLocalApplicationPreviewMessage
} from '../../utils/expenseApplicationPreview.js'
import {
  REIMBURSEMENT_LIST_PREVIEW_PARAMS,
  fetchExpenseClaims
} from '../../services/reimbursements.js'
import {
  buildRequiredApplicationActions,
  buildRequiredApplicationMissingText,
  buildRequiredApplicationSelectionText,
  filterRequiredApplicationCandidates,
  requiresApplicationBeforeReimbursement
} from './travelReimbursementApplicationLinkModel.js'
import {
  GUIDED_ACTION_START_APPLICATION,
  GUIDED_ACTION_CONFIRM_REIMBURSEMENT_REVIEW,
  GUIDED_ACTION_CONTINUE_FILLING,
  GUIDED_ACTION_OPEN_TRAVEL_CALCULATOR,
  GUIDED_ACTION_PROCESS_INTERRUPTION,
  GUIDED_ACTION_SELECT_EXPENSE_TYPE,
  GUIDED_ACTION_SELECT_REQUIRED_APPLICATION,
  GUIDED_ACTION_SELECT_QUERY_MODE,
  GUIDED_ACTION_SELECT_QUERY_STATUS,
  GUIDED_ACTION_START_REIMBURSEMENT,
  GUIDED_ACTION_START_STATUS_QUERY,
  GUIDED_FLOW_MODE_REIMBURSEMENT,
  GUIDED_FLOW_MODE_STATUS_QUERY,
  applyGuidedReimbursementAnswer,
  buildGuidedExpenseTypeActions,
  buildGuidedInterruptionActions,
  buildGuidedInterruptionText,
  buildGuidedQueryModeActions,
  buildGuidedQueryPromptText,
  buildGuidedQueryStatusActions,
  buildGuidedReimbursementStartText,
  buildGuidedReimbursementSummaryText,
  buildGuidedReviewConfirmationActions,
  buildGuidedReviewSubmitOptions,
  buildGuidedStatusQueryStartText,
  buildGuidedStatusQueryText,
  buildGuidedStepPromptText,
  createEmptyGuidedFlowState,
  createGuidedReimbursementState,
  createGuidedStatusQueryState,
  getCurrentGuidedStep,
  isGuidedFlowActive,
  isGuidedReimbursementReadyForReview,
  normalizeGuidedFlowState,
  resolveGuidedExpenseTypeFromText,
  resolveGuidedQueryModeFromText,
  selectGuidedExpenseType,
  selectGuidedRequiredApplication,
  selectGuidedQueryMode,
  shouldConfirmGuidedInterruption,
  waitForGuidedApplicationSelection
} from './travelReimbursementGuidedFlowModel.js'

function normalizeText(value) {
  return String(value || '').trim()
}

function buildFileNames(files) {
  return Array.from(files || [])
    .map((file) => normalizeText(file?.name))
    .filter(Boolean)
}

function mergePendingFiles(currentFiles, nextFiles) {
  const merged = [...Array.from(currentFiles || [])]
  Array.from(nextFiles || []).forEach((file) => {
    const name = normalizeText(file?.name)
    if (!name) return
    const duplicated = merged.some((item) => normalizeText(item?.name) === name && Number(item?.size || 0) === Number(file?.size || 0))
    if (!duplicated) {
      merged.push(file)
    }
  })
  return merged
}

export function useTravelReimbursementGuidedFlow({
  guidedFlowState,
  messages,
  composerDraft,
  attachedFiles,
  composerBusinessTimeTags,
  composerBusinessTimeDraftTouched,
  fileInputRef,
  submitting,
  reviewActionBusy,
  sessionSwitchBusy,
  createMessage,
  nextTick,
  scrollToBottom,
  persistSessionState,
  clearAttachedFiles,
  adjustComposerTextareaHeight,
  buildComposerBusinessTimeContext,
  openTravelCalculator,
  lockSuggestedActionMessage,
  submitExistingComposer,
  currentUser,
  refreshCurrentUserFromBackend,
  toast
}) {
  const guidedPendingFiles = ref([])

  function persistAndScroll() {
    persistSessionState()
    nextTick(() => {
      adjustComposerTextareaHeight?.()
      scrollToBottom?.()
    })
  }

  function clearComposerRuntime() {
    composerDraft.value = ''
    clearAttachedFiles?.()
    if (fileInputRef?.value) {
      fileInputRef.value.value = ''
    }
    if (composerBusinessTimeTags) {
      composerBusinessTimeTags.value = []
    }
    if (composerBusinessTimeDraftTouched) {
      composerBusinessTimeDraftTouched.value = false
    }
  }

  function pushAssistant(text, extras = {}) {
    messages.value.push(createMessage('assistant', text, [], extras))
  }

  function pushUser(text, attachmentNames = []) {
    const normalizedText = normalizeText(text)
    messages.value.push(createMessage('user', normalizedText || `上传 ${attachmentNames.length} 份附件`, attachmentNames))
  }

  function resetGuidedFlowState() {
    guidedFlowState.value = createEmptyGuidedFlowState()
    guidedPendingFiles.value = []
  }

  function startGuidedReimbursement() {
    guidedFlowState.value = createGuidedReimbursementState()
    guidedPendingFiles.value = []
    pushAssistant(buildGuidedReimbursementStartText(), {
      meta: ['引导式报销'],
      suggestedActions: buildGuidedExpenseTypeActions()
    })
    persistAndScroll()
  }

  async function resolveApplicationPreviewUser() {
    const user = currentUser?.value || {}
    if (String(user.position || '').trim() || typeof refreshCurrentUserFromBackend !== 'function') {
      return user
    }

    await refreshCurrentUserFromBackend({ silent: true })
    return currentUser?.value || user
  }

  async function startGuidedApplicationTemplate() {
    resetGuidedFlowState()
    const applicationPreview = buildApplicationTemplatePreview(await resolveApplicationPreviewUser())
    pushAssistant(buildLocalApplicationPreviewMessage(applicationPreview), {
      meta: ['申请模板'],
      applicationPreview
    })
    persistAndScroll()
  }

  function startGuidedStatusQuery() {
    guidedFlowState.value = createGuidedStatusQueryState()
    guidedPendingFiles.value = []
    pushAssistant(buildGuidedStatusQueryStartText(), {
      meta: ['引导式查询'],
      suggestedActions: buildGuidedQueryModeActions()
    })
    persistAndScroll()
  }

  async function handleGuidedShortcut(shortcut) {
    const actionType = normalizeText(shortcut?.action)
    if (actionType === GUIDED_ACTION_START_APPLICATION) {
      await startGuidedApplicationTemplate()
      return true
    }
    if (actionType === GUIDED_ACTION_START_REIMBURSEMENT) {
      startGuidedReimbursement()
      return true
    }
    if (actionType === GUIDED_ACTION_START_STATUS_QUERY) {
      startGuidedStatusQuery()
      return true
    }
    if (actionType === GUIDED_ACTION_OPEN_TRAVEL_CALCULATOR) {
      openTravelCalculator?.()
      pushAssistant('差旅计算器已打开。您可以直接填写目的地、天数和金额，我会按规则中心标准帮您测算。', {
        meta: ['差旅计算器']
      })
      persistAndScroll()
      return true
    }
    return false
  }

  function buildAnswerText(rawText, state) {
    const text = normalizeText(rawText)
    if (text) {
      return text
    }
    const currentStep = getCurrentGuidedStep(state)
    if (currentStep?.key === 'time_range') {
      const businessTimeContext = buildComposerBusinessTimeContext?.()
      return normalizeText(businessTimeContext?.time_range || businessTimeContext?.business_time)
    }
    return ''
  }

  function pushNextReimbursementPrompt() {
    pushAssistant(buildGuidedStepPromptText(guidedFlowState.value), {
      meta: ['引导式报销']
    })
  }

  function pushReimbursementSummary() {
    pushAssistant(buildGuidedReimbursementSummaryText(guidedFlowState.value), {
      meta: ['待生成报销草稿'],
      suggestedActions: buildGuidedReviewConfirmationActions()
    })
  }

  async function selectExpenseTypeForGuidedReimbursement(currentState, expenseType, options = {}) {
    const nextState = options.pendingSceneSelection
      ? {
          ...currentState,
          values: {
            ...currentState.values,
            pending_scene_original_message: normalizeText(options.pendingSceneSelection.originalMessage),
            pending_scene_expense_type_label: normalizeText(options.pendingSceneSelection.expenseTypeLabel)
          }
        }
      : currentState

    if (!requiresApplicationBeforeReimbursement(expenseType)) {
      guidedFlowState.value = selectGuidedExpenseType(nextState, expenseType)
      pushNextReimbursementPrompt()
      return
    }

    let claimsPayload = null
    try {
      claimsPayload = await fetchExpenseClaims(REIMBURSEMENT_LIST_PREVIEW_PARAMS)
    } catch (error) {
      console.warn('Fetch reimbursement applications failed:', error)
      guidedFlowState.value = createEmptyGuidedFlowState()
      pushAssistant('查询可关联申请单时出现异常，请稍后再试。为避免直接报销，我先暂停当前流程。', {
        meta: ['申请单查询失败']
      })
      toast?.('申请单查询失败，请稍后再试')
      return
    }

    const applications = filterRequiredApplicationCandidates(claimsPayload, expenseType, currentUser?.value || {})
    if (!applications.length) {
      guidedFlowState.value = createEmptyGuidedFlowState()
      pushAssistant(buildRequiredApplicationMissingText(expenseType), {
        meta: ['缺少可关联申请单']
      })
      return
    }

    guidedFlowState.value = waitForGuidedApplicationSelection(nextState, expenseType, applications)
    pushAssistant(buildRequiredApplicationSelectionText(expenseType, applications), {
      meta: ['等待关联申请单'],
      suggestedActions: buildRequiredApplicationActions(applications, GUIDED_ACTION_SELECT_REQUIRED_APPLICATION)
    })
  }

  function buildPendingSceneSubmitOptions(state) {
    const current = normalizeGuidedFlowState(state)
    const originalMessage = normalizeText(current.values.pending_scene_original_message)
    const expenseTypeLabel = normalizeText(current.values.pending_scene_expense_type_label)
    const applicationNo = normalizeText(current.values.application_claim_no)
    const applicationId = normalizeText(current.values.application_claim_id)
    const applicationReason = normalizeText(current.values.application_reason)
    const applicationLocation = normalizeText(current.values.application_location)
    const applicationBusinessTime = normalizeText(current.values.application_business_time)
    const applicationTransportMode = normalizeText(current.values.application_transport_mode)
    if (!originalMessage || !expenseTypeLabel || !applicationNo) {
      return null
    }

    const rawText = [
      originalMessage,
      `用户选择报销场景：${expenseTypeLabel}`,
      `关联申请单：${applicationNo}`
    ].join('\n')

    return {
      rawText,
      userText: `关联申请单 ${applicationNo}`,
      pendingText: `已关联申请单，正在生成${expenseTypeLabel}草稿...`,
      systemGenerated: true,
      skipUserMessage: true,
      extraContext: {
        draft_claim_id: '',
        review_action: 'save_draft',
        user_input_text: originalMessage,
        expense_scene_selection: {
          expense_type: current.expenseType || 'other',
          expense_type_label: expenseTypeLabel,
          original_message: originalMessage,
          application_claim_id: applicationId,
          application_claim_no: applicationNo
        },
        review_form_values: {
          expense_type: expenseTypeLabel,
          reason: applicationReason,
          location: applicationLocation,
          time_range: applicationBusinessTime,
          transport_mode: applicationTransportMode,
          amount: '',
          application_claim_id: applicationId,
          application_claim_no: applicationNo,
          application_reason: applicationReason,
          application_location: applicationLocation,
          application_amount: current.values.application_amount || '',
          application_amount_label: current.values.application_amount_label || '',
          application_business_time: applicationBusinessTime,
          application_days: current.values.application_days || '',
          application_transport_mode: current.values.application_transport_mode || '',
          application_lodging_daily_cap: current.values.application_lodging_daily_cap || '',
          application_subsidy_daily_cap: current.values.application_subsidy_daily_cap || '',
          application_transport_policy: current.values.application_transport_policy || '',
          application_policy_estimate: current.values.application_policy_estimate || '',
          application_rule_name: current.values.application_rule_name || '',
          application_rule_version: current.values.application_rule_version || ''
        }
      }
    }
  }

  async function handleReimbursementAnswer(answerText, files) {
    const currentState = normalizeGuidedFlowState(guidedFlowState.value)
    const currentStep = getCurrentGuidedStep(currentState)
    const fileNames = buildFileNames(files)

    if (isGuidedReimbursementReadyForReview(currentState) && fileNames.length) {
      const mergedFiles = mergePendingFiles(guidedPendingFiles.value, files)
      guidedPendingFiles.value = mergedFiles
      const submitOptions = {
        ...buildGuidedReviewSubmitOptions(currentState, mergedFiles),
        skipDraftAssociationPrompt: true,
        skipUserMessage: true,
        pendingText: '已关联申请单，正在识别票据并生成报销草稿...'
      }
      resetGuidedFlowState()
      persistAndScroll()
      await submitExistingComposer(submitOptions)
      return
    }

    if (currentState.stepKey === 'expense_type') {
      const expenseType = resolveGuidedExpenseTypeFromText(answerText)
      if (!expenseType) {
        pushAssistant('我还需要先确认报销类型。请点击下面最贴近的费用场景后，我再继续问下一项。', {
          meta: ['等待选择报销类型'],
          suggestedActions: buildGuidedExpenseTypeActions()
        })
        return
      }
      await selectExpenseTypeForGuidedReimbursement(currentState, expenseType)
      return
    }

    if (currentState.stepKey === 'application_selection') {
      pushAssistant('请先点击上方列出的申请单完成关联。关联后，我会直接进入生成报销草稿。', {
        meta: ['等待关联申请单'],
        suggestedActions: buildRequiredApplicationActions(
          currentState.applicationCandidates,
          GUIDED_ACTION_SELECT_REQUIRED_APPLICATION
        )
      })
      return
    }

    if (!currentStep) {
      pushAssistant(buildGuidedReimbursementStartText(), {
        meta: ['引导式报销'],
        suggestedActions: buildGuidedExpenseTypeActions()
      })
      return
    }

    if (!answerText && fileNames.length && currentStep.key !== 'attachments') {
      guidedPendingFiles.value = mergePendingFiles(guidedPendingFiles.value, files)
      pushAssistant([
        `我已先记录 ${fileNames.length} 份附件。`,
        '',
        `当前还需要补充：${currentStep.summaryLabel}。`,
        currentStep.prompt
      ].join('\n'), {
        meta: ['已记录附件']
      })
      return
    }

    if (fileNames.length) {
      guidedPendingFiles.value = mergePendingFiles(guidedPendingFiles.value, files)
    }
    guidedFlowState.value = applyGuidedReimbursementAnswer(currentState, answerText, fileNames)
    if (isGuidedReimbursementReadyForReview(guidedFlowState.value)) {
      pushReimbursementSummary()
      return
    }
    pushNextReimbursementPrompt()
  }

  async function runStatusQuery(queryText, skipUserMessage = true) {
    const normalizedQuery = normalizeText(queryText)
    resetGuidedFlowState()
    clearComposerRuntime()
    persistAndScroll()
    if (!normalizedQuery) {
      return true
    }
    await submitExistingComposer({
      rawText: normalizedQuery,
      userText: normalizedQuery,
      pendingText: '正在查询单据状态...',
      skipUserMessage
    })
    return true
  }

  async function handleStatusQueryAnswer(answerText) {
    const currentState = normalizeGuidedFlowState(guidedFlowState.value)
    if (currentState.stepKey === 'query_mode') {
      const queryMode = resolveGuidedQueryModeFromText(answerText)
      if (!queryMode) {
        pushAssistant(buildGuidedStatusQueryStartText(), {
          meta: ['引导式查询'],
          suggestedActions: buildGuidedQueryModeActions()
        })
        return true
      }
      guidedFlowState.value = selectGuidedQueryMode(currentState, queryMode)
      const actions = guidedFlowState.value.stepKey === 'status_value' ? buildGuidedQueryStatusActions() : []
      pushAssistant(buildGuidedQueryPromptText(guidedFlowState.value), {
        meta: ['引导式查询'],
        suggestedActions: actions
      })
      return true
    }

    const queryText = buildGuidedStatusQueryText(currentState, answerText)
    return runStatusQuery(queryText, true)
  }

  async function handleGuidedComposerSubmit(options = {}) {
    const currentState = normalizeGuidedFlowState(guidedFlowState.value)
    if (!isGuidedFlowActive(currentState)) {
      return false
    }
    if (options.systemGenerated || normalizeText(options.extraContext?.review_action)) {
      return false
    }
    if (submitting.value || reviewActionBusy.value || sessionSwitchBusy.value) {
      return true
    }

    const files = Array.from(options.files ?? attachedFiles.value ?? [])
    const fileNames = buildFileNames(files)
    const answerText = buildAnswerText(options.rawText ?? composerDraft.value, currentState)
    if (!answerText && !fileNames.length) {
      return true
    }

    pushUser(answerText, fileNames)
    if (shouldConfirmGuidedInterruption(answerText, currentState) && !fileNames.length) {
      guidedFlowState.value = {
        ...currentState,
        pendingInterruptionText: answerText
      }
      pushAssistant(buildGuidedInterruptionText(answerText), {
        meta: ['等待确认是否打断'],
        suggestedActions: buildGuidedInterruptionActions()
      })
      clearComposerRuntime()
      persistAndScroll()
      return true
    }

    if (currentState.mode === GUIDED_FLOW_MODE_REIMBURSEMENT) {
      await handleReimbursementAnswer(answerText, files)
      clearComposerRuntime()
      persistAndScroll()
      return true
    }

    if (currentState.mode === GUIDED_FLOW_MODE_STATUS_QUERY) {
      clearComposerRuntime()
      persistAndScroll()
      await handleStatusQueryAnswer(answerText)
      return true
    }

    return false
  }

  async function handleGuidedSuggestedAction(message, action) {
    const actionType = normalizeText(action?.action_type)
    if (!actionType) {
      return false
    }
    const guidedActionTypes = new Set([
      GUIDED_ACTION_SELECT_EXPENSE_TYPE,
      GUIDED_ACTION_SELECT_REQUIRED_APPLICATION,
      GUIDED_ACTION_CONFIRM_REIMBURSEMENT_REVIEW,
      GUIDED_ACTION_CONTINUE_FILLING,
      GUIDED_ACTION_PROCESS_INTERRUPTION,
      GUIDED_ACTION_SELECT_QUERY_MODE,
      GUIDED_ACTION_SELECT_QUERY_STATUS
    ])
    if (!guidedActionTypes.has(actionType)) {
      return false
    }
    if (submitting.value || reviewActionBusy.value || sessionSwitchBusy.value || message?.suggestedActionsLocked) {
      return true
    }
    if (!lockSuggestedActionMessage(message, action)) {
      return true
    }

    if (actionType === GUIDED_ACTION_SELECT_EXPENSE_TYPE) {
      const expenseType = normalizeText(action?.payload?.expense_type)
      const expenseTypeLabel = normalizeText(action?.payload?.expense_type_label || action?.label)
      pushUser(`选择${expenseTypeLabel || '报销类型'}`)
      await selectExpenseTypeForGuidedReimbursement(guidedFlowState.value, expenseType)
      persistAndScroll()
      return true
    }

    if (actionType === GUIDED_ACTION_SELECT_REQUIRED_APPLICATION) {
      const applicationNo = normalizeText(action?.payload?.application_claim_no || action?.label)
      pushUser(`关联申请单 ${applicationNo || ''}`.trim())
      guidedFlowState.value = selectGuidedRequiredApplication(guidedFlowState.value, action?.payload || {})
      const pendingSceneSubmitOptions = buildPendingSceneSubmitOptions(guidedFlowState.value)
      if (pendingSceneSubmitOptions) {
        resetGuidedFlowState()
        persistAndScroll()
        await submitExistingComposer(pendingSceneSubmitOptions)
        return true
      }
      if (isGuidedReimbursementReadyForReview(guidedFlowState.value)) {
        pushReimbursementSummary()
        persistAndScroll()
        return true
      }
      pushNextReimbursementPrompt()
      persistAndScroll()
      return true
    }

    if (actionType === GUIDED_ACTION_CONFIRM_REIMBURSEMENT_REVIEW) {
      const submitOptions = buildGuidedReviewSubmitOptions(guidedFlowState.value, guidedPendingFiles.value)
      resetGuidedFlowState()
      persistAndScroll()
      await submitExistingComposer(submitOptions)
      return true
    }

    if (actionType === GUIDED_ACTION_CONTINUE_FILLING) {
      const pendingState = {
        ...normalizeGuidedFlowState(guidedFlowState.value),
        pendingInterruptionText: ''
      }
      guidedFlowState.value = pendingState
      if (pendingState.mode === GUIDED_FLOW_MODE_STATUS_QUERY) {
        pushAssistant(buildGuidedQueryPromptText(pendingState), {
          meta: ['引导式查询'],
          suggestedActions: pendingState.stepKey === 'status_value' ? buildGuidedQueryStatusActions() : []
        })
      } else {
        pushNextReimbursementPrompt()
      }
      persistAndScroll()
      return true
    }

    if (actionType === GUIDED_ACTION_PROCESS_INTERRUPTION) {
      const pendingText = normalizeText(guidedFlowState.value?.pendingInterruptionText)
      resetGuidedFlowState()
      persistAndScroll()
      await submitExistingComposer({
        rawText: pendingText,
        userText: pendingText,
        pendingText: '正在处理您的问题...',
        skipUserMessage: true
      })
      return true
    }

    if (actionType === GUIDED_ACTION_SELECT_QUERY_MODE) {
      const queryMode = normalizeText(action?.payload?.query_mode)
      const queryModeLabel = normalizeText(action?.payload?.query_mode_label || action?.label)
      guidedFlowState.value = selectGuidedQueryMode(guidedFlowState.value, queryMode)
      pushUser(`选择${queryModeLabel || '查询方式'}`)
      pushAssistant(buildGuidedQueryPromptText(guidedFlowState.value), {
        meta: ['引导式查询'],
        suggestedActions: guidedFlowState.value.stepKey === 'status_value' ? buildGuidedQueryStatusActions() : []
      })
      persistAndScroll()
      return true
    }

    if (actionType === GUIDED_ACTION_SELECT_QUERY_STATUS) {
      const statusLabel = normalizeText(action?.payload?.query_status_label || action?.label)
      pushUser(`选择${statusLabel || '单据状态'}`)
      const queryText = buildGuidedStatusQueryText(guidedFlowState.value, statusLabel)
      await runStatusQuery(queryText, true)
      return true
    }

    return false
  }

  async function handleSceneSelectionApplicationGate(message, action) {
    const actionType = normalizeText(action?.action_type)
    if (actionType !== 'select_expense_type') {
      return false
    }
    const actionPayload = action?.payload && typeof action.payload === 'object' ? action.payload : {}
    const expenseType = normalizeText(actionPayload.expense_type)
    if (!requiresApplicationBeforeReimbursement(expenseType)) {
      return false
    }
    const expenseTypeLabel = normalizeText(actionPayload.expense_type_label || action?.label)
    const originalMessage = normalizeText(actionPayload.original_message || message?.text)
    if (!expenseTypeLabel || !originalMessage) {
      return false
    }
    if (!lockSuggestedActionMessage(message, action)) {
      return true
    }

    guidedPendingFiles.value = []
    pushUser(`选择${expenseTypeLabel}`)
    await selectExpenseTypeForGuidedReimbursement(createGuidedReimbursementState(), expenseType, {
      pendingSceneSelection: {
        originalMessage,
        expenseTypeLabel
      }
    })
    persistAndScroll()
    return true
  }

  return {
    handleGuidedShortcut,
    handleGuidedComposerSubmit,
    handleGuidedSuggestedAction,
    handleSceneSelectionApplicationGate,
    resetGuidedFlowState
  }
}
