import { extractExpenseClaimItems } from '../services/reimbursements.js'
import {
  isClaimOwnedByCurrentUser,
  isExpenseApplicationClaim,
  matchesRequiredApplicationExpenseType,
  normalizeRequiredApplicationCandidate
} from '../views/scripts/travelReimbursementApplicationLinkModel.js'
import {
  normalizeApplicationPreview,
  resolveApplicationDateRange
} from './expenseApplicationPreview.js'

const APPLICATION_BUDGET_REVIEW_THRESHOLD = 90

function normalizeText(value) {
  return String(value || '').trim()
}

function normalizeMoney(value) {
  if (typeof value === 'number') {
    return Number.isFinite(value) ? value : 0
  }
  const normalized = normalizeText(value).replace(/,/g, '')
  const match = normalized.match(/-?\d+(?:\.\d+)?/)
  const amount = match ? Number(match[0]) : 0
  return Number.isFinite(amount) && amount > 0 ? amount : 0
}

function formatMoney(value) {
  const amount = normalizeMoney(value)
  if (!amount) {
    return ''
  }
  return `${new Intl.NumberFormat('zh-CN', {
    maximumFractionDigits: Number.isInteger(amount) ? 0 : 2,
    minimumFractionDigits: Number.isInteger(amount) ? 0 : 2
  }).format(amount)}元`
}

function escapeMarkdownCell(value) {
  return normalizeText(value).replace(/\|/g, '\\|') || '-'
}

function buildApplicationDetailHref(item = {}) {
  const claimNo = normalizeText(item.claimNo)
  const reference = claimNo && claimNo !== '未编号申请单'
    ? claimNo
    : normalizeText(item.claimId)
  return reference ? `#ai-open-application-detail:${encodeURIComponent(reference)}` : ''
}

function buildApplicationDetailActionCell(item = {}) {
  const href = buildApplicationDetailHref(item)
  return href ? `[查看](${href})` : '-'
}

function parseDate(value) {
  const dateText = normalizeText(value)
  if (!/^\d{4}-\d{2}-\d{2}$/.test(dateText)) {
    return null
  }
  const date = new Date(`${dateText}T00:00:00Z`)
  return Number.isNaN(date.getTime()) ? null : date
}

function resolveDateRange(value, daysText = '') {
  const resolved = resolveApplicationDateRange(value, daysText)
  if (!resolved) {
    return null
  }
  const startText = normalizeText(resolved.startDate)
  const endText = normalizeText(resolved.endDate || resolved.startDate)
  const startDate = parseDate(startText)
  const endDate = parseDate(endText)
  if (!startDate || !endDate) {
    return null
  }
  return startDate <= endDate
    ? { startText, endText, startDate, endDate }
    : { startText: endText, endText: startText, startDate: endDate, endDate: startDate }
}

function rangesOverlap(left, right) {
  return Boolean(left && right && left.startDate <= right.endDate && right.startDate <= left.endDate)
}

function resolvePreviewDateRange(preview) {
  const fields = normalizeApplicationPreview(preview).fields || {}
  return resolveDateRange(fields.time, fields.days)
}

function resolvePreviewAmount(preview) {
  const normalized = normalizeApplicationPreview(preview)
  const fields = normalized.fields || {}
  const policyEstimate = normalized.policyEstimate && typeof normalized.policyEstimate === 'object'
    ? normalized.policyEstimate
    : {}
  return normalizeMoney(
    fields.amount ||
      fields.policyTotalAmount ||
      fields.reimbursementAmount ||
      policyEstimate.system_total_amount
  )
}

function resolveApplicationClaims(claimsPayload, currentUser, expenseType) {
  return extractExpenseClaimItems(claimsPayload)
    .filter((claim) => (
      isExpenseApplicationClaim(claim) &&
      isClaimOwnedByCurrentUser(claim, currentUser) &&
      matchesRequiredApplicationExpenseType(claim, expenseType)
    ))
    .map((claim) => normalizeRequiredApplicationCandidate(claim))
}

function buildOverlapPrecheck(preview, claimsPayload, currentUser, expenseType) {
  const targetRange = resolvePreviewDateRange(preview)
  if (!targetRange) {
    return {
      status: 'unknown',
      summary: '暂未识别到完整出差日期，无法判断是否与已有申请时间重叠。'
    }
  }

  const applications = resolveApplicationClaims(claimsPayload, currentUser, expenseType)
  const matches = applications
    .map((application) => {
      const range = resolveDateRange(application.business_time)
      return {
        ...application,
        range
      }
    })
    .filter((application) => rangesOverlap(targetRange, application.range))
    .slice(0, 3)

  if (!matches.length) {
    return {
      status: 'ok',
      summary: `未发现 ${targetRange.startText} 至 ${targetRange.endText} 期间已有重叠的差旅申请单。`,
      matches: []
    }
  }

  return {
    status: 'warning',
    summary: `发现 ${matches.length} 张同时间段可能重叠的申请单，暂不能继续发起新的出差申请。`,
    matches: matches.map((item) => ({
      claimId: item.id || '',
      claimNo: item.claim_no || '未编号申请单',
      time: item.business_time || '',
      statusLabel: item.status_label || '',
      reason: item.reason || ''
    }))
  }
}

function isBlockingPrecheck(precheck = {}) {
  return precheck?.overlap?.status === 'warning'
}

export function isAiApplicationPrecheckBlocking(precheck = {}) {
  return isBlockingPrecheck(precheck)
}

function buildOverlapMatchTable(matches = []) {
  const rows = Array.isArray(matches) ? matches : []
  if (!rows.length) {
    return ''
  }
  return [
    '| 单据编号 | 申请时间 | 状态 | 事由 | 操作 |',
    '| --- | --- | --- | --- | --- |',
    ...rows.map((item) => [
      escapeMarkdownCell(item.claimNo),
      escapeMarkdownCell(item.time),
      escapeMarkdownCell(item.statusLabel),
      escapeMarkdownCell(item.reason),
      buildApplicationDetailActionCell(item)
    ].join(' | ')).map((row) => `| ${row} |`)
  ].join('\n')
}

function resolveBudgetNumbers(summary = {}) {
  const totalAmount = normalizeMoney(summary.total_amount || summary.totalAmount)
  const reservedAmount = normalizeMoney(summary.reserved_amount || summary.reservedAmount)
  const consumedAmount = normalizeMoney(summary.consumed_amount || summary.consumedAmount)
  const availableAmount = normalizeMoney(summary.available_amount || summary.availableAmount)
  return {
    totalAmount,
    reservedAmount,
    consumedAmount,
    availableAmount,
    usedAmount: reservedAmount + consumedAmount
  }
}

function buildBudgetPrecheck(preview, budgetSummary) {
  const amount = resolvePreviewAmount(preview)
  const missingFields = normalizeApplicationPreview(preview).missingFields || []
  if (!amount) {
    const reason = missingFields.includes('出行方式')
      ? '当前还缺出行方式，交通费用和申请总额暂未完成测算。'
      : '当前申请总额暂未完成测算。'
    return {
      status: 'pending',
      requiresBudgetReview: false,
      summary: `${reason}补齐后会刷新预算占用；若达到 ${APPLICATION_BUDGET_REVIEW_THRESHOLD}% 预算复核线或超预算，系统会增加预算管理者审核。`
    }
  }

  if (!budgetSummary || typeof budgetSummary !== 'object') {
    return {
      status: 'unknown',
      requiresBudgetReview: false,
      summary: `本次预计申请金额 ${formatMoney(amount)}。预算接口暂未返回，以提交时系统预算复核为准；若达到 ${APPLICATION_BUDGET_REVIEW_THRESHOLD}% 复核线或超预算，会增加预算管理者审核。`
    }
  }

  const budget = resolveBudgetNumbers(budgetSummary)
  if (!budget.totalAmount) {
    return {
      status: 'unknown',
      requiresBudgetReview: false,
      summary: `本次预计申请金额 ${formatMoney(amount)}。当前部门预算总额暂未配置或暂未返回，提交时会继续做预算归口复核。`
    }
  }

  const afterUsed = budget.usedAmount + amount
  const afterUsageRate = Number(((afterUsed / budget.totalAmount) * 100).toFixed(2))
  if (amount > budget.availableAmount) {
    return {
      status: 'warning',
      requiresBudgetReview: true,
      summary: `本次预计申请金额 ${formatMoney(amount)}，当前可用预算 ${formatMoney(budget.availableAmount)}，预计超出 ${formatMoney(amount - budget.availableAmount)}，提交后需要预算管理者审核。`
    }
  }
  if (afterUsageRate >= APPLICATION_BUDGET_REVIEW_THRESHOLD) {
    return {
      status: 'warning',
      requiresBudgetReview: true,
      summary: `本次预计申请金额 ${formatMoney(amount)}，审批后预算占用约 ${afterUsageRate}%，达到 ${APPLICATION_BUDGET_REVIEW_THRESHOLD}% 复核线，提交后需要预算管理者审核。`
    }
  }

  return {
    status: 'ok',
    requiresBudgetReview: false,
    summary: `本次预计申请金额 ${formatMoney(amount)}，审批后预算占用约 ${afterUsageRate}%，未达到 ${APPLICATION_BUDGET_REVIEW_THRESHOLD}% 复核线。`
  }
}

export function buildAiApplicationPrecheck(preview = {}, {
  claimsPayload = null,
  budgetSummary = null,
  currentUser = {},
  expenseType = 'travel',
  budgetError = null
} = {}) {
  const normalizedPreview = normalizeApplicationPreview(preview)
  const budget = budgetError
    ? {
        status: 'unknown',
        requiresBudgetReview: false,
        summary: `预算接口暂未返回：${normalizeText(budgetError?.message || budgetError) || '当前无可用预算数据'}。提交时系统仍会按预算余额、风险规则判断是否增加预算管理者审核。`
      }
    : buildBudgetPrecheck(normalizedPreview, budgetSummary)
  return {
    overlap: buildOverlapPrecheck(normalizedPreview, claimsPayload, currentUser, expenseType),
    budget,
    missingFields: Array.isArray(normalizedPreview.missingFields) ? normalizedPreview.missingFields : []
  }
}

export function buildAiApplicationPrecheckThinkingEvents(precheck = {}) {
  const blocked = isBlockingPrecheck(precheck)
  return [
    {
      eventId: 'application-precheck-overlap',
      title: '核查同时间段申请单',
      content: precheck?.overlap?.summary || '已完成已有申请单核查。',
      status: precheck?.overlap?.status === 'warning' ? 'completed' : 'completed'
    },
    {
      eventId: 'application-precheck-budget',
      title: '评估预算与审批影响',
      content: precheck?.budget?.summary || '已完成预算影响评估。',
      status: 'completed'
    },
    {
      eventId: 'application-precheck-form',
      title: blocked ? '暂停生成申请表' : '生成申请表草稿',
      content: blocked
        ? '因发现同时间段已有申请单，已暂停生成新的申请表，等待用户核对申请时间。'
        : '已将识别到的时间、地点、事由和申请人信息预填到申请表。',
      status: 'completed'
    }
  ]
}

export function buildAiApplicationPrecheckMessage(preview = {}, precheck = {}) {
  if (isBlockingPrecheck(precheck)) {
    const matchTable = buildOverlapMatchTable(precheck?.overlap?.matches)
    const lines = [
      '### 发现同时间段已有申请单',
      '',
      '**我已完成发起前的单据重叠核查**，当前不能继续生成新的出差申请表。',
      '',
      `> **时间重叠提醒**：${precheck?.overlap?.summary || '发现同时间段已有申请单，暂不能继续发起新的出差申请。'}`,
    ]
    if (matchTable) {
      lines.push('', matchTable)
    }
    lines.push(
      '',
      '**后续行动建议**：',
      '- 请先检查本次申请时间是否填写正确。若日期填错，请直接回复正确的出发时间和返回时间，我会重新查询；',
      '- 若日期无误，请先处理或关联已有申请单，避免重复申请。',
      '',
      '我会先暂停本次申请表生成，不会开放保存草稿或提交入口。'
    )
    return lines.join('\n')
  }

  const normalized = normalizeApplicationPreview(preview)
  const missingFields = Array.isArray(normalized.missingFields) ? normalized.missingFields : []
  const missingText = missingFields.length ? missingFields.join('、') : '暂无'
  const budgetPrefix = precheck?.budget?.requiresBudgetReview ? '预算管理者审核提示' : '预算与审批影响'
  const overlapPrefix = precheck?.overlap?.status === 'warning' ? '时间重叠提醒' : '单据重叠核查'
  const lines = [
    '### 出差申请表草稿已生成',
    '',
    '**我已完成发起前的单据与预算预审**，并为您生成一张完整的出差申请表。',
    '',
    '**发起前预审结果**：',
    `- **${overlapPrefix}**：${precheck?.overlap?.summary || '已完成已有单据核查。'}`,
    `- **${budgetPrefix}**：${precheck?.budget?.summary || '已完成预算影响评估。'}`,
    `- **仍需补充**：${missingText}`,
    '',
    '请直接点击表格中的字段补充或修改；费用测算会根据地点、天数和出行方式自动更新。'
  ]

  if (missingFields.length) {
    lines.push('', `当前还需要补充：**${missingText}**。`)
  } else {
    lines.push('', '信息已基本齐全，您可以保存草稿，或直接提交进入审批。')
  }

  return lines.join('\n')
}

export function buildAiApplicationSubmitConflictMessage(preview = {}, precheck = {}) {
  const matchTable = buildOverlapMatchTable(precheck?.overlap?.matches)
  const normalized = normalizeApplicationPreview(preview)
  const fields = normalized.fields || {}
  const currentRange = resolveDateRange(fields.time, fields.days)
  const currentRangeText = currentRange
    ? `${currentRange.startText} 至 ${currentRange.endText}`
    : normalizeText(fields.time) || '待确认'
  const lines = [
    '### 发现相同日期已有申请单',
    '',
    '**我已完成提交前的单据重叠核查**，发现相同或重叠日期已有差旅申请单，当前不能继续提交。',
    '',
    `> **相同日期提醒**：${precheck?.overlap?.summary || '发现相同日期已有申请单，请先核对后再提交。'}`,
    '',
    `**本次申请时间**：${currentRangeText}`,
  ]
  if (matchTable) {
    lines.push('', matchTable)
  }
  lines.push(
    '',
    '**后续行动建议**：',
    '- 请先核对申请时间是否填写正确。若日期填错，请直接回复正确的出发时间和返回时间，我会重新查询；',
    '- 若日期无误，请先查看或处理已有申请单，避免重复申请。',
    '',
    '我会先暂停本次提交，不会生成新的审批流。'
  )
  return lines.join('\n')
}
