import ontologyBusinessContract from '../../../shared/ontology_business_contract.json' with { type: 'json' }

export const ASSISTANT_SCOPE_ACTION_SWITCH = 'switch_assistant_session'
export const ASSISTANT_SCOPE_ACTION_UNSUPPORTED = 'unsupported_business_intent'
// 点击后把 payload.fill_text 填充到输入框，不切换会话、不自动提交，交由用户编辑后自行发送。
export const ASSISTANT_SCOPE_ACTION_FILL_COMPOSER = 'fill_composer'

export const ASSISTANT_SCOPE_SESSION_APPLICATION = 'application'
export const ASSISTANT_SCOPE_SESSION_EXPENSE = 'expense'
export const ASSISTANT_SCOPE_SESSION_APPROVAL = 'approval'
export const ASSISTANT_SCOPE_SESSION_KNOWLEDGE = 'knowledge'
export const ASSISTANT_SCOPE_SESSION_STEWARD = 'steward'

const FALLBACK_SESSION_SCOPE_CONFIG = {
  [ASSISTANT_SCOPE_SESSION_STEWARD]: {
    label: '小财管家',
    icon: 'mdi mdi-account-tie-outline',
    scope: '多任务拆解、附件归集、申请助手和报销助手统一调度'
  },
  [ASSISTANT_SCOPE_SESSION_APPLICATION]: {
    label: '申请助手',
    icon: 'mdi mdi-file-plus-outline',
    scope: '费用申请、事前审批、申请材料清单、申请单状态查询'
  },
  [ASSISTANT_SCOPE_SESSION_EXPENSE]: {
    label: '报销助手',
    icon: 'mdi mdi-receipt-text-plus-outline',
    scope: '发起报销、票据识别、草稿归集、报销单状态查询和报销信息核对'
  },
  [ASSISTANT_SCOPE_SESSION_APPROVAL]: {
    label: '审核助手',
    icon: 'mdi mdi-clipboard-check-outline',
    scope: '待审单据查询、审批动作、风险解释和审核意见草稿'
  },
  [ASSISTANT_SCOPE_SESSION_KNOWLEDGE]: {
    label: '财务知识助手',
    icon: 'mdi mdi-book-open-page-variant-outline',
    scope: '财务制度、报销标准、票据要求、流程规则和政策口径解释'
  }
}

const ONTOLOGY_BUSINESS_CONTRACT = ontologyBusinessContract || {}
const SESSION_SCOPE_CONFIG = ONTOLOGY_BUSINESS_CONTRACT.sessions || FALLBACK_SESSION_SCOPE_CONFIG
const SESSION_SCOPE_TYPES = Object.keys(SESSION_SCOPE_CONFIG)
const BUSINESS_SIGNAL_GROUPS = ONTOLOGY_BUSINESS_CONTRACT.businessSignals || {}

const APPLICATION_PATTERN =
  /费用申请|发起申请|申请单|事前申请|事前审批|前置审批|出差申请|申请出差|差旅申请|申请差旅|采购申请|用款申请|预算申请|申请材料|材料清单|先申请|立项申请/
const APPLICATION_PLANNING_PATTERN =
  /计划|安排|准备|需要|打算|预计|申请|发起|提交|提出|先走|先办|要去|将要|下周|下月|明天|后天|近期|月底|去|到|赴|前往|参加/
const APPLICATION_BUSINESS_PATTERN =
  /出差|差旅|客户现场|现场|客户|项目|部署|实施|支撑|支持|协助|拜访|调研|培训|会议|会务|驻场|上线|验收|采购|购置|用款|立项/
const APPLICATION_FUTURE_OR_DURATION_PATTERN =
  /明天|后天|下周|下月|近期|月底|预计|计划|安排|准备|将要|[0-9]+天|[一二两三四五六七八九十]+天/
const APPLICATION_ROUTE_PATTERN =
  /(?:去|到|赴|前往)[^，,。；;！？?!\n]{0,24}(?:出差|差旅|客户|现场|项目|部署|实施|支撑|支持|协助|拜访|调研|培训|会议|驻场|上线|验收)|(?:出差|差旅)[^，,。；;！？?!\n]{0,24}(?:[0-9]+天|[一二两三四五六七八九十]+天|客户|现场|项目|部署|实施|支撑|支持|协助|拜访|调研|培训|会议|驻场|上线|验收)/
const AMBIGUOUS_TRAVEL_DATE_RANGE_PATTERN =
  /(?:\d{1,2}月)?\d{1,2}(?:日|号)?(?:-|—|~|～|至|到)\d{1,2}(?:日|号)?[^，,。；;！？?!\n]{0,32}(?:出差|差旅|客户|现场|项目|部署|实施|支撑|支持|协助|拜访|调研|培训|会议|驻场|上线|验收)/
const EXPLICIT_APPLICATION_ACTION_PATTERN =
  /费用申请|发起申请|申请单|事前申请|事前审批|前置审批|出差申请|申请出差|差旅申请|申请差旅|采购申请|用款申请|预算申请|先申请|补办申请|补申请|补办出差申请|创建申请|提交申请/
const COMPLETED_EXPENSE_PATTERN =
  /已经|已|昨天|前天|上周|上月|去年|花了|花销|消费|垫付|支付|付了|买了|采购了|招待了|发生了/
const EXPENSE_PATTERN =
  /报销|报销单|票据|发票|火车票|高铁票|机票|飞机票|的士票|出租车|网约车|酒店票|住宿票|住宿单据|保存草稿|草稿|费用明细|归集|上传.*票|关联单据|继续下一步/
const APPROVAL_PATTERN =
  /待我审核|待审|审核|审批|审核意见|审批意见|审批通过|审批驳回|驳回|退回|审核中心|审批中心|领导审批|财务审核|处理意见/
const KNOWLEDGE_PATTERN =
  /制度|政策|标准|规则|规定|流程|口径|依据|上限|额度|补贴|住宿标准|差旅标准|报销标准|票据要求|可不可以|能不能|怎么规定|如何计算|怎么算/
const EXPENSE_OPERATION_PATTERN = /发起报销|报销单|票据|发票|火车票|高铁票|机票|的士票|草稿|归集|上传|关联单据|继续下一步/
const CURRENT_CLAIM_RISK_PATTERN = /这张|当前|本单|该单|单据|风险|超标|异常|重复|待补/
const FINANCE_OPERATING_PATTERN = buildKeywordPattern([
  ...(BUSINESS_SIGNAL_GROUPS.budget || []),
  ...(BUSINESS_SIGNAL_GROUPS.accounts_receivable || []),
  ...(BUSINESS_SIGNAL_GROUPS.accounts_payable || [])
])
const CONTEXTUAL_FOLLOW_UP_PATTERN = buildExactKeywordPattern(ONTOLOGY_BUSINESS_CONTRACT.contextualFollowUps || [])

export const SUPPORTED_BUSINESS_SCOPE_TEXT = Array.isArray(ONTOLOGY_BUSINESS_CONTRACT.supportedBusinessScopes)
  ? ONTOLOGY_BUSINESS_CONTRACT.supportedBusinessScopes
  : [
      '费用申请/事前审批',
      '报销与票据识别',
      '审批审核与风险解释',
      '财务制度、报销标准和流程规则问答',
      '预算、应收、应付等财务经营查询',
      '小财管家多任务拆解和附件归集'
    ]

function escapeRegExp(value) {
  return String(value || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
}

function buildKeywordPattern(keywords = []) {
  const source = keywords
    .map((keyword) => String(keyword || '').trim())
    .filter(Boolean)
    .map(escapeRegExp)
    .join('|')
  return source ? new RegExp(source) : /$a/
}

function buildExactKeywordPattern(keywords = []) {
  const source = keywords
    .map((keyword) => String(keyword || '').trim())
    .filter(Boolean)
    .map(escapeRegExp)
    .join('|')
  return source ? new RegExp(`^(${source})$`) : /$a/
}

function normalizeSessionType(sessionType) {
  const normalized = String(sessionType || '').trim()
  return SESSION_SCOPE_TYPES.includes(normalized) ? normalized : ASSISTANT_SCOPE_SESSION_EXPENSE
}

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

export function hasReimbursementIntentSignal(rawText) {
  return EXPENSE_PATTERN.test(normalizeText(rawText))
}

export function hasExpenseApplicationIntentSignal(rawText) {
  const text = normalizeText(rawText)
  if (!text) {
    return false
  }

  if (APPLICATION_PATTERN.test(text)) {
    return true
  }
  if (hasReimbursementIntentSignal(text) || COMPLETED_EXPENSE_PATTERN.test(text)) {
    return false
  }
  if (KNOWLEDGE_PATTERN.test(text) && !EXPENSE_OPERATION_PATTERN.test(text)) {
    return false
  }

  const hasBusinessSignal = APPLICATION_BUSINESS_PATTERN.test(text)
  const planningScore = APPLICATION_PLANNING_PATTERN.test(text) ? 1 : 0
  const timingScore = APPLICATION_FUTURE_OR_DURATION_PATTERN.test(text) ? 1 : 0
  const routeScore = APPLICATION_ROUTE_PATTERN.test(text) ? 2 : 0

  return hasBusinessSignal && planningScore + timingScore + routeScore >= 2
}

export function hasAmbiguousTravelFlowIntent(rawText) {
  const text = normalizeText(rawText)
  if (!text) {
    return false
  }
  if (
    EXPLICIT_APPLICATION_ACTION_PATTERN.test(text) ||
    EXPENSE_PATTERN.test(text) ||
    KNOWLEDGE_PATTERN.test(text)
  ) {
    return false
  }
  return AMBIGUOUS_TRAVEL_DATE_RANGE_PATTERN.test(text)
}

function resolveScopeConfig(sessionType) {
  return SESSION_SCOPE_CONFIG[normalizeSessionType(sessionType)] || SESSION_SCOPE_CONFIG[ASSISTANT_SCOPE_SESSION_EXPENSE]
}

export function inferAssistantScopeTarget(rawText, options = {}) {
  const text = normalizeText(rawText)
  if (!text) {
    return ''
  }

  if (hasAmbiguousTravelFlowIntent(text)) {
    return ASSISTANT_SCOPE_SESSION_STEWARD
  }

  const applicationMatched = hasExpenseApplicationIntentSignal(text)
  const expenseMatched = EXPENSE_PATTERN.test(text)
  const approvalMatched = APPROVAL_PATTERN.test(text)
  const knowledgeMatched = KNOWLEDGE_PATTERN.test(text)

  if (applicationMatched && expenseMatched) {
    return ASSISTANT_SCOPE_SESSION_STEWARD
  }

  if (approvalMatched && /(待我审核|待审|审核意见|审批意见|审批通过|审批驳回|驳回|退回|审核中心|审批中心|处理意见)/.test(text)) {
    return ASSISTANT_SCOPE_SESSION_APPROVAL
  }

  if (knowledgeMatched && !options.hasActiveReviewPayload && !EXPENSE_OPERATION_PATTERN.test(text)) {
    return ASSISTANT_SCOPE_SESSION_KNOWLEDGE
  }

  if (expenseMatched && !applicationMatched) {
    return ASSISTANT_SCOPE_SESSION_EXPENSE
  }

  if (applicationMatched && !expenseMatched) {
    return ASSISTANT_SCOPE_SESSION_APPLICATION
  }

  if (FINANCE_OPERATING_PATTERN.test(text)) {
    return ASSISTANT_SCOPE_SESSION_STEWARD
  }

  if (knowledgeMatched && !expenseMatched && !approvalMatched && !applicationMatched) {
    return ASSISTANT_SCOPE_SESSION_KNOWLEDGE
  }

  if (knowledgeMatched && !options.hasActiveReviewPayload) {
    return ASSISTANT_SCOPE_SESSION_KNOWLEDGE
  }

  if (approvalMatched) {
    return ASSISTANT_SCOPE_SESSION_APPROVAL
  }

  if (expenseMatched) {
    return ASSISTANT_SCOPE_SESSION_EXPENSE
  }

  if (applicationMatched) {
    return ASSISTANT_SCOPE_SESSION_APPLICATION
  }

  return ''
}

function shouldAllowCurrentExpensePolicyQuestion(rawText, currentSessionType, targetSessionType, options = {}) {
  if (
    normalizeSessionType(currentSessionType) !== ASSISTANT_SCOPE_SESSION_EXPENSE ||
    targetSessionType !== ASSISTANT_SCOPE_SESSION_KNOWLEDGE ||
    !options.hasActiveReviewPayload
  ) {
    return false
  }

  return CURRENT_CLAIM_RISK_PATTERN.test(normalizeText(rawText))
}

function buildScopeSwitchAction(targetSessionType, rawText, options = {}) {
  const target = resolveScopeConfig(targetSessionType)
  const carryText = String(rawText || '').trim()

  return {
    label: `切换到${target.label}`,
    description: `带着这条内容进入${target.label}继续处理`,
    icon: target.icon,
    action_type: ASSISTANT_SCOPE_ACTION_SWITCH,
    payload: {
      session_type: normalizeSessionType(targetSessionType),
      carry_text: carryText,
      carry_files: Boolean(options.attachmentCount)
    }
  }
}

function buildScopeBoundaryText(currentSessionType, targetSessionType) {
  const current = resolveScopeConfig(currentSessionType)
  const target = resolveScopeConfig(targetSessionType)

  return [
    `我先暂停在「${current.label}」里继续处理这条消息。`,
    '',
    `当前助手的业务范围是：${current.scope}。`,
    '',
    `您这条内容更适合交给「${target.label}」处理；它的业务范围是：${target.scope}。`,
    '',
    `建议切换到「${target.label}」后继续，我会尽量把这条内容带过去，避免在错误的会话里把流程跑偏。`
  ].join('\n')
}

function shouldAllowContextualFollowUp(rawText, currentSessionType, options = {}) {
  const text = normalizeText(rawText)
  if (options.hasActiveReviewPayload && CURRENT_CLAIM_RISK_PATTERN.test(text)) {
    return true
  }
  if (!text || !CONTEXTUAL_FOLLOW_UP_PATTERN.test(text)) {
    return false
  }
  return Boolean(
    options.hasActiveReviewPayload ||
    options.hasPendingApplicationPreview ||
    options.reviewAction ||
    currentSessionType
  )
}

function buildUnsupportedBusinessScopeSuggestedActions(options = {}) {
  const sharedOptions = {
    attachmentCount: options.attachmentCount || 0
  }
  const applicationAction = buildScopeSwitchAction(ASSISTANT_SCOPE_SESSION_APPLICATION, '申请下周去上海出差，支撑客户系统上线', sharedOptions)
  const expenseAction = buildScopeSwitchAction(ASSISTANT_SCOPE_SESSION_EXPENSE, '我要报销昨天的交通费', sharedOptions)
  const knowledgeAction = buildScopeSwitchAction(ASSISTANT_SCOPE_SESSION_KNOWLEDGE, '差旅住宿标准是多少', sharedOptions)
  const approvalAction = buildScopeSwitchAction(ASSISTANT_SCOPE_SESSION_APPROVAL, '帮我查询待我审核的单据', sharedOptions)

  return [
    { ...applicationAction, label: '去申请助手', description: '发起费用申请和事前审批' },
    { ...expenseAction, label: '去报销助手', description: '继续处理报销和票据' },
    { ...knowledgeAction, label: '去知识助手', description: '查看标准和流程规则' },
    { ...approvalAction, label: '去审核助手', description: '查看待审单据和风险' }
  ]
}

function buildUnsupportedBusinessScopeText(rawText, options = {}) {
  const message = ONTOLOGY_BUSINESS_CONTRACT.unsupportedIntentMessage || {}
  const text = String(rawText || '').trim()
  const intro = text
    ? `**小财管家暂时不处理「${text}」这类内容。**`
    : `**${message.title || '此意图系统不支持。'}**`
  const attachmentHint = options.attachmentCount
    ? '您刚刚上传的附件我会先保留，切换到合适场景后可以继续使用。'
    : ''
  return [
    intro,
    '',
    '### 当前可继续的场景',
    `- ${SUPPORTED_BUSINESS_SCOPE_TEXT[0] || '费用申请/事前审批'}`,
    `- ${SUPPORTED_BUSINESS_SCOPE_TEXT[1] || '报销与票据识别'}`,
    `- ${SUPPORTED_BUSINESS_SCOPE_TEXT[3] || '财务制度、报销标准和流程规则问答'}`,
    `- ${SUPPORTED_BUSINESS_SCOPE_TEXT[4] || '预算、应收、应付等财务经营查询'}`,
    '',
    message.body || '这条内容没有识别到当前系统支持的财务业务意图，暂时不能继续处理。',
    attachmentHint,
    '您可以直接点下面的场景继续，或者重新描述您的财务业务需求。',
    '',
    message.retryHint || '请重新描述您的财务业务要求，例如“申请下周去上海出差”“查询我的报销单进度”或“解释差旅住宿标准”。'
  ].filter(Boolean).join('\n')
}

export function buildUnsupportedBusinessScopeConversation(rawText, options = {}) {
  const suggestedActions = buildUnsupportedBusinessScopeSuggestedActions(options)
  return {
    state_json: {
      session_type: ASSISTANT_SCOPE_SESSION_STEWARD
    },
    messages: [
      {
        id: 'unsupported-business-intent',
        role: 'assistant',
        content: buildUnsupportedBusinessScopeText(rawText, options),
        created_at: new Date().toISOString(),
        message_json: {
          assistant_name: '小财管家',
          assistant_variant: 'compact_guidance',
          orchestrator_payload: {
            result: {
              suggested_actions: suggestedActions
            }
          }
        }
      }
    ]
  }
}

function buildUnsupportedBusinessScopeGuard(rawText, options = {}) {
  const suggestedActions = buildUnsupportedBusinessScopeSuggestedActions(options)
  return {
    targetSessionType: '',
    targetLabel: '不支持的意图',
    blocked: true,
    text: buildUnsupportedBusinessScopeText(rawText, options),
    meta: ['意图不支持'],
    suggestedActions,
    actionType: ASSISTANT_SCOPE_ACTION_UNSUPPORTED
  }
}

export function resolveAssistantScopeGuard(rawText, currentSessionType, options = {}) {
  const normalizedCurrent = normalizeSessionType(currentSessionType)
  const targetSessionType = inferAssistantScopeTarget(rawText, options)
  if (!targetSessionType) {
    if (shouldAllowContextualFollowUp(rawText, normalizedCurrent, options)) {
      return null
    }
    return normalizeText(rawText) ? buildUnsupportedBusinessScopeGuard(rawText, options) : null
  }

  if (targetSessionType === normalizedCurrent) {
    return null
  }

  if (shouldAllowCurrentExpensePolicyQuestion(rawText, normalizedCurrent, targetSessionType, options)) {
    return null
  }

  const target = resolveScopeConfig(targetSessionType)

  return {
    targetSessionType,
    targetLabel: target.label,
    text: buildScopeBoundaryText(normalizedCurrent, targetSessionType),
    meta: [`建议切换至${target.label}`],
    suggestedActions: [buildScopeSwitchAction(targetSessionType, rawText, options)]
  }
}
