import { buildSuggestedActionKey } from '../../utils/suggestedActionKey.js'
import { filterVisibleMessageMeta } from '../../utils/assistantMessageMeta.js'
import { normalizeExpenseQueryPayload } from './travelReimbursementExpenseQueryModel.js'
import { buildAgentInsight, buildReviewFilePreviewsFromReviewPayload } from './travelReimbursementAttachmentModel.js'
import { normalizeAssistantSessionType, SESSION_TYPE_EXPENSE } from './travelReimbursementConversationSessionModel.js'
import {
  buildRestoredMessageId,
  buildStoredMessageMeta,
  createMessage,
  formatMessageTime
} from './travelReimbursementConversationMessageModel.js'

export function resolveInitialSessionType(conversation, fallback = SESSION_TYPE_EXPENSE) {
  const stateJson = conversation?.state_json || conversation?.stateJson || {}
  const sessionType = String(stateJson?.session_type || '').trim()
  return normalizeAssistantSessionType(sessionType, fallback)
}

export function buildInitialInsightFromConversation(conversation) {
  const rawMessages = Array.isArray(conversation?.messages) ? conversation.messages : []
  for (let index = rawMessages.length - 1; index >= 0; index -= 1) {
    const item = rawMessages[index]
    const messageJson = item?.message_json || item?.messageJson || {}
    const orchestratorPayload = messageJson?.orchestrator_payload || null
    if (!orchestratorPayload) continue
    const attachmentNames = Array.isArray(messageJson?.attachment_names)
      ? messageJson.attachment_names.filter(Boolean)
      : []
    return buildAgentInsight(
      orchestratorPayload,
      attachmentNames,
      buildReviewFilePreviewsFromReviewPayload(orchestratorPayload?.result?.review_payload)
    )
  }
  return null
}

export function resolveInitialConversationId(conversation) {
  return String(conversation?.conversation_id || conversation?.conversationId || '').trim()
}

export function resolveInitialDraftClaimId(conversation) {
  return String(conversation?.draft_claim_id || conversation?.draftClaimId || '').trim()
}

export function resolveKnowledgeRankLabel(index) {
  return String(index + 1)
}

export function resolveKnowledgeRankTone(index) {
  if (index === 0) return 'gold'
  if (index === 1) return 'silver'
  if (index === 2) return 'bronze'
  return 'default'
}

export function parseConversationMessageSequence(message) {
  const messageJson = message?.message_json || message?.messageJson || {}
  const sequence = Number.parseInt(messageJson?.sequence, 10)
  return Number.isFinite(sequence) && sequence > 0 ? sequence : null
}

export function parseConversationMessageTime(message) {
  const rawValue = message?.created_at || message?.createdAt || ''
  const timestamp = new Date(rawValue).getTime()
  return Number.isFinite(timestamp) ? timestamp : Number.MAX_SAFE_INTEGER
}

export function resolveConversationMessageRolePriority(message) {
  return String(message?.role || '').trim() === 'user' ? 0 : 1
}

export function sortConversationMessages(messages) {
  return [...(Array.isArray(messages) ? messages : [])].sort((left, right) => {
    const leftSequence = parseConversationMessageSequence(left)
    const rightSequence = parseConversationMessageSequence(right)
    if (leftSequence !== null && rightSequence !== null && leftSequence !== rightSequence) {
      return leftSequence - rightSequence
    }

    const timeDiff = parseConversationMessageTime(left) - parseConversationMessageTime(right)
    if (timeDiff !== 0) {
      return timeDiff
    }

    const leftRunId = String(left?.run_id || left?.runId || '').trim()
    const rightRunId = String(right?.run_id || right?.runId || '').trim()
    if (leftRunId && rightRunId && leftRunId === rightRunId) {
      const roleDiff = resolveConversationMessageRolePriority(left) - resolveConversationMessageRolePriority(right)
      if (roleDiff !== 0) {
        return roleDiff
      }
    }

    return String(left?.id || '').localeCompare(String(right?.id || ''))
  })
}

export function normalizeInitialConversationMessages(conversation) {
  const rawMessages = sortConversationMessages(conversation?.messages)

  const restoredMessages = rawMessages.map((item) => {
    const messageJson = item?.message_json || item?.messageJson || {}
    const attachmentNames = Array.isArray(messageJson?.attachment_names)
      ? messageJson.attachment_names.filter(Boolean)
      : []
    const orchestratorPayload = messageJson?.orchestrator_payload || null
    const result = orchestratorPayload?.result || {}

    return createMessage(item.role, item.content, attachmentNames, {
      id: buildRestoredMessageId(item.id),
      time: formatMessageTime(item.created_at || item.createdAt),
      assistantName: String(messageJson?.assistant_name || messageJson?.assistantName || '').trim(),
      assistantVariant: String(messageJson?.assistant_variant || messageJson?.assistantVariant || '').trim(),
      meta: item.role === 'assistant' ? buildStoredMessageMeta(messageJson, attachmentNames) : [],
      citations: item.role === 'assistant' && Array.isArray(result?.citations) ? result.citations : [],
      suggestedActions:
        item.role === 'assistant' && Array.isArray(result?.suggested_actions)
          ? result.suggested_actions
          : [],
      queryPayload: item.role === 'assistant' ? normalizeExpenseQueryPayload(result?.query_payload) : null,
      draftPayload: item.role === 'assistant' ? result?.draft_payload || messageJson?.draft_payload || null : null,
      reviewPayload: item.role === 'assistant' ? result?.review_payload || null : null,
      riskFlags: item.role === 'assistant' && Array.isArray(result?.risk_flags) ? result.risk_flags : [],
      applicationPreview: item.role === 'assistant' ? result?.application_preview || null : null,
      applicationLearningReceipts:
        item.role === 'assistant' && Array.isArray(result?.learning_receipts)
          ? result.learning_receipts
          : []
    })
  })
  return markResolvedSuggestedActionMessages(restoredMessages)
}

export function normalizeSnapshotMessage(message) {
  const extras = message && typeof message === 'object' ? { ...message } : {}
  const role = String(extras.role || 'assistant').trim() || 'assistant'
  const text = String(extras.text || '')
  const attachments = Array.isArray(extras.attachments) ? extras.attachments.filter(Boolean) : []
  delete extras.role
  delete extras.text
  delete extras.attachments
  if (!extras.applicationPreview && extras.pendingApplicationPreviewDecision) {
    extras.applicationPreview = {
      ...extras.pendingApplicationPreviewDecision,
      decisionId: '',
      decisionTrackingStatus: 'registration_failed',
      decisionRegistrationError: '上次签发请求未完成，请重新签发。'
    }
  }
  delete extras.pendingApplicationPreviewDecision
  return createMessage(role, text, attachments, extras)
}

export function normalizeSnapshotMessages(messages) {
  return Array.isArray(messages)
    ? markResolvedSuggestedActionMessages(messages.map(normalizeSnapshotMessage))
    : []
}

export function serializeSessionMessages(messages) {
  return (Array.isArray(messages) ? messages : []).map((message) => ({
    id: message.id,
    role: message.role,
    text: message.text,
    attachments: Array.isArray(message.attachments) ? message.attachments.filter(Boolean) : [],
    time: message.time,
    meta: filterVisibleMessageMeta(message.meta),
    metaTone: message.metaTone || '',
    citations: Array.isArray(message.citations) ? message.citations : [],
    suggestedActions: Array.isArray(message.suggestedActions) ? message.suggestedActions : [],
    suggestedActionsLocked: Boolean(message.suggestedActionsLocked),
    selectedSuggestedActionKey: String(message.selectedSuggestedActionKey || ''),
    selectedSuggestedActionLabel: String(message.selectedSuggestedActionLabel || ''),
    querySelectionLocked: Boolean(message.querySelectionLocked),
    selectedQueryRecordId: String(message.selectedQueryRecordId || ''),
    queryPayload: message.queryPayload || null,
    draftPayload: message.draftPayload || null,
    reviewPayload: message.reviewPayload || null,
    riskFlags: Array.isArray(message.riskFlags) ? message.riskFlags : [],
    pendingAttachmentAssociation: message.pendingAttachmentAssociation || null,
    applicationPreview: message.applicationPreview || null,
    applicationLearningReceipts: Array.isArray(message.applicationLearningReceipts)
      ? message.applicationLearningReceipts
      : [],
    pendingApplicationPreviewDecision: message.pendingApplicationPreviewDecision || null,
    applicationSubmitConfirmed: Boolean(message.applicationSubmitConfirmed),
    budgetReport: message.budgetReport || null,
    stewardPlan: message.stewardPlan || null,
    operationFeedback: message.operationFeedback || null,
    assistantName: message.assistantName || '',
    assistantVariant: message.assistantVariant || '',
    isWelcome: Boolean(message.isWelcome),
    welcomeQuickActions: Array.isArray(message.welcomeQuickActions) ? message.welcomeQuickActions : []
  }))
}

export function hasMeaningfulSessionMessages(messages) {
  return (Array.isArray(messages) ? messages : []).some((message) => {
    if (!message || message.isWelcome) {
      return false
    }
    if (message.role === 'user') {
      return true
    }
    return Boolean(
      String(message.text || '').trim()
        || (Array.isArray(message.suggestedActions) && message.suggestedActions.length)
        || message.reviewPayload
        || message.queryPayload
        || message.draftPayload
        || message.applicationPreview
        || (Array.isArray(message.applicationLearningReceipts) && message.applicationLearningReceipts.length)
        || message.budgetReport
        || message.stewardPlan
        || message.operationFeedback
        || message.pendingAttachmentAssociation
        || (Array.isArray(message.riskFlags) && message.riskFlags.length)
    )
  })
}

export function hasActiveSuggestedActionMessage(messages) {
  return (Array.isArray(messages) ? messages : []).some(
    (message) =>
      message?.role === 'assistant'
        && Array.isArray(message.suggestedActions)
        && message.suggestedActions.length > 0
        && !message.suggestedActionsLocked
  )
}

export function resolveConversationUpdatedAt(conversation) {
  const timestamp = new Date(conversation?.updated_at || conversation?.updatedAt || 0).getTime()
  return Number.isFinite(timestamp) ? timestamp : 0
}

export function shouldPreferPersistedSessionState(persistedState, snapshot, conversation) {
  if (!persistedState) {
    return false
  }
  if (!conversation) {
    return true
  }
  if (hasActiveSuggestedActionMessage(persistedState.messages)) {
    return true
  }
  const snapshotUpdatedAt = Number(snapshot?.updatedAt || 0)
  return snapshotUpdatedAt >= resolveConversationUpdatedAt(conversation)
}

export function markResolvedSuggestedActionMessages(messages) {
  const items = Array.isArray(messages) ? messages : []
  const selectedLabels = new Set()

  for (const message of items) {
    if (message?.role !== 'user') {
      continue
    }
    const text = String(message.text || '').trim()
    const selectedMatch = text.match(/^选择(.+)$/) || text.match(/用户选择报销场景[:：]\s*([^\n\r]+)/)
    if (selectedMatch?.[1]) {
      selectedLabels.add(selectedMatch[1].trim())
    } else if (text === '我要报销') {
      selectedLabels.add(text)
    }
  }

  if (!selectedLabels.size) {
    return items
  }

  return items.map((message) => {
    if (
      message?.role !== 'assistant'
        || message.suggestedActionsLocked
        || !Array.isArray(message.suggestedActions)
        || !message.suggestedActions.length
    ) {
      return message
    }

    const selectedAction = message.suggestedActions.find((action) =>
      selectedLabels.has(String(action?.label || action?.payload?.expense_type_label || '').trim())
    )
    if (!selectedAction) {
      return message
    }

    return {
      ...message,
      suggestedActionsLocked: true,
      selectedSuggestedActionKey: buildSuggestedActionKey(selectedAction),
      selectedSuggestedActionLabel: String(selectedAction.label || selectedAction?.payload?.expense_type_label || '').trim()
    }
  })
}
