import {
  buildApplicationTemplatePreview,
  buildLocalApplicationPreview,
  buildModelRefinedApplicationPreview,
  normalizeApplicationPreview
} from '../../utils/expenseApplicationPreview.js'
import {
  buildAiApplicationPrecheckThinkingEvents,
  isAiApplicationPrecheckBlocking
} from '../../utils/aiApplicationPrecheckModel.js'
import { extractExpenseClaimItems } from '../../services/reimbursements.js'
import {
  AI_APPLICATION_ACTION_SAVE_DRAFT,
  AI_APPLICATION_ACTION_SUBMIT
} from '../../services/aiApplicationPreviewActions.js'
import { INLINE_APPLICATION_STATUS_LABELS } from '../../constants/documentProtocol.js'
import { resolveInlineApplicationPreviewTextAction } from './workbenchAiApplicationGateModel.js'

function normalizeInlineApplicationResultTableCell(value, fallback = '-') {
  const text = String(value || '')
    .replace(/\s*\n+\s*/g, ' ')
    .replace(/\|/g, '｜')
    .trim()
  return text || fallback
}

export function normalizeInlineApplicationStatusLabel(value, fallback = '') {
  const text = String(value || '').trim()
  if (!text) {
    return fallback
  }
  return INLINE_APPLICATION_STATUS_LABELS[text.toLowerCase()] || text
}

export function resolveInlineApplicationActionDocumentInfo(draftPayload = {}) {
  const source = draftPayload && typeof draftPayload === 'object' ? draftPayload : {}
  const body = String(source.body || source.markdown || '').trim()
  const resolveBodyField = (labels = []) => {
    for (const label of labels) {
      const pattern = new RegExp(`${label}\\s*[：:]\\s*([^\\n|]+)`, 'u')
      const match = body.match(pattern)
      if (match?.[1]) {
        return String(match[1]).replace(/\*\*/g, '').trim()
      }
    }
    return ''
  }
  const startDate = String(source.start_date || source.startDate || source.trip_start_date || source.tripStartDate || '').trim()
  const endDate = String(source.end_date || source.endDate || source.trip_end_date || source.tripEndDate || '').trim()
  const dateText = String(
    source.business_time ||
      source.businessTime ||
      source.time ||
      source.occurred_at ||
      source.occurredAt ||
      source.apply_time ||
      source.applyTime ||
      ''
  ).trim()
  const rangeText = startDate && endDate && startDate !== endDate
    ? `${startDate} 至 ${endDate}`
    : startDate || endDate
  return {
    claimNo: String(source.claim_no || source.claimNo || source.document_no || source.documentNo || '').trim(),
    claimId: String(source.claim_id || source.claimId || source.id || '').trim(),
    statusLabel: normalizeInlineApplicationStatusLabel(source.status_label || source.statusLabel || source.status),
    approvalStage: String(source.approval_stage || source.approvalStage || '').trim(),
    dateLabel: rangeText || dateText || resolveBodyField(['时间', '日期', '申请时间']) || '待补充',
    locationLabel: String(
      source.location ||
        source.application_location ||
        source.applicationLocation ||
        source.destination ||
        source.destination_city ||
        source.destinationCity ||
        ''
    ).trim() || resolveBodyField(['地点', '目的地']) || '待补充',
    reasonLabel: String(
      source.reason ||
        source.business_reason ||
        source.businessReason ||
        source.description ||
        source.title ||
        ''
    ).trim() || resolveBodyField(['事由', '事件', '申请事由']) || '待补充',
    amountLabel: String(
      source.amount ||
        source.application_amount ||
        source.applicationAmount ||
        source.estimated_amount ||
        source.estimatedAmount ||
        ''
    ).trim() || resolveBodyField(['金额', '预计金额', '申请金额']) || '-',
    documentTypeLabel: String(
      source.document_type_label ||
        source.documentTypeLabel ||
        source.application_type_label ||
        source.applicationTypeLabel ||
        source.expense_type_label ||
        source.expenseTypeLabel ||
        ''
    ).trim()
  }
}

export function buildInlineApplicationResultTable(draftPayload = {}, options = {}) {
  const info = resolveInlineApplicationActionDocumentInfo(draftPayload)
  const reference = info.claimNo || info.claimId
  const statusLabel = normalizeInlineApplicationStatusLabel(info.statusLabel, options.statusLabel)
  return [
    '| 单据类型 | 单据编号 | 单据状态 | 当前节点 | 日期 | 地点 | 事由 | 金额 |',
    '| --- | --- | --- | --- | --- | --- | --- | --- |',
    `| ${normalizeInlineApplicationResultTableCell(info.documentTypeLabel || options.documentTypeLabel, '出差申请')} | ${normalizeInlineApplicationResultTableCell(reference)} | ${normalizeInlineApplicationResultTableCell(statusLabel)} | ${normalizeInlineApplicationResultTableCell(info.approvalStage || options.stageLabel)} | ${normalizeInlineApplicationResultTableCell(info.dateLabel)} | ${normalizeInlineApplicationResultTableCell(info.locationLabel)} | ${normalizeInlineApplicationResultTableCell(info.reasonLabel)} | ${normalizeInlineApplicationResultTableCell(info.amountLabel, '-')} |`
  ].join('\n')
}

export function extractInlineApplicationDraftPayload(payload = {}) {
  const result = payload?.result && typeof payload.result === 'object' ? payload.result : {}
  return result.draft_payload && typeof result.draft_payload === 'object'
    ? result.draft_payload
    : payload?.draft_payload && typeof payload.draft_payload === 'object'
      ? payload.draft_payload
      : null
}

export function buildInlineApplicationPreviewActionResultText(actionType, payload = {}) {
  const draftPayload = extractInlineApplicationDraftPayload(payload) || {}
  const claimNo = String(draftPayload.claim_no || draftPayload.claimNo || '').trim()
  const approvalStage = String(draftPayload.approval_stage || draftPayload.approvalStage || '').trim()
  if (actionType === AI_APPLICATION_ACTION_SUBMIT) {
    return [
      '### 申请单据已生成，并已进入审批流程',
      approvalStage ? `系统已推送到 **${approvalStage}**，当前节点：${approvalStage}。` : '系统已推送到审批流程，当前节点：审批中。',
      buildInlineApplicationResultTable(draftPayload, {
        statusLabel: '审批中',
        stageLabel: approvalStage || '直属领导审批',
        documentTypeLabel: '出差申请'
      })
    ].filter(Boolean).join('\n\n')
  }
  return [
    '### 申请草稿已保存',
    claimNo ? `系统已保存当前申请草稿，草稿单号：**${claimNo}**。` : '系统已保存当前申请草稿。',
    buildInlineApplicationResultTable(draftPayload, {
      statusLabel: '草稿',
      stageLabel: '待提交',
      documentTypeLabel: '出差申请'
    })
  ].filter(Boolean).join('\n\n')
}

export function buildInlineApplicationDetailAction(draftPayload = {}) {
  const claimNo = String(draftPayload?.claim_no || draftPayload?.claimNo || '').trim()
  if (!claimNo) {
    return []
  }
  return [{
    label: '查看单据详情',
    description: '打开刚生成的申请单详情。',
    icon: 'mdi mdi-open-in-new',
    action_type: 'open_application_detail',
    payload: {
      claim_no: claimNo,
      claim_id: String(draftPayload.claim_id || draftPayload.claimId || '').trim(),
      document_type: 'application'
    }
  }]
}

export function resolveInlineApplicationPreviewActionFromText(text = '') {
  return resolveInlineApplicationPreviewTextAction(text)
}

export function normalizeInlineApplicationTypeLabel(expenseTypeLabel, fallback = '费用申请') {
  const label = String(expenseTypeLabel || '').trim()
  if (!label) {
    return fallback
  }
  if (label.endsWith('费用申请') || label.endsWith('申请')) {
    return label
  }
  if (label.endsWith('费用')) {
    return `${label}申请`
  }
  if (label.endsWith('费')) {
    return `${label.slice(0, -1)}费用申请`
  }
  return `${label}申请`
}

function buildOntologyTimeRangeFromCanonical(value = '') {
  const raw = String(value || '').trim()
  if (!raw) {
    return {}
  }
  const normalized = raw.replace(/\s+/g, ' ')
  const [startDate, endDate] = normalized
    .split(/\s*(?:至|到|~|--|—)\s*/)
    .map((item) => item.trim())
    .filter(Boolean)
  if (/^20\d{2}-\d{1,2}-\d{1,2}$/.test(startDate || '')) {
    return {
      raw,
      start_date: startDate,
      end_date: /^20\d{2}-\d{1,2}-\d{1,2}$/.test(endDate || '') ? endDate : startDate
    }
  }
  return { raw }
}

function buildEntityFromCanonicalField(type, value) {
  const normalizedValue = String(value || '').trim()
  if (!type || !normalizedValue) {
    return null
  }
  return {
    type,
    value: normalizedValue,
    normalized_value: normalizedValue
  }
}

function buildApplicationOntologyFromCanonicalFields(fields = {}) {
  const source = fields && typeof fields === 'object' ? fields : {}
  const entityKeys = [
    'expense_type',
    'location',
    'reason',
    'amount',
    'transport_mode',
    'customer_name',
    'merchant_name',
    'department_name',
    'employee_name',
    'employee_no'
  ]
  return {
    parse_strategy: 'llm_primary',
    time_range: buildOntologyTimeRangeFromCanonical(source.time_range),
    entities: entityKeys
      .map((key) => buildEntityFromCanonicalField(key, source[key]))
      .filter(Boolean)
  }
}

export function buildInlineApplicationPreview(expenseTypeLabel, sourceText = '', currentUser = {}, options = {}) {
  const rawText = String(sourceText || '').trim()
  const basePreview = rawText
    ? buildLocalApplicationPreview(rawText, currentUser)
    : buildApplicationTemplatePreview(currentUser)
  const preview = options.ontologyFields && typeof options.ontologyFields === 'object'
    ? buildModelRefinedApplicationPreview(
        basePreview,
        buildApplicationOntologyFromCanonicalFields(options.ontologyFields),
        rawText,
        currentUser
      )
    : basePreview
  const normalized = normalizeApplicationPreview(preview)
  return normalizeApplicationPreview({
    ...normalized,
    fields: {
      ...(normalized.fields || {}),
      applicationType: normalizeInlineApplicationTypeLabel(
        expenseTypeLabel,
        normalized.fields?.applicationType || '费用申请'
      )
    }
  })
}

export function resolveInlineApplicationDraftIdentity(payload = {}) {
  const source = payload && typeof payload === 'object' ? payload : {}
  return {
    claimId: String(source.claim_id || source.claimId || source.id || '').trim(),
    claimNo: String(source.claim_no || source.claimNo || source.document_no || source.documentNo || '').trim()
  }
}

export function isSameInlineApplicationDraftClaim(claim = {}, draftPayload = {}) {
  const draftIdentity = resolveInlineApplicationDraftIdentity(draftPayload)
  if (!draftIdentity.claimId && !draftIdentity.claimNo) {
    return false
  }
  const claimIdentity = resolveInlineApplicationDraftIdentity(claim)
  return Boolean(
    (draftIdentity.claimId && claimIdentity.claimId && draftIdentity.claimId === claimIdentity.claimId) ||
      (draftIdentity.claimNo && claimIdentity.claimNo && draftIdentity.claimNo === claimIdentity.claimNo)
  )
}

export function buildInlineApplicationSubmitPrecheckPayload(claimsPayload, draftPayload = {}) {
  const items = extractExpenseClaimItems(claimsPayload)
    .filter((claim) => !isSameInlineApplicationDraftClaim(claim, draftPayload))
  return { items }
}

export function completeInlineThinkingEvents(events = []) {
  return events.map((event) => ({
    ...event,
    status: event.status === 'failed' ? 'failed' : 'completed'
  }))
}

export function buildInitialInlineApplicationSubmitThinkingEvents() {
  return [
    {
      eventId: 'application-precheck-overlap',
      title: '核查同时间段申请单',
      content: '正在查询您名下可见申请单，检查是否存在相同或重叠日期。',
      status: 'running'
    },
    {
      eventId: 'application-precheck-budget',
      title: '评估预算与审批影响',
      content: '等待单据重叠核查完成后，继续评估预算占用和审批影响。',
      status: 'pending'
    },
    {
      eventId: 'application-submit',
      title: '提交申请单据',
      content: '等待提交前核查完成。',
      status: 'pending'
    }
  ]
}

export function buildInlineApplicationSubmitThinkingEvents(precheck = {}) {
  const blocked = isAiApplicationPrecheckBlocking(precheck)
  return buildAiApplicationPrecheckThinkingEvents(precheck).map((event) => {
    if (event.eventId !== 'application-precheck-form') {
      return event
    }
    return {
      eventId: 'application-submit',
      title: blocked ? '暂停提交申请' : '提交申请单据',
      content: blocked
        ? '发现相同或重叠日期已有申请单，已暂停本次提交。'
        : '提交前核查通过，正在生成申请单据并推送审批流程。',
      status: blocked ? 'completed' : 'running'
    }
  })
}

export function buildFailedInlineApplicationSubmitThinkingEvents(error) {
  return [
    {
      eventId: 'application-precheck-overlap',
      title: '核查同时间段申请单',
      content: `查询已有申请单失败：${String(error?.message || error || '未知错误')}`,
      status: 'failed'
    },
    {
      eventId: 'application-submit',
      title: '暂停提交申请',
      content: '因为未能完成提交前重复日期核查，系统没有提交本次申请。',
      status: 'failed'
    }
  ]
}
