import {
  fetchStewardPlan,
  fetchStewardPlanStream
} from '../../services/steward.js'
import {
  REIMBURSEMENT_LIST_PREVIEW_PARAMS,
  fetchExpenseClaims
} from '../../services/reimbursements.js'
import {
  buildStewardPlanMessageText,
  buildStewardPlanRequest,
  buildStewardSuggestedActions,
  normalizeStewardPlan
} from '../../views/scripts/stewardPlanModel.js'
import {
  buildRequiredApplicationActions,
  buildRequiredApplicationMissingText,
  buildRequiredApplicationSelectionText,
  filterRequiredApplicationCandidates
} from '../../views/scripts/travelReimbursementApplicationLinkModel.js'
import {
  buildInlineAttachmentOcrDetails
} from './workbenchAiMessageModel.js'
import {
  completeWorkbenchAiThinkingEvents,
  mergeWorkbenchAiThinkingEvents
} from './workbenchAiPlanningThinkingModel.js'

function shouldCheckAiRequiredApplicationGate(prompt) {
  const compact = String(prompt || '').replace(/\s+/g, '')
  if (!compact || !/(出差|差旅|部署|实施|支撑|支持|协助|拜访|调研|驻场|上线|验收)/.test(compact)) {
    return false
  }
  if (!/\d{1,2}月\d{1,2}|昨天|前天|上周|上月/.test(compact)) {
    return false
  }
  return !/(申请|报销|草稿|提交|审批|保存|发起|创建)/.test(compact)
}

function serializeRequiredApplicationCandidate(candidate = {}) {
  return {
    id: String(candidate.id || '').trim(),
    claim_no: String(candidate.claim_no || '').trim(),
    reason: String(candidate.reason || '').trim(),
    location: String(candidate.location || '').trim(),
    business_time: String(candidate.business_time || '').trim(),
    status_label: String(candidate.status_label || '').trim()
  }
}

function resolveRequiredApplicationGateContinuationFlow(normalizedPlan) {
  if (String(normalizedPlan?.pendingFlowConfirmation?.status || '').trim() !== 'pending') {
    return null
  }
  const flows = Array.isArray(normalizedPlan?.candidateFlows) ? normalizedPlan.candidateFlows : []
  const applicationFlow = flows.find((flow) => flow.flowId === 'travel_application')
  if (flows.length === 1 && applicationFlow && /先发起出差申请/.test(applicationFlow.label)) {
    return applicationFlow
  }
  return flows.find((flow) => (
    flow.flowId === 'travel_reimbursement' &&
    /关联已有申请单/.test(flow.label)
  )) || null
}

function buildAiRequiredApplicationGateAutoMessage(normalizedPlan, flow) {
  const baseText = buildStewardPlanMessageText({
    planStatus: normalizedPlan?.planStatus,
    nextAction: normalizedPlan?.nextAction,
    summary: normalizedPlan?.summary,
    pendingFlowConfirmation: normalizedPlan?.pendingFlowConfirmation,
    candidateFlows: normalizedPlan?.candidateFlows
  })
  const contextText = String(baseText || '')
    .split(/\n\n1\. \*\*/)[0]
    .trim()
    .replace('### 需要先确认流程方向', '### 我已先查询申请单')
  if (flow?.flowId === 'travel_application') {
    return [
      contextText || baseText,
      '这类操作需要您手动确认。请点击下方 **确认发起出差申请**，我会在当前对话里生成完整申请表，并把已识别的信息自动预填。'
    ].filter(Boolean).join('\n\n')
  }
  if (flow?.flowId === 'travel_reimbursement') {
    return [
      contextText || baseText,
      '这类操作需要您手动确认。请点击下方 **确认关联已有申请单**，我会继续查询并展示可关联单据。'
    ].filter(Boolean).join('\n\n')
  }
  return baseText
}

function buildAiRequiredApplicationGateSuggestedActions(flow, prompt = '') {
  if (flow.flowId === 'travel_application') {
    return [{
      label: '确认发起出差申请',
      description: '确认后生成完整申请表，并预填已识别的时间、地点和事由。',
      icon: 'mdi mdi-file-plus-outline',
      action_type: 'ai_application_start_inline',
      payload: {
        expense_type: 'travel',
        expense_type_label: '差旅费',
        carry_text: prompt
      }
    }]
  }
  if (flow.flowId === 'travel_reimbursement') {
    return [{
      label: '确认关联已有申请单',
      description: '确认后查询您名下可关联的差旅申请单，并进入关联步骤。',
      icon: 'mdi mdi-link-variant',
      action_type: 'steward_confirm_flow',
      payload: {
        steward_confirm_flow: true,
        flow_id: 'travel_reimbursement',
        expense_type: 'travel',
        expense_type_label: '差旅费',
        carry_text: prompt
      }
    }]
  }
  return []
}

function normalizeStreamThinkingEvent(event = {}) {
  const data = event?.data && typeof event.data === 'object' ? event.data : {}
  const eventId = String(data.event_id || data.eventId || data.stage || `thinking-${Date.now()}`).trim()
  return {
    eventId,
    stage: String(data.stage || '').trim(),
    title: String(data.title || '小财管家正在分析').trim(),
    content: String(data.content || '').trim(),
    status: String(data.status || 'running').trim() || 'running'
  }
}

export function useWorkbenchAiStewardFlow({
  activeConversationTitle,
  collectAiModeReceiptContext,
  conversationId,
  conversationMessages,
  createInlineMessage,
  currentUser,
  deleteAiWorkbenchConversation,
  emit,
  handleAiDocumentQueryIntent,
  inlineConversationAutoScrollPinned,
  persistCurrentConversation,
  replaceInlineMessage,
  resolveInlineThinkingEvents,
  scrollInlineConversationToBottom,
  sending,
  stewardState,
  streamInlineAssistantContent,
  updateInlineMessageContent,
  appendInlineMessageContent,
  toast
}) {
  async function attachAiRequiredApplicationGate(planRequest, prompt) {
    if (!shouldCheckAiRequiredApplicationGate(prompt)) {
      return planRequest
    }

    try {
      const claims = await fetchExpenseClaims(REIMBURSEMENT_LIST_PREVIEW_PARAMS)
      const candidates = filterRequiredApplicationCandidates(claims, 'travel', currentUser.value || {})
      planRequest.context_json = {
        ...(planRequest.context_json || {}),
        required_application_gate: {
          ...((planRequest.context_json || {}).required_application_gate || {}),
          travel: {
            checked: true,
            candidate_count: candidates.length,
            candidates: candidates.slice(0, 5).map((candidate) => serializeRequiredApplicationCandidate(candidate))
          }
        }
      }
    } catch (error) {
      console.warn('AI mode required application lookup failed:', error)
      planRequest.context_json = {
        ...(planRequest.context_json || {}),
        required_application_gate: {
          ...((planRequest.context_json || {}).required_application_gate || {}),
          travel: {
            checked: false,
            query_failed: true
          }
        }
      }
    }
    return planRequest
  }

  function handleInlineStewardStreamEvent(messageId, event, options = {}) {
    const message = conversationMessages.value.find((item) => item.id === messageId)
    if (!message) {
      return
    }

    if (event?.event === 'answer_delta') {
      if (options.includeAnswerDelta === false) {
        return
      }
      const data = event?.data && typeof event.data === 'object' ? event.data : {}
      const shouldAutoScroll = inlineConversationAutoScrollPinned.value
      appendInlineMessageContent(message, data.delta || data.content || data.text || '')
      message.stewardPlan = {
        ...(message.stewardPlan || {}),
        streamStatus: 'streaming'
      }
      scrollInlineConversationToBottom({ force: shouldAutoScroll })
      return
    }

    if (event?.event !== 'thinking') {
      return
    }

    const nextEvent = normalizeStreamThinkingEvent(event)
    const shouldAutoScroll = inlineConversationAutoScrollPinned.value
    const currentPlan = message.stewardPlan || {}
    const currentEvents = Array.isArray(currentPlan.thinkingEvents) ? currentPlan.thinkingEvents : []
    const eventIndex = currentEvents.findIndex((item) => item.eventId && item.eventId === nextEvent.eventId)
    const nextEvents = eventIndex >= 0
      ? currentEvents.map((item, index) => (index === eventIndex ? { ...item, ...nextEvent } : item))
      : [...currentEvents, nextEvent]

    message.stewardPlan = {
      ...currentPlan,
      thinkingEvents: nextEvents,
      streamStatus: 'streaming'
    }
    scrollInlineConversationToBottom({ force: shouldAutoScroll })
  }

  async function fetchInlineStewardPlan(messageId, payload, options = {}) {
    const {
      includeAnswerDelta = true,
      idleTimeoutMs = 90000,
      timeoutMs = 0,
      timeoutMessage = '小财管家仍在规划任务，已停止等待。您可以稍后继续追问。'
    } = options
    try {
      return await fetchStewardPlanStream(
        payload,
        {
          onEvent: (event) => handleInlineStewardStreamEvent(messageId, event, { includeAnswerDelta })
        },
        {
          idleTimeoutMs,
          timeoutMs,
          timeoutMessage
        }
      )
    } catch (error) {
      if (String(error?.message || '').includes('流式服务')) {
        return fetchStewardPlan(payload, {
          timeoutMs: 75000,
          timeoutMessage: '小财管家仍在规划任务，已停止等待。您可以稍后继续追问。'
        })
      }
      throw error
    }
  }

  async function resolveInlineExecutionPlan(prompt, entry = {}, files = [], options = {}) {
    const receiptContext = await collectAiModeReceiptContext(files)
    const planRequest = buildStewardPlanRequest({
      rawText: prompt,
      files,
      currentUser: currentUser.value || {},
      conversationId: conversationId.value,
      stewardState: stewardState.value
    })
    planRequest.context_json = {
      ...planRequest.context_json,
      entry_source: 'workbench_ai_inline_execution_plan',
      source: entry.source || 'workbench',
      attachment_names: receiptContext.attachmentNames,
      attachment_count: receiptContext.attachmentCount,
      ocr_summary: receiptContext.ocrSummary,
      ocr_documents: receiptContext.ocrDocuments,
      ocr_source_file_names: receiptContext.ocrSourceFileNames,
      requested_execution_mode: 'plan_then_execute',
      ...(receiptContext.ocrError ? { ocr_error: receiptContext.ocrError } : {})
    }
    await attachAiRequiredApplicationGate(planRequest, prompt)
    const planningMessageId = String(options.pendingMessageId || '').trim()
    if (planningMessageId) {
      return fetchInlineStewardPlan(planningMessageId, planRequest, {
        includeAnswerDelta: false,
        idleTimeoutMs: 45000,
        timeoutMs: 35000,
        timeoutMessage: '小财管家意图规划超时，已切换到本地保守计划。'
      })
    }
    return fetchStewardPlan(planRequest, {
      timeoutMs: 35000,
      timeoutMessage: '小财管家意图规划超时，已切换到本地保守计划。'
    })
  }

  async function requestInlineAssistantReply(prompt, entry = {}, files = [], options = {}) {
    let shouldAutoScrollOnFinish = true
    const reusablePendingMessageId = String(options.pendingMessageId || '').trim()
    const reusablePendingMessage = reusablePendingMessageId
      ? conversationMessages.value.find((item) => item.id === reusablePendingMessageId)
      : null
    const previousThinkingEvents = resolveInlineThinkingEvents(reusablePendingMessage)
    const completedPreviousThinkingEvents = completeWorkbenchAiThinkingEvents(previousThinkingEvents)
    const pendingMessage = createInlineMessage('assistant', '', {
      id: reusablePendingMessageId || undefined,
      pending: true,
      stewardPlan: {
        streamStatus: 'streaming',
        thinkingEvents: mergeWorkbenchAiThinkingEvents(completedPreviousThinkingEvents, [
          {
            eventId: 'init',
            title: '小财管家正在接入业务流程',
            content: '正在识别您的意图、上下文和附件信息。',
            status: 'running'
          }
        ])
      }
    })
    reusablePendingMessageId ? replaceInlineMessage(reusablePendingMessageId, pendingMessage) : conversationMessages.value.push(pendingMessage)
    scrollInlineConversationToBottom()

    try {
      if (await handleAiDocumentQueryIntent(prompt, pendingMessage)) {
        shouldAutoScrollOnFinish = inlineConversationAutoScrollPinned.value
        return
      }

      const receiptContext = await collectAiModeReceiptContext(files)
      const attachmentOcrDetails = buildInlineAttachmentOcrDetails(receiptContext, files)
      const planRequest = buildStewardPlanRequest({
        rawText: prompt,
        files,
        currentUser: currentUser.value || {},
        conversationId: conversationId.value,
        stewardState: stewardState.value
      })
      planRequest.context_json = {
        ...planRequest.context_json,
        entry_source: 'workbench_ai_inline',
        source: entry.source || 'workbench',
        attachment_names: receiptContext.attachmentNames,
        attachment_count: receiptContext.attachmentCount,
        ocr_summary: receiptContext.ocrSummary,
        ocr_documents: receiptContext.ocrDocuments,
        ocr_source_file_names: receiptContext.ocrSourceFileNames,
        ...(receiptContext.ocrError ? { ocr_error: receiptContext.ocrError } : {})
      }
      await attachAiRequiredApplicationGate(planRequest, prompt)

      const plan = await fetchInlineStewardPlan(pendingMessage.id, planRequest)
      const normalizedPlan = normalizeStewardPlan(plan, {
        visibleThinkingEventCount: Number.MAX_SAFE_INTEGER,
        initialSummaryOnly: true
      })
      const previousThinkingEvents = resolveInlineThinkingEvents(pendingMessage)
      const nextThinkingEvents = normalizedPlan.thinkingEvents.length
        ? mergeWorkbenchAiThinkingEvents(previousThinkingEvents, normalizedPlan.thinkingEvents)
        : completeWorkbenchAiThinkingEvents(previousThinkingEvents)
      const previousConversationId = conversationId.value
      const nextConversationId = String(normalizedPlan.conversationId || '').trim()
      if (nextConversationId) {
        conversationId.value = nextConversationId
        emit('conversation-change', { id: conversationId.value, title: activeConversationTitle.value })
        if (previousConversationId && previousConversationId !== nextConversationId) {
          deleteAiWorkbenchConversation(currentUser.value || {}, previousConversationId)
        }
      }
      if (normalizedPlan.stewardState) {
        stewardState.value = normalizedPlan.stewardState
      }
      const requiredApplicationContinuationFlow = resolveRequiredApplicationGateContinuationFlow(normalizedPlan)
      const finalMessageText = requiredApplicationContinuationFlow
        ? buildAiRequiredApplicationGateAutoMessage(normalizedPlan, requiredApplicationContinuationFlow)
        : buildStewardPlanMessageText(plan)
      const hasServerStreamedContent = Boolean(String(pendingMessage.content || '').trim())
      if (!hasServerStreamedContent) {
        await streamInlineAssistantContent(pendingMessage.id, finalMessageText)
      }
      shouldAutoScrollOnFinish = inlineConversationAutoScrollPinned.value
      replaceInlineMessage(
        pendingMessage.id,
        createInlineMessage('assistant', finalMessageText, {
          id: pendingMessage.id,
          stewardPlan: {
            ...normalizedPlan,
            thinkingEvents: nextThinkingEvents,
            streamStatus: 'completed'
          },
          suggestedActions: requiredApplicationContinuationFlow
            ? buildAiRequiredApplicationGateSuggestedActions(requiredApplicationContinuationFlow, prompt)
            : buildStewardSuggestedActions(plan),
          attachmentOcrDetails
        })
      )
      persistCurrentConversation()
    } catch (error) {
      shouldAutoScrollOnFinish = inlineConversationAutoScrollPinned.value
      replaceInlineMessage(
        pendingMessage.id,
        createInlineMessage(
          'assistant',
          error?.message || '小财管家暂时无法完成规划，请稍后再试。',
          {
            id: pendingMessage.id,
            stewardPlan: {
              streamStatus: 'failed',
              thinkingEvents: resolveInlineThinkingEvents(pendingMessage).map((item) => ({
                ...item,
                status: 'failed'
              }))
            }
          }
        )
      )
      toast(error?.message || '小财管家暂时无法完成规划。')
      persistCurrentConversation()
    } finally {
      sending.value = false
      scrollInlineConversationToBottom({ force: shouldAutoScrollOnFinish })
    }
  }

  return {
    buildRequiredApplicationActions,
    buildRequiredApplicationMissingText,
    buildRequiredApplicationSelectionText,
    filterRequiredApplicationCandidates,
    resolveInlineExecutionPlan,
    requestInlineAssistantReply
  }
}
