const QUARTER_NAME_MAP = {
  1: 'Q1',
  2: 'Q2',
  3: 'Q3',
  4: 'Q4'
}

const CHINESE_QUARTER_MAP = {
  一: 1,
  二: 2,
  三: 3,
  四: 4
}

const BUDGET_REPORT_COLORS = {
  travel: 'var(--theme-primary)',
  meal: 'var(--theme-secondary)',
  office: 'var(--warning)',
  communication: 'var(--info)'
}

const PREVIOUS_QUARTER_SPEND = [
  {
    key: 'travel',
    name: '差旅',
    value: 468000,
    previousValue: 395600,
    recommendedBudget: 550000,
    color: BUDGET_REPORT_COLORS.travel,
    drivers: ['客户现场实施增加', '跨区域项目支持', '住宿单价上浮'],
    risk: 'Q2 差旅占比最高，Q3 如果继续集中出差，建议把提醒阈值放在 75%。',
    suggestion: '建议 Q3 编制 52-56 万，优先锁定核心项目差旅，非项目型出行走事前说明。'
  },
  {
    key: 'meal',
    name: '招待费',
    value: 286000,
    previousValue: 255100,
    recommendedBudget: 320000,
    color: BUDGET_REPORT_COLORS.meal,
    drivers: ['重点客户拜访', '渠道活动增多', '单次人均金额偏高'],
    risk: '招待费增长快于整体费用，容易触发合规说明和客户关联材料补充。',
    suggestion: '建议 Q3 编制 30-32 万，并按客户拓展活动拆分额度，避免月底集中消耗。'
  },
  {
    key: 'office',
    name: '办公用品',
    value: 181600,
    previousValue: 172000,
    recommendedBudget: 200000,
    color: BUDGET_REPORT_COLORS.office,
    drivers: ['新员工入职物资', '会议设备补充', '季度集中采购'],
    risk: '办公用品整体平稳，但集中采购会造成单月占用偏高。',
    suggestion: '建议 Q3 编制 19-20 万，采用月度采购节奏，把一次性采购纳入占用预留。'
  },
  {
    key: 'communication',
    name: '通信',
    value: 98000,
    previousValue: 102800,
    recommendedBudget: 110000,
    color: BUDGET_REPORT_COLORS.communication,
    drivers: ['固定通讯补贴', '项目远程协同', '少量专线费用'],
    risk: '通信费用占比较低且略有下降，适合维持刚性额度。',
    suggestion: '建议 Q3 编制 10-11 万，保留 8% 弹性池用于项目临时通讯支出。'
  }
]

const currency = (value) =>
  Number(value || 0).toLocaleString('zh-CN', {
    minimumFractionDigits: 0,
    maximumFractionDigits: 0
  })

const compactCurrency = (value) => `¥${(Number(value || 0) / 10000).toFixed(1)}万`

const percent = (value, total) => {
  const denominator = Number(total || 0)
  if (!denominator) return '0.0%'
  return `${((Number(value || 0) / denominator) * 100).toFixed(1)}%`
}

function normalizeBudgetText(rawText) {
  return String(rawText || '')
    .replace(/\s+/g, '')
    .toLowerCase()
}

function parseQuarter(rawText) {
  const text = String(rawText || '')
  const qMatch = text.match(/[qQ]\s*([1-4])/)
  if (qMatch) return Number(qMatch[1])

  const numberMatch = text.match(/第?\s*([1-4])\s*(?:季|季度)/)
  if (numberMatch) return Number(numberMatch[1])

  const chineseMatch = text.match(/第?\s*([一二三四])\s*(?:季|季度)/)
  if (chineseMatch) return CHINESE_QUARTER_MAP[chineseMatch[1]] || 0

  return 0
}

function parseYear(rawText) {
  const match = String(rawText || '').match(/(20\d{2})/)
  return match ? Number(match[1]) : 2026
}

function hasExplicitYear(rawText) {
  return /(20\d{2})/.test(String(rawText || ''))
}

function resolvePreviousPeriod(year, quarter) {
  if (quarter > 1) {
    return { year, quarter: quarter - 1 }
  }
  return { year: year - 1, quarter: 4 }
}

function resolveDepartmentNameFromText(rawText) {
  const text = String(rawText || '')
  const match = text.match(/(市场部|财务部|技术部|人力资源部|生产部|总裁办)/)
  return match ? match[1] : ''
}

function normalizeBudgetContext(context) {
  return context && typeof context === 'object' ? context : null
}

function resolveContextMode(context) {
  return String(context?.mode || '').trim() === 'review' ? 'review' : 'edit'
}

function buildFinanceSuggestion(item, mode) {
  if (mode !== 'review') {
    return ''
  }
  if (item.riskTone === 'risk') {
    return `${item.name}增幅较高，建议压降到可归控额度，并要求预算管理者补充业务依据。`
  }
  if (item.riskTone === 'alert') {
    return `${item.name}建议结合上一周期实际发生额复核，避免预算冗余。`
  }
  return `${item.name}预算结构基本合理，建议按提交金额形成预算。`
}

function resolveSuggestedBudgetAmount(row) {
  const amount = Number(row.amount || row.budgetAmount || row.recommendedBudget || 0)
  const tone = String(row.riskTone || '').trim()
  if (tone === 'risk') return Math.round(amount * 0.92)
  if (tone === 'alert') return Math.round(amount * 0.96)
  return amount
}

function buildItemsFromBudgetContext(context, fallbackItems) {
  const rows = Array.isArray(context?.categoryRows) ? context.categoryRows : []
  const mode = resolveContextMode(context)
  if (!rows.length) return fallbackItems

  return rows.map((row, index) => {
    const fallback = fallbackItems[index] || PREVIOUS_QUARTER_SPEND[index] || {}
    const amount = Number(row.amount || fallback.recommendedBudget || 0)
    const used = Number(row.used || 0)
    const occupied = Number(row.occupied || 0)
    const value = used + occupied
    const suggestedBudget = resolveSuggestedBudgetAmount(row)
    const item = {
      key: row.code || fallback.key || `budget-${index}`,
      name: row.name || fallback.name || '预算科目',
      value,
      previousValue: Number(fallback.previousValue || 0),
      recommendedBudget: suggestedBudget,
      color: BUDGET_REPORT_COLORS[row.code] || fallback.color || BUDGET_REPORT_COLORS.travel,
      drivers: Array.isArray(fallback.drivers) ? fallback.drivers : [],
      risk: row.note || `${row.name || '该费用类型'}预算提交金额为 ${compactCurrency(amount)}，已发生与已占用合计 ${compactCurrency(value)}。`,
      suggestion: buildFinanceSuggestion({ ...row, name: row.name || fallback.name, riskTone: row.riskTone }, mode),
      amountDisplay: compactCurrency(value),
      display: row.usageRateLabel || '0.0%',
      share: row.usageRateLabel || '0.0%',
      trend: row.usageRateLabel || '0.0%',
      trendTone: row.riskTone === 'risk' ? 'risk' : row.riskTone === 'alert' ? 'warn' : 'stable',
      recommendedDisplay: compactCurrency(suggestedBudget),
      editableBudget: amount,
      suggestedBudget,
      submittedNote: row.note || '',
      financeSuggestion: buildFinanceSuggestion({ ...row, name: row.name || fallback.name, riskTone: row.riskTone }, mode)
    }
    return item
  })
}

export function shouldUseBudgetCompileReport(rawText, options = {}) {
  const sessionType = String(options.sessionType || '').trim()
  const entrySource = String(options.entrySource || '').trim()
  const budgetContext = normalizeBudgetContext(options.budgetContext)
  const text = normalizeBudgetText(rawText)
  const hasTargetPeriod = parseQuarter(rawText) || hasExplicitYear(rawText)
  const hasBudgetKeyword = /(预算|budget)/.test(text)
  const hasCompileKeyword = /(编制|制定|测算|生成|规划|预算一下|编辑|修改|调整|compile|create|plan|edit)/.test(text)
  const hasReviewKeyword = /(审核|复核|审预算|形成预算|回退预算|review|audit)/.test(text)
  const isBudgetContext = sessionType === 'budget' || entrySource === 'budget'
  const isWholeBudgetCompileIntent = hasBudgetKeyword && hasCompileKeyword && hasTargetPeriod
  const isBudgetContextPeriodIntent = isBudgetContext && hasBudgetKeyword && (hasTargetPeriod || hasReviewKeyword)
  const isBudgetContextEditIntent = isBudgetContext && hasBudgetKeyword && hasCompileKeyword

  return Boolean(
    (isBudgetContext && budgetContext) ||
      (
        text &&
        (isWholeBudgetCompileIntent || isBudgetContextPeriodIntent || isBudgetContextEditIntent)
      )
  )
}

export function buildBudgetCompileReport(rawText, user = {}, budgetContext = null) {
  const context = normalizeBudgetContext(budgetContext)
  const contextMode = resolveContextMode(context)
  const isReviewMode = contextMode === 'review'
  const targetYear = parseYear(rawText)
  const parsedQuarter = parseQuarter(rawText)
  const isAnnualBudget = !parsedQuarter
  const targetQuarter = parsedQuarter || 1
  const previous = isAnnualBudget
    ? { year: targetYear - 1, quarter: 0 }
    : resolvePreviousPeriod(targetYear, targetQuarter)
  const periodMultiplier = isAnnualBudget ? 4 : 1
  const totalSpend = PREVIOUS_QUARTER_SPEND.reduce((sum, item) => sum + item.value * periodMultiplier, 0)
  const totalBudget = 1320000 * periodMultiplier
  const recommendedTotal = PREVIOUS_QUARTER_SPEND.reduce((sum, item) => sum + item.recommendedBudget * periodMultiplier, 0)
  const departmentName = String(
    context?.departmentName ||
    resolveDepartmentNameFromText(rawText) ||
    user.departmentName ||
    user.department ||
    user.department_name ||
    ''
  ).trim() || '当前部门'

  const simulatedItems = PREVIOUS_QUARTER_SPEND.map((item) => {
    const value = item.value * periodMultiplier
    const previousValue = item.previousValue * periodMultiplier
    const recommendedBudget = item.recommendedBudget * periodMultiplier
    const risk = isAnnualBudget
      ? item.risk
        .replace(/Q2/g, `${previous.year}年度`)
        .replace(/Q3/g, `${targetYear}年度`)
        .replace(/季度/g, '年度')
      : item.risk
    const suggestion = isAnnualBudget
      ? item.suggestion
        .replace(/Q3/g, `${targetYear}年度`)
        .replace(/季度/g, '年度')
        .replace(/52-56 万/g, '208-224 万')
        .replace(/30-32 万/g, '120-128 万')
        .replace(/19-20 万/g, '76-80 万')
        .replace(/10-11 万/g, '40-44 万')
      : item.suggestion
    const trendValue = item.previousValue
      ? ((value - previousValue) / previousValue) * 100
      : 0
    return {
      ...item,
      value,
      previousValue,
      recommendedBudget,
      amountDisplay: compactCurrency(value),
      display: percent(value, totalSpend),
      share: percent(value, totalSpend),
      trend: `${trendValue >= 0 ? '+' : ''}${trendValue.toFixed(1)}%`,
      trendTone: trendValue >= 10 ? 'risk' : trendValue >= 0 ? 'warn' : 'stable',
      recommendedDisplay: compactCurrency(recommendedBudget),
      editableBudget: recommendedBudget,
      reminderThreshold: item.key === 'communication' || item.key === 'office' ? 60 : 70,
      alertThreshold: item.key === 'communication' || item.key === 'office' ? 70 : 80,
      riskThreshold: item.key === 'communication' || item.key === 'office' ? 80 : 90,
      risk,
      suggestion,
      editNote: suggestion
    }
  })
  const items = buildItemsFromBudgetContext(context, simulatedItems)
  const reportSpend = isReviewMode
    ? items.reduce((sum, item) => sum + Number(item.value || 0), 0)
    : totalSpend

  const topItem = [...items].sort((a, b) => b.value - a.value)[0]
  const growthItem = [...items].sort((a, b) => {
    const aGrowth = a.previousValue ? (a.value - a.previousValue) / a.previousValue : 0
    const bGrowth = b.previousValue ? (b.value - b.previousValue) / b.previousValue : 0
    return bGrowth - aGrowth
  })[0]

  const submittedBudgetTotal = items.reduce((sum, item) => sum + Number(item.editableBudget || item.recommendedBudget || 0), 0)
  const financeSuggestedTotal = items.reduce((sum, item) => sum + Number(item.suggestedBudget || item.recommendedBudget || 0), 0)

  return {
    type: 'budget_compile_analysis',
    mode: contextMode,
    title: isReviewMode
      ? `${departmentName}${context?.periodLabel || ''}预算审核分析报告`
      : isAnnualBudget
        ? `${targetYear}年度预算编制前置分析报告`
        : `${targetYear}年${targetQuarter}季度预算编制前置分析报告`,
    subtitle: isReviewMode
      ? `${context?.budgetNo || '部门提交预算'} / ${context?.version || '待审核版本'}`
      : isAnnualBudget
        ? `基于${previous.year}年度预算执行模拟数据`
        : `基于${previous.year}年${previous.quarter}季度预算执行模拟数据`,
    departmentName,
    targetPeriod: context?.periodLabel || (isAnnualBudget ? `${targetYear}年度` : `${targetYear}年${QUARTER_NAME_MAP[targetQuarter]}`),
    basePeriod: isAnnualBudget ? `${previous.year}年度` : `${previous.year}年${QUARTER_NAME_MAP[previous.quarter]}`,
    periodType: isAnnualBudget ? '年度预算' : '季度预算',
    centerValue: compactCurrency(reportSpend),
    centerLabel: isAnnualBudget ? '去年开销' : '上季度开销',
    summary: {
      totalBudget: compactCurrency(isReviewMode ? submittedBudgetTotal : totalBudget),
      totalSpend: compactCurrency(reportSpend),
      usageRate: percent(reportSpend, isReviewMode ? submittedBudgetTotal : totalBudget),
      recommendedTotal: compactCurrency(isReviewMode ? financeSuggestedTotal : recommendedTotal)
    },
    macroInsights: [
      isReviewMode
        ? `${departmentName}本次提交预算 ${compactCurrency(submittedBudgetTotal)}，AI 建议可归控预算 ${compactCurrency(financeSuggestedTotal)}，请高级财务人员确认是否需要回退调整。`
        : `${isAnnualBudget ? `${previous.year}年度` : `${previous.year}年${previous.quarter}季度`}实际开销 ${compactCurrency(totalSpend)}，预算使用率 ${percent(totalSpend, totalBudget)}，整体仍在可控区间。`,
      `${topItem.name}是最大开销项，占 ${topItem.share}，建议作为${isReviewMode ? '审核重点' : `${isAnnualBudget ? `${targetYear}年度` : `${targetYear}年${targetQuarter}季度`}预算编制的第一优先级`}。`,
      isReviewMode
        ? `${growthItem.name}需要重点核对预算说明、业务依据和可归控空间；如果建议预算低于提交预算，应写明回退理由。`
        : `${growthItem.name}环比增长 ${growthItem.trend}，需要在预算说明中提前解释业务驱动，避免后续报销阶段反复补充材料。`
    ],
    items,
    editableDraft: {
      status: 'editing',
      mode: contextMode,
      departmentName,
      rows: items.map((item) => ({
        key: item.key,
        name: item.name,
        departmentName,
        budgetAmount: item.editableBudget,
        suggestedBudget: item.suggestedBudget || item.recommendedBudget || item.editableBudget,
        submittedNote: item.submittedNote || item.editNote,
        financeSuggestion: item.financeSuggestion || ''
      }))
    },
    recommendations: isReviewMode
      ? [
          '审核时先看预算管理者提交说明是否覆盖业务增长、已占用事项和可归控边界。',
          '建议预算低于提交预算时，应在“建议”列写明压降原因，并回退预算给预算管理者再次编辑。',
          '如果建议预算与提交预算一致且说明充分，可以直接形成正式预算。'
        ]
      : [
          `建议${isAnnualBudget ? `${targetYear}年度` : `${targetYear}年${targetQuarter}季度`}总预算先按 ${compactCurrency(recommendedTotal)} 编制，再预留 5%-8% 部门机动池。`,
          '差旅和招待费采用更早的提醒阈值，通信和办公用品保持稳定额度，避免把预算过度分散到低波动项目。',
          '正式编制时建议把重点项目、客户活动和集中采购计划写入预算说明，后续费用控制会更容易解释。'
        ],
    generatedAt: '模拟数据 · 用于 Demo 预览'
  }
}

export async function handleBudgetCompileReportSubmit(runtime) {
  const {
    adjustComposerTextareaHeight,
    clearAttachedFiles,
    completeFlowStep,
    composerBusinessTimeDraftTouched,
    composerBusinessTimeTags,
    composerDraft,
    createMessage,
    currentUser,
    fileInputRef,
    fileNames,
    messages,
    nextTick,
    options,
    persistSessionState,
    rawText,
    replaceMessage,
    resetFlowRun,
    refreshCurrentUserFromBackend,
    budgetContext,
    scrollToBottom,
    startFlowStep,
    submitting,
    userText
  } = runtime
  const analysisStartedAt = Date.now()
  const context = normalizeBudgetContext(budgetContext)
  const isReviewRequest = resolveContextMode(context) === 'review'
  const isAnnualRequest = hasExplicitYear(rawText) && !parseQuarter(rawText)
  const basePeriodLabel = isReviewRequest ? '部门提交预算分析' : isAnnualRequest ? '去年预算开销分析' : '上季度预算开销分析'
  const recommendationLabel = isReviewRequest ? '高级财务审核建议生成' : isAnnualRequest ? '年度预算编制建议生成' : '预算编制建议生成'
  resetFlowRun()
  startFlowStep('budget-prior-quarter-analysis', {
    title: basePeriodLabel,
    tool: 'budget.analysis.previous_quarter',
    detail: isReviewRequest
      ? '正在读取部门提交预算表，分析费用结构、历史消耗和可归控空间...'
      : isAnnualRequest
        ? '正在汇总去年费用占比、增长点和年度预算编制建议...'
        : '正在汇总上季度费用占比、增长点和下一季度编制建议...'
  })
  startFlowStep('budget-compile-guidance', {
    title: recommendationLabel,
    tool: 'budget.compile.recommendation',
    detail: '正在生成预算编制前置分析报告...'
  })
  if (!options.skipUserMessage) {
    messages.value.push(createMessage('user', userText, fileNames))
  }
  const pendingMessage = createMessage(
    'assistant',
    isReviewRequest
      ? '我先加载部门提交的预算表，结合费用结构和预算说明生成高级财务审核建议。'
      : isAnnualRequest
        ? '我先不直接进入预算表单，先执行去年预算开销结构分析，再给您一版年度预算编制建议。'
        : '我先不直接进入预算表单，先执行上季度预算开销结构分析，再给您一版下一季度预算编制建议。',
    [],
    { meta: ['预算分析中'] }
  )
  messages.value.push(pendingMessage)
  composerDraft.value = ''
  composerBusinessTimeTags.value = []
  composerBusinessTimeDraftTouched.value = false
  clearAttachedFiles()
  if (fileInputRef.value) {
    fileInputRef.value.value = ''
  }
  submitting.value = true
  nextTick(() => {
    adjustComposerTextareaHeight()
    scrollToBottom()
  })
  persistSessionState()

  try {
    await new Promise((resolve) => setTimeout(resolve, 360))
    let reportUser = currentUser.value || {}
    const hasUserDepartment = String(
      reportUser.departmentName || reportUser.department || reportUser.department_name || ''
    ).trim()
    if (!hasUserDepartment && typeof refreshCurrentUserFromBackend === 'function') {
      await refreshCurrentUserFromBackend({ silent: true })
      reportUser = currentUser.value || reportUser
    }
    const budgetReport = buildBudgetCompileReport(rawText, reportUser, context)
    completeFlowStep(
      'budget-prior-quarter-analysis',
      isReviewRequest
        ? '已完成部门提交预算、费用结构和风险点分析'
        : isAnnualRequest
          ? '已完成去年费用占比、增长点和风险点分析'
          : '已完成上季度费用占比、增长点和风险点分析',
      Date.now() - analysisStartedAt
    )
    completeFlowStep(
      'budget-compile-guidance',
      isReviewRequest ? '已生成高级财务审核建议' : isAnnualRequest ? '已生成年度预算编制建议' : '已生成下一季度预算编制建议',
      Date.now() - analysisStartedAt
    )
    replaceMessage(pendingMessage.id, createMessage(
      'assistant',
      isReviewRequest
        ? '下面先按部门提交的预算草案做一版审核分析。正式接入预算池后，这里会替换成真实提交记录、历史消耗和归控建议。'
        : isAnnualRequest
          ? '下面先按去年模拟数据做一版年度预算编制前置分析。正式接入预算池后，这里会替换成真实部门预算和报销消耗数据。'
          : '下面先按上季度模拟数据做一版预算编制前置分析。正式接入预算池后，这里会替换成真实部门预算和报销消耗数据。',
      [],
      {
        meta: ['预算分析报告', '模拟数据'],
        budgetReport
      }
    ))
    persistSessionState()
  } finally {
    submitting.value = false
    nextTick(scrollToBottom)
  }
  return null
}
