import { computed, ref } from 'vue'

import {
  approveExpenseClaim,
  createExpenseClaimActionRequestId,
  deleteExpenseClaim,
  returnExpenseClaim
} from '../../services/reimbursements.js'
import { resolveGeneratedDraftClaimNo } from '../../utils/applicationApproval.js'

export function useTravelRequestDetailApprovalFlow({
  request,
  isApplicationDocument,
  isDraftRequest,
  isArchivedRequest,
  isFinanceApprovalStage,
  isBudgetApprovalStage,
  canDeleteRequest,
  canReturnRequest,
  canApproveRequest,
  approvalRiskConfirmItems,
  canViewApprovalRiskAdvice,
  toast,
  emit
}) {
  const deleteBusy = ref(false)
  const deleteDialogOpen = ref(false)
  const returnBusy = ref(false)
  const returnDialogOpen = ref(false)
  const returnRequestId = ref('')
  const returnExpectedStatus = ref('')
  const returnExpectedStage = ref('')
  const approveBusy = ref(false)
  const approveConfirmDialogOpen = ref(false)
  const approveRequestId = ref('')
  const approveExpectedStatus = ref('')
  const approveExpectedStage = ref('')
  const approvalRiskConfirmed = ref(false)
  const leaderOpinion = ref('')

  const budgetApprovalOpinionRequired = computed(() => (
    isBudgetApprovalStage.value
    && hasBudgetApprovalWarning(request.value)
  ))
  const requiresApprovalOpinion = computed(() => budgetApprovalOpinionRequired.value)
  const approvalRiskConfirmRequired = computed(() =>
    canApproveRequest.value
    && canViewApprovalRiskAdvice.value
    && approvalRiskConfirmItems.value.length > 0
  )
  const approvalOpinionTitle = computed(() => {
    if (isFinanceApprovalStage.value) {
      return '财务意见'
    }
    if (isBudgetApprovalStage.value) {
      return '预算审批意见'
    }
    return '附加意见'
  })
  const approvalOpinionPlaceholder = computed(() => {
    if (isFinanceApprovalStage.value) {
      return '请输入财务终审意见，可补充票据核验、金额一致性或入账关注点。'
    }
    if (budgetApprovalOpinionRequired.value) {
      return '预算已超过警戒值，请写明预算审批意见、通过依据或后续控制要求。'
    }
    if (isBudgetApprovalStage.value) {
      return '可选填预算审批补充说明；未超过预算警戒值时不填写默认为同意。'
    }
    if (isApplicationDocument.value) {
      return '可选填审批补充说明，例如业务必要性、预算合理性或执行要求；不填写默认为同意。'
    }
    return '可选填审批补充说明，例如核实情况、费用合理性或后续财务关注点；不填写默认为同意。'
  })
  const approvalOpinionHint = computed(() => {
    if (isFinanceApprovalStage.value) {
      return '审核通过后将进入待付款。'
    }
    if (isBudgetApprovalStage.value) {
      return budgetApprovalOpinionRequired.value
        ? '预算已超过警戒值，需填写预算审批意见后才能通过。'
        : '未超过预算警戒值时不填写意见将默认同意，确认后按流程继续流转。'
    }
    return isApplicationDocument.value ? '不填写附加意见则默认同意，确认后系统会按预算与风险结果决定下一步：无风险且预算充足将直接完成申请，否则进入预算管理者审批。' : '不填写附加意见则默认同意，审批通过后将流转至财务审批。'
  })
  const approvalConfirmBadge = computed(() => {
    if (isFinanceApprovalStage.value) {
      return '财务终审'
    }
    return isBudgetApprovalStage.value ? '预算审核' : '领导审批'
  })
  const approvalConfirmDescription = computed(() => {
    if (isFinanceApprovalStage.value) {
      return '确认后该报销单会完成财务终审并进入待付款，请确认票据、金额与财务意见无误。'
    }
    if (isApplicationDocument.value) {
      return isBudgetApprovalStage.value
        ? '确认后该申请单会完成预算审核，归档申请单，并自动进入申请人的报销草稿中。'
        : '确认后该申请单会完成直属领导审批，系统将按预算余额、当前风险和历史风险判断是否需要预算管理者复核；无风险且预算充足会直接完成申请并生成报销草稿。'
    }
    return '确认后该报销单会从直属领导审批流转到财务审批，请确认申请信息与领导意见无误。'
  })
  const approveActionLabel = computed(() => (isApplicationDocument.value ? '确认审核' : '审批通过'))
  const approveBusyLabel = computed(() => (isApplicationDocument.value ? '确认中' : '通过中'))
  const approveConfirmTitle = computed(() => (
    isApplicationDocument.value ? `确认审核 ${request.value.id} 吗？` : `确认通过 ${request.value.id} 吗？`
  ))
  const approveConfirmText = computed(() => (isApplicationDocument.value ? '确认审核' : '确认通过'))
  const approveBusyText = computed(() => (isApplicationDocument.value ? '确认中...' : '通过中...'))
  const returnDialogDescription = computed(() => (
    isApplicationDocument.value
      ? '退回后该申请单会回到待提交状态，申请人需要调整后重新提交。'
      : '退回后该单据会回到待提交状态，申请人需要调整后重新提交并再次经过 AI 预审。'
  ))
  const approvalSuccessToast = computed(() => {
    if (isFinanceApprovalStage.value) {
      return `${request.value.id} 已完成财务终审，进入待付款。`
    }
    return isApplicationDocument.value
      ? isBudgetApprovalStage.value
        ? `${request.value.id} 已完成预算审核，正在生成报销草稿。`
        : `${request.value.id} 已确认审核，系统已按预算与风险结果更新流程。`
      : `${request.value.id} 已审批通过，流转至财务审批。`
  })
  const deleteActionLabel = computed(() => {
    if (isApplicationDocument.value) {
      return '删除申请'
    }
    return isDraftRequest.value ? '删除草稿' : '删除单据'
  })
  const deleteDialogTarget = computed(() => request.value.documentNo || request.value.id || '当前单据')
  const deleteDialogTitle = computed(() => `确认${deleteActionLabel.value}吗？`)
  const deleteDialogDescription = computed(() =>
    isDraftRequest.value
      ? `${deleteDialogTarget.value} 删除后，该草稿及其当前费用明细将不可恢复。`
      : `${deleteDialogTarget.value} 删除后，该${isApplicationDocument.value ? '申请单' : '报销单'}及费用明细将不可恢复。`
  )

  async function handleDeleteRequest() {
    if (!request.value.claimId) {
      toast('当前单据缺少 claimId，暂时无法删除。')
      return
    }

    if (!canDeleteRequest.value) {
      toast(
        isArchivedRequest.value
          ? '已归档单据不能删除，只有高级管理员可以执行删除。'
          : isApplicationDocument.value
            ? '当前申请单已进入审批流程，只有草稿、待补充或退回待提交阶段的申请人本人或系统管理员可以删除。'
            : '当前单据已进入流程，只有草稿、待补充或退回待提交阶段的申请人本人或系统管理员可以删除。'
      )
      return
    }

    deleteDialogOpen.value = true
  }

  function closeDeleteDialog() {
    if (deleteBusy.value) {
      return
    }

    deleteDialogOpen.value = false
  }

  async function confirmDeleteRequest() {
    if (!request.value.claimId) {
      toast('当前单据缺少 claimId，暂时无法删除。')
      return
    }

    deleteBusy.value = true
    try {
      const payload = await deleteExpenseClaim(request.value.claimId)
      deleteDialogOpen.value = false
      toast(payload?.message || `${request.value.id} ${isApplicationDocument.value ? '申请单' : '报销单'}已删除。`)
      emit('request-deleted', {
        claimId: request.value.claimId,
        claimNo: request.value.claimNo || request.value.documentNo || request.value.id,
        documentNo: request.value.documentNo || request.value.id
      })
    } catch (error) {
      toast(error?.message || '删除单据失败，请稍后重试。')
    } finally {
      deleteBusy.value = false
    }
  }

  function handleReturnRequest() {
    if (!request.value.claimId) {
      toast('当前单据缺少 claimId，暂时无法退回。')
      return
    }

    if (!canReturnRequest.value) {
      toast('当前状态不支持退回。')
      return
    }

    returnRequestId.value = createExpenseClaimActionRequestId('return', request.value.claimId)
    returnExpectedStatus.value = String(request.value.status || '').trim()
    returnExpectedStage.value = String(request.value.node || request.value.approvalStage || '').trim()
    returnDialogOpen.value = true
  }

  function closeReturnDialog() {
    if (returnBusy.value) {
      return
    }

    returnDialogOpen.value = false
    returnRequestId.value = ''
    returnExpectedStatus.value = ''
    returnExpectedStage.value = ''
  }

  async function confirmReturnRequest(payload) {
    if (!request.value.claimId) {
      toast('当前单据缺少 claimId，暂时无法退回。')
      return
    }

    returnBusy.value = true
    try {
      await returnExpenseClaim(request.value.claimId, {
        ...payload,
        request_id: returnRequestId.value,
        expected_status: returnExpectedStatus.value,
        expected_approval_stage: returnExpectedStage.value
      })
      returnDialogOpen.value = false
      returnRequestId.value = ''
      returnExpectedStatus.value = ''
      returnExpectedStage.value = ''
      toast(`${request.value.id} 已退回待提交。`)
      emit('request-updated', { claimId: request.value.claimId })
    } catch (error) {
      toast(error?.message || '退回单据失败，请稍后重试。')
    } finally {
      returnBusy.value = false
    }
  }

  function handleApproveRequest() {
    if (!request.value.claimId) {
      toast('当前单据缺少 claimId，暂时无法审批通过。')
      return
    }

    if (!canApproveRequest.value) {
      toast('当前节点暂不支持审批通过。')
      return
    }

    approveRequestId.value = createExpenseClaimActionRequestId('approve', request.value.claimId)
    approveExpectedStatus.value = String(request.value.status || '').trim()
    approveExpectedStage.value = String(request.value.node || request.value.approvalStage || '').trim()
    approvalRiskConfirmed.value = !approvalRiskConfirmRequired.value
    approveConfirmDialogOpen.value = true
  }

  function closeApproveConfirmDialog() {
    if (approveBusy.value) {
      return
    }

    approveConfirmDialogOpen.value = false
    approveRequestId.value = ''
    approveExpectedStatus.value = ''
    approveExpectedStage.value = ''
  }

  function resolveApproveErrorMessage(error) {
    const message = String(error?.message || '').trim()
    if (message.includes('未找到同部门 P8 预算审批人')) {
      return '当前部门未配置 P8 预算审批人，请联系管理员配置后再审批。'
    }
    return message || '审批通过失败，请稍后重试。'
  }

  async function confirmApproveRequest() {
    if (!request.value.claimId) {
      toast('当前单据缺少 claimId，暂时无法审批通过。')
      approveConfirmDialogOpen.value = false
      return
    }

    if (!canApproveRequest.value) {
      toast('当前节点暂不支持审批通过。')
      approveConfirmDialogOpen.value = false
      return
    }

    if (approvalRiskConfirmRequired.value && !approvalRiskConfirmed.value) {
      toast('请先确认已核对风险说明和佐证材料，再继续审批。')
      return
    }

    if (requiresApprovalOpinion.value && !leaderOpinion.value.trim()) {
      toast('预算已超过警戒值，请填写预算审批意见后再通过。')
      return
    }

    approveBusy.value = true
    try {
      const responsePayload = await approveExpenseClaim(request.value.claimId, {
        opinion: leaderOpinion.value.trim() || '同意',
        request_id: approveRequestId.value,
        expected_status: approveExpectedStatus.value,
        expected_approval_stage: approveExpectedStage.value
      })
      const generatedDraftClaimNo = resolveGeneratedDraftClaimNo(responsePayload)
      approveConfirmDialogOpen.value = false
      approveRequestId.value = ''
      approveExpectedStatus.value = ''
      approveExpectedStage.value = ''
      approvalRiskConfirmed.value = false
      leaderOpinion.value = ''
      toast(
        isApplicationDocument.value && generatedDraftClaimNo
          ? `${request.value.id} 已确认审核，报销草稿 ${generatedDraftClaimNo} 已生成。`
          : approvalSuccessToast.value
      )
      emit('request-updated', {
        claimId: request.value.claimId,
        claim: responsePayload
      })
      emit('backToRequests')
    } catch (error) {
      toast(resolveApproveErrorMessage(error))
    } finally {
      approveBusy.value = false
    }
  }

  return {
    approveActionLabel,
    approveBusy,
    approveBusyLabel,
    approveBusyText,
    approveConfirmDialogOpen,
    approveConfirmText,
    approveConfirmTitle,
    approvalConfirmBadge,
    approvalConfirmDescription,
    approvalOpinionHint,
    approvalOpinionPlaceholder,
    approvalOpinionTitle,
    approvalRiskConfirmed,
    approvalRiskConfirmRequired,
    closeApproveConfirmDialog,
    closeDeleteDialog,
    closeReturnDialog,
    confirmApproveRequest,
    confirmDeleteRequest,
    confirmReturnRequest,
    deleteActionLabel,
    deleteBusy,
    deleteDialogDescription,
    deleteDialogOpen,
    deleteDialogTitle,
    handleApproveRequest,
    handleDeleteRequest,
    handleReturnRequest,
    leaderOpinion,
    requiresApprovalOpinion,
    returnBusy,
    returnDialogDescription,
    returnDialogOpen
  }
}

function hasBudgetApprovalWarning(request = {}) {
  const flags = Array.isArray(request?.riskFlags)
    ? request.riskFlags
    : Array.isArray(request?.risk_flags_json)
      ? request.risk_flags_json
      : []

  return flags.some((flag) => {
    if (!flag || typeof flag !== 'object') {
      return false
    }

    const routeDecision = flag.route_decision || flag.routeDecision || {}
    const directBudgetResult = flag.budget_result || flag.budgetResult
    const routeBudgetResult = routeDecision?.budget_result || routeDecision?.budgetResult
    const budgetResult = routeBudgetResult || directBudgetResult
    if (!budgetResult || typeof budgetResult !== 'object') {
      return false
    }

    return budgetResultExceedsWarning(budgetResult)
  })
}

function budgetResultExceedsWarning(budgetResult = {}) {
  const metrics = budgetResult.metrics && typeof budgetResult.metrics === 'object' ? budgetResult.metrics : {}
  const context = budgetResult.budget_context && typeof budgetResult.budget_context === 'object'
    ? budgetResult.budget_context
    : budgetResult.budgetContext && typeof budgetResult.budgetContext === 'object'
      ? budgetResult.budgetContext
      : {}
  const overBudgetAmount = parseBudgetNumber(metrics.over_budget_amount ?? metrics.overBudgetAmount)
  if (overBudgetAmount > 0) {
    return true
  }

  const afterUsageRate = parseBudgetNumber(metrics.after_usage_rate ?? metrics.afterUsageRate)
  const claimAmountRatio = parseBudgetNumber(metrics.claim_amount_ratio ?? metrics.claimAmountRatio)
  const warningThreshold = parseBudgetNumber(context.warning_threshold ?? context.warningThreshold, 80)
  return Math.max(afterUsageRate, claimAmountRatio) >= warningThreshold
}

function parseBudgetNumber(value, fallback = 0) {
  const number = Number(value)
  return Number.isFinite(number) ? number : fallback
}
