import {
  canApproveBudgetExpenseApplications,
  isCurrentDirectManagerForRequest,
  isCurrentRequestApplicant,
  isExecutiveUser,
  isFinanceUser,
  isPlatformAdminUser
} from './accessControl.js'
import { isApplicationDocumentNo } from './documentClassification.js'

const APPLICATION_STAGE_ALIASES = new Set([
  'expense_application',
  'application',
  'apply',
  'pre_apply',
  'pre_application',
  'budget_application'
])
const REIMBURSEMENT_STAGE_ALIASES = new Set([
  'reimbursement',
  'expense_reimbursement',
  'claim',
  'expense_claim',
  'expense_report'
])
const SUPPORTED_DOMAINS = new Set(['budget', 'policy', 'invoice', 'trip', 'amount', 'workflow', 'profile'])
const SUPPORTED_ACTIONABILITIES = new Set([
  'fixable_by_submitter',
  'review_decision',
  'budget_governance',
  'finance_check',
  'system_trace'
])
const SUPPORTED_SCOPES = new Set(['submitter', 'leader', 'budget_manager', 'finance', 'admin'])

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

function normalizeKey(value) {
  return normalizeText(value).toLowerCase()
}

export function normalizeRiskBusinessStage(value, fallback = 'reimbursement') {
  const stage = normalizeKey(value)
  if (APPLICATION_STAGE_ALIASES.has(stage)) {
    return 'expense_application'
  }
  if (REIMBURSEMENT_STAGE_ALIASES.has(stage)) {
    return 'reimbursement'
  }
  return fallback
}

export function resolveRiskBusinessStage(flag, fallback = 'reimbursement') {
  if (!flag || typeof flag !== 'object') {
    return resolveRiskTextBusinessStage(flag, fallback)
  }
  const explicitStage = normalizeRiskBusinessStage(
    flag.business_stage || flag.businessStage || flag.control_stage || flag.controlStage,
    ''
  )
  if (explicitStage) {
    return explicitStage
  }
  return resolveRiskTextBusinessStage(cardLikeText(flag), fallback)
}

export function resolveRiskTextBusinessStage(value, fallback = 'reimbursement') {
  const text = normalizeText(value)
  if (/报销|附件|单据|票据|发票|OCR|识别|付款|支付|酒店|住宿票|交通票/.test(text)) {
    return 'reimbursement'
  }
  if (/申请|预算|额度|事前|预估|申请金额|申请事由/.test(text)) {
    return 'expense_application'
  }
  return fallback
}

export function resolveRiskDomain(flag) {
  if (!flag || typeof flag !== 'object') {
    return inferRiskDomainFromText(flag)
  }
  const explicitDomain = normalizeKey(flag.risk_domain || flag.riskDomain || flag.domain)
  if (SUPPORTED_DOMAINS.has(explicitDomain)) {
    return explicitDomain
  }
  const source = normalizeKey(flag.source)
  const eventType = normalizeKey(flag.event_type || flag.eventType)
  if (source === 'budget_control' || eventType.includes('budget')) {
    return 'budget'
  }
  if (source === 'attachment_analysis') {
    return 'invoice'
  }
  if (source === 'manual_return' || source === 'approval_routing') {
    return 'workflow'
  }
  if (source === 'financial_risk_graph') {
    return 'profile'
  }
  return inferRiskDomainFromText(cardLikeText(flag))
}

export function resolveRiskActionability(flag, options = {}) {
  const explicitActionability = normalizeKey(flag?.actionability)
  if (SUPPORTED_ACTIONABILITIES.has(explicitActionability)) {
    return explicitActionability
  }
  const domain = options.riskDomain || resolveRiskDomain(flag)
  const stage = normalizeRiskBusinessStage(options.businessStage, 'reimbursement')
  const source = normalizeKey(flag?.source)
  if (isSystemTraceSource(source)) {
    return 'system_trace'
  }
  if (domain === 'budget') {
    return 'budget_governance'
  }
  if (source === 'manual_return') {
    return 'fixable_by_submitter'
  }
  if (source === 'attachment_analysis') {
    return 'fixable_by_submitter'
  }
  if (['policy', 'invoice', 'trip', 'amount'].includes(domain)) {
    return 'fixable_by_submitter'
  }
  return 'review_decision'
}

export function resolveRiskVisibilityScope(flag, options = {}) {
  const explicitScope = normalizeKey(flag?.visibility_scope || flag?.visibilityScope)
  if (SUPPORTED_SCOPES.has(explicitScope)) {
    return explicitScope
  }
  const domain = options.riskDomain || resolveRiskDomain(flag)
  const actionability = options.actionability || resolveRiskActionability(flag, options)
  const stage = normalizeRiskBusinessStage(options.businessStage, 'reimbursement')
  if (actionability === 'system_trace') {
    return 'admin'
  }
  if (domain === 'budget' || actionability === 'budget_governance') {
    return 'budget_manager'
  }
  if (actionability === 'fixable_by_submitter') {
    return 'submitter'
  }
  return 'finance'
}

export function isApplicationRiskStageRequest(request = {}) {
  const documentType = normalizeText(
    request?.documentTypeCode ||
    request?.document_type_code ||
    request?.documentType ||
    request?.document_type
  )
  const claimNo = normalizeText(request?.claimNo || request?.claim_no || request?.documentNo || request?.id).toUpperCase()
  const typeCode = normalizeKey(request?.typeCode || request?.expense_type)
  return (
    documentType === 'application' ||
    documentType === 'expense_application' ||
    isApplicationDocumentNo(claimNo) ||
    typeCode === 'application' ||
    typeCode.endsWith('_application')
  )
}

export function buildRiskViewerContext(options = {}) {
  const request = options.request || {}
  const currentUser = options.currentUser || null
  const isApplicationDocument = Boolean(
    options.isApplicationDocument ?? isApplicationRiskStageRequest(request)
  )
  const businessStage = normalizeRiskBusinessStage(
    options.businessStage,
    isApplicationDocument ? 'expense_application' : 'reimbursement'
  )
  const isCurrentApplicant = Boolean(
    options.isCurrentApplicant ?? isCurrentRequestApplicant(request, currentUser)
  )
  const isBudgetReviewer = Boolean(
    options.isBudgetReviewer ?? canApproveBudgetExpenseApplications(currentUser, request)
  )
  const isDirectManagerReviewer = Boolean(
    options.isDirectManagerReviewer ?? isCurrentDirectManagerForRequest(request, currentUser)
  )
  const isFinanceReviewer = Boolean(options.isFinanceReviewer ?? isFinanceUser(currentUser))
  const isAdminViewer = Boolean(
    options.isAdminViewer ?? (isPlatformAdminUser(currentUser) || isExecutiveUser(currentUser))
  )
  return {
    request,
    currentUser,
    businessStage,
    isApplicationDocument,
    isCurrentApplicant,
    isBudgetReviewer,
    isDirectManagerReviewer,
    isFinanceReviewer,
    isAdminViewer,
    canViewApprovalRiskAdvice: Boolean(options.canViewApprovalRiskAdvice)
  }
}

export function canViewRiskForContext(flag, options = {}) {
  const context = buildRiskViewerContext(options)
  const stage = resolveRiskBusinessStage(flag, context.businessStage)
  if (stage !== context.businessStage) {
    return false
  }
  const riskDomain = resolveRiskDomain(flag)
  const actionability = resolveRiskActionability(flag, { businessStage: stage, riskDomain })
  const visibilityScope = resolveRiskVisibilityScope(flag, { businessStage: stage, riskDomain, actionability })

  if (context.isAdminViewer) {
    return true
  }
  if (actionability === 'system_trace' || visibilityScope === 'admin') {
    return false
  }
  if (stage === 'expense_application') {
    // 申请单阶段：申请人可见可自行整改的风险（信息完整性/差旅/金额等），
    // 以便申请时知晓风险及原因；预算类仅预算审批人可见；其余（画像/审批流程）仅领导/审批人可见。
    if (context.isCurrentApplicant) {
      return actionability === 'fixable_by_submitter' || visibilityScope === 'submitter'
    }
    if (riskDomain === 'budget' || actionability === 'budget_governance' || visibilityScope === 'budget_manager') {
      return context.isBudgetReviewer
    }
    return context.isDirectManagerReviewer || context.canViewApprovalRiskAdvice || context.isBudgetReviewer
  }

  const isReimbursementSubmitterFixableRisk = (
    (actionability === 'fixable_by_submitter' || visibilityScope === 'submitter') &&
    !['budget', 'profile'].includes(riskDomain)
  )
  if (isReimbursementSubmitterFixableRisk) {
    return true
  }
  if (context.isCurrentApplicant) {
    return actionability === 'fixable_by_submitter' || visibilityScope === 'submitter'
  }
  if (riskDomain === 'budget' || actionability === 'budget_governance' || visibilityScope === 'budget_manager') {
    return context.isBudgetReviewer
  }
  if (context.isFinanceReviewer) {
    return true
  }
  if (context.isDirectManagerReviewer || context.canViewApprovalRiskAdvice) {
    return actionability !== 'finance_check'
  }
  return false
}

export function filterRiskCardsForVisibility(cards = [], options = {}) {
  return (Array.isArray(cards) ? cards : []).filter((card) => canViewRiskForContext(card, options))
}

function inferRiskDomainFromText(value) {
  const text = normalizeText(value)
  if (/预算|余额|占用|超预算|budget/i.test(text)) {
    return 'budget'
  }
  if (/城市|行程|住宿|交通|出差|地点|日期|时间|酒店|trip|travel|city|hotel|transport|period/i.test(text)) {
    return 'trip'
  }
  if (/附件|票据|发票|OCR|识别|单据|invoice|receipt/i.test(text)) {
    return 'invoice'
  }
  if (/金额|超标|阈值|额度|标准|amount|limit|over/i.test(text)) {
    return 'amount'
  }
  if (/历史|画像|异常关系|profile|baseline/i.test(text)) {
    return 'profile'
  }
  if (/审批|退回|流程|付款|routing|approval|return|payment/i.test(text)) {
    return 'workflow'
  }
  return 'policy'
}

function isSystemTraceSource(source) {
  return [
    'application_detail',
    'application_handoff',
    'application_submission',
    'approval',
    'approval_log',
    'approval_routing',
    'budget_approval',
    'expense_claim_approval',
    'expense_claim_finance_approval',
    'finance_approval',
    'manual_approval',
    'payment',
    'sla_reminder',
    'reminder',
    'urge'
  ].includes(source)
}

function cardLikeText(card = {}) {
  if (!card || typeof card !== 'object') {
    return normalizeText(card)
  }
  return [
    card.rule_code,
    card.risk_category,
    card.label,
    card.title,
    card.risk,
    card.message,
    card.summary,
    card.suggestion,
    card.description,
    card.detail
  ].map((item) => normalizeText(item)).join(' ')
}
