import { normalizeAttachmentAssociationJob } from '../../utils/attachmentAssociationJobModel.js'

export const AI_ATTACHMENT_ASSOCIATION_CONFIRM_ACTION = 'confirm_ai_attachment_association'
export const AI_ATTACHMENT_OCR_DETAIL_ACTION = 'show_ai_attachment_ocr_details'

function normalizeParagraphs(content) {
  return String(content || '')
    .split(/\n{2,}|\n/)
    .map((item) => item.trim())
    .filter(Boolean)
}

function stripInlineAssociationMarkdown(value = '') {
  return String(value || '')
    .replace(/\*\*/g, '')
    .replace(/`/g, '')
    .trim()
}

export function resolveLegacyAiAttachmentAssociationPayload(content = '') {
  const text = String(content || '')
  if (!/我已先识别票据，并(?:匹配到最可能的报销单|找到一张可能关联的报销单)/.test(text)) {
    return null
  }

  const claimNo = stripInlineAssociationMarkdown(
    text.match(/推荐关联[：:]\s*([^\n]+)/u)?.[1] || ''
  )
  if (!claimNo) {
    return null
  }

  return {
    claim_no: claimNo,
    document_type: 'expense'
  }
}

export function hydrateInlineAttachmentAssociationSuggestedActions(actions = [], content = '') {
  const safeActions = Array.isArray(actions) ? actions : []
  const hasConfirmAction = safeActions.some(
    (action) => String(action?.action_type || '').trim() === AI_ATTACHMENT_ASSOCIATION_CONFIRM_ACTION
  )
  if (hasConfirmAction) {
    return safeActions
  }

  const payload = resolveLegacyAiAttachmentAssociationPayload(content)
  if (!payload) {
    return safeActions
  }

  return [
    {
      label: '确认自动关联',
      description: '将本次票据自动归集到推荐单据。',
      icon: 'mdi mdi-link-variant',
      action_type: AI_ATTACHMENT_ASSOCIATION_CONFIRM_ACTION,
      payload
    },
    ...safeActions
  ]
}

function normalizeInlineAttachmentOcrField(field = {}) {
  if (!field || typeof field !== 'object') {
    return null
  }
  const value = String(field.value ?? field.text ?? '').trim()
  if (!value) {
    return null
  }
  return {
    label: String(field.label || field.key || field.name || '识别字段').trim() || '识别字段',
    value
  }
}

function normalizeInlineAttachmentOcrDocument(document = {}, index = 0) {
  const fields = (Array.isArray(document?.document_fields) ? document.document_fields : document?.fields || [])
    .map((field) => normalizeInlineAttachmentOcrField(field))
    .filter(Boolean)
    .slice(0, 12)
  const summary = String(document?.summary || document?.text || '').replace(/\s+/g, ' ').trim()
  const filename = String(document?.filename || document?.name || '').trim()
  if (!filename && !summary && !fields.length) {
    return null
  }
  return {
    filename: filename || `附件 ${index + 1}`,
    summary,
    fields
  }
}

export function normalizeInlineAttachmentOcrDetails(details = null) {
  if (!details || typeof details !== 'object') {
    return null
  }
  const documents = (Array.isArray(details.documents) ? details.documents : details.ocrDocuments || [])
    .map((document, index) => normalizeInlineAttachmentOcrDocument(document, index))
    .filter(Boolean)
  const fileNames = (Array.isArray(details.fileNames) ? details.fileNames : [])
    .map((name) => String(name || '').trim())
    .filter(Boolean)
  if (!documents.length && !fileNames.length) {
    return null
  }
  return {
    fileNames,
    documents
  }
}

export function buildInlineAttachmentOcrDetails(collected = {}, files = []) {
  return normalizeInlineAttachmentOcrDetails({
    fileNames: files.map((file) => file?.name || '').filter(Boolean),
    documents: collected?.ocrDocuments || []
  })
}

export function formatMessageTime(timestamp) {
  if (!timestamp) return ''
  return new Date(timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
}

export function createWorkbenchAiMessageRuntime() {
  let messageSeq = 0

  function nextMessageId() {
    messageSeq += 1
    return `${Date.now()}-${messageSeq}`
  }

  function createAiAttachmentAssociationId() {
    messageSeq += 1
    return `ai-attachment-${Date.now()}-${messageSeq}`
  }

  function createInlineMessage(role, content, options = {}) {
    const normalizedContent = String(content || '').trim()
    const suggestedActions = Array.isArray(options.suggestedActions) ? options.suggestedActions : []
    return {
      id: options.id || nextMessageId(),
      role,
      content: normalizedContent,
      paragraphs: normalizeParagraphs(normalizedContent),
      pending: Boolean(options.pending),
      feedback: String(options.feedback || ''),
      stewardPlan: options.stewardPlan || null,
      suggestedActions: role === 'assistant'
        ? hydrateInlineAttachmentAssociationSuggestedActions(suggestedActions, normalizedContent)
        : suggestedActions,
      applicationPreview: options.applicationPreview || null,
      requestedSubmit: Boolean(options.requestedSubmit),
      submitRequiresConfirmation: Boolean(options.submitRequiresConfirmation),
      draftPayload: options.draftPayload || null,
      attachmentAssociationJob: normalizeInlineAttachmentAssociationJob(options.attachmentAssociationJob || null),
      linkedReimbursementDraftJob: normalizeInlineLinkedReimbursementDraftJob(options.linkedReimbursementDraftJob || null),
      attachmentOcrDetails: normalizeInlineAttachmentOcrDetails(options.attachmentOcrDetails || null),
      // 多 task 推进上下文:申请预览/报销草稿消息上挂载剩余 task 列表,
      // 刷新或消息重建后仍能继续推进,避免 task 链断裂。
      stewardRemainingTasks: Array.isArray(options.stewardRemainingTasks) ? options.stewardRemainingTasks : [],
      text: options.text || normalizedContent,
      createdAt: options.createdAt || Date.now()
    }
  }

  function normalizeRuntimeMessage(message = {}) {
    return createInlineMessage(message.role || 'assistant', message.content || '', {
      id: message.id,
      pending: false,
      feedback: message.feedback || '',
      stewardPlan: message.stewardPlan || null,
      suggestedActions: Array.isArray(message.suggestedActions) ? message.suggestedActions : [],
      applicationPreview: message.applicationPreview || null,
      requestedSubmit: Boolean(message.requestedSubmit),
      submitRequiresConfirmation: Boolean(message.submitRequiresConfirmation),
      draftPayload: message.draftPayload || null,
      attachmentAssociationJob: message.attachmentAssociationJob || null,
      linkedReimbursementDraftJob: message.linkedReimbursementDraftJob || null,
      attachmentOcrDetails: message.attachmentOcrDetails || null,
      stewardRemainingTasks: Array.isArray(message.stewardRemainingTasks) ? message.stewardRemainingTasks : [],
      text: message.text || message.content || ''
    })
  }

  function serializeRuntimeMessage(message = {}) {
    return {
      id: message.id,
      role: message.role,
      content: message.content,
      text: message.text || message.content || '',
      feedback: message.feedback || '',
      stewardPlan: message.stewardPlan || null,
      suggestedActions: Array.isArray(message.suggestedActions) ? message.suggestedActions : [],
      applicationPreview: message.applicationPreview || null,
      requestedSubmit: Boolean(message.requestedSubmit),
      submitRequiresConfirmation: Boolean(message.submitRequiresConfirmation),
      draftPayload: message.draftPayload || null,
      attachmentAssociationJob: normalizeInlineAttachmentAssociationJob(message.attachmentAssociationJob || null),
      linkedReimbursementDraftJob: normalizeInlineLinkedReimbursementDraftJob(message.linkedReimbursementDraftJob || null),
      attachmentOcrDetails: message.attachmentOcrDetails || null,
      stewardRemainingTasks: Array.isArray(message.stewardRemainingTasks) ? message.stewardRemainingTasks : []
    }
  }

  return {
    createAiAttachmentAssociationId,
    createInlineMessage,
    normalizeRuntimeMessage,
    serializeRuntimeMessage
  }
}

export function normalizeInlineAttachmentAssociationJob(job = null) {
  return normalizeAttachmentAssociationJob(job)
}

export function normalizeInlineLinkedReimbursementDraftJob(job = null) {
  if (!job || typeof job !== 'object') {
    return null
  }
  const jobId = String(job.jobId || job.job_id || '').trim()
  if (!jobId) {
    return null
  }
  const draftPayload = job.draftPayload && typeof job.draftPayload === 'object'
    ? job.draftPayload
    : job.draft_payload && typeof job.draft_payload === 'object'
      ? job.draft_payload
      : null
  return {
    jobId,
    status: String(job.status || 'queued').trim() || 'queued',
    message: String(job.message || '').trim(),
    error: String(job.error || '').trim(),
    runId: String(job.runId || job.run_id || '').trim(),
    applicationClaimNo: String(job.applicationClaimNo || job.application_claim_no || '').trim(),
    draftPayload
  }
}
