import { computed, onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'

import { fetchOrderChat } from '@/features/chats/api/chats'
import { cancelOrderDispute, createDispute } from '@/features/disputes/api/disputes'
import { uploadFile } from '@/shared/api/files'
import { readError } from '@/shared/utils/error'
import {
  acceptCheckout,
  cancelOrder,
  confirmCheckout,
  confirmReceive,
  counterCheckout,
  fetchHandoffRecords,
  fetchOrder,
  startOrderPayment,
  submitCheckout,
  submitHandoff,
  type HandoffRecord,
  type Order,
  type PaymentOrder,
  type PaymentPayWay,
} from '@/features/orders/api/orders'
import {
  hydrateCounterFormFromCheckout,
  linesToList,
  orderEstimatedEndAt as readOrderEstimatedEndAt,
  orderRentAmount,
  ownerActualIncome,
  useOrderCheckoutSnapshot,
} from '@/features/orders/composables/useOrderSnapshot'
import { useSessionStore } from '@/stores/session'
import { formatListingNo } from '@/shared/utils/listingDisplay'

/**
 * 订单详情交互 Composable
 *
 * 承载订单详情双视图（PC / Mobile）共享的业务逻辑：状态、计算属性、handler。
 * UI 反馈（ElMessage / showToast）与二次确认（ElMessageBox / showDialog）通过 options 注入，
 * 文案与业务流程（API 调用顺序、参数构造、表单 reset、autoPay 触发）归本 composable。
 *
 * 设计参考：{@link ./usePublishForm.ts}（PC / Mobile 共用 composable 范式）。
 */
export interface UseOrderActionsOptions {
  /** 成功提示，注入端决定 UI 形态（ElMessage.success / showToast）。 */
  notifySuccess: (message: string) => void
  /** 错误提示，注入端决定 UI 形态。 */
  notifyError: (message: string) => void
  /** 警告提示，用于表单校验未通过等非致命场景。 */
  notifyWarning: (message: string) => void
  /** 二次确认。返回 true 表示用户确认继续，false 表示取消。PC 注入直接 resolve(true)，Mobile 注入 showDialog。 */
  confirm: (opts: { title: string; message: string }) => Promise<boolean>
  /** 需要走二次确认的 handler 名集合。Mobile 传 ['cancel','confirmCheckout','acceptCheckout','cancelDispute']，PC 传 []。 */
  actionsNeedingConfirm: readonly string[]
  /** 支付前选择支付方式。返回 null 表示用户取消支付。 */
  selectPayWay: () => Promise<PaymentPayWay | null>
  /** 订单列表跳转路径，PC '/orders' / Mobile '/m/orders'。 */
  ordersPath: string
  /** 订单群聊路由前缀，PC '/messages/' / Mobile '/m/chats/'。openOrderChat 内部拼接 `${prefix}${chat.id}`。 */
  chatPathPrefix: string
  /**
   * 打开收银台 UI（二维码弹窗 / App 浏览器跳转）。由调用方注入。
   * 仅在 payment 未支付时被调用；payment 已支付的情况由 composable 自行提示并 loadOrder。
   * onPaid：支付完成（轮询发现 paid）时的回调，通常传入 loadOrder。
   */
  startCashier: (payment: PaymentOrder, onPaid: () => Promise<void>) => void | Promise<void>
  /** 修改结账提交成功后触发（如关闭弹窗）。可选。 */
  onCounterCheckoutSuccess?: () => void
  /** 拒绝修正提交成功后触发（如关闭弹窗）。可选。 */
  onRejectCheckoutSuccess?: () => void
  /** 提交申诉成功后触发（如关闭弹窗）。可选。 */
  onCreateDisputeSuccess?: () => void
}

/** handler 名常量，供 actionsNeedingConfirm 校验。 */
export const CONFIRMABLE_ACTIONS = [
  'cancel',
  'confirmCheckout',
  'acceptCheckout',
  'cancelDispute',
] as const

export interface CheckoutFormState {
  content: string
  consumableAmountYuan: number
  coin_consumed_m: number
  otherAmountYuan: number
  evidenceText: string
}

export interface CounterFormState {
  consumableAmountYuan: number
  coin_consumed_m: number
  otherAmountYuan: number
  depositDeductAmountYuan: number
  reason: string
  evidenceText: string
}

function createCheckoutForm(): CheckoutFormState {
  return {
    content: '',
    consumableAmountYuan: 0,
    coin_consumed_m: 0,
    otherAmountYuan: 0,
    evidenceText: '',
  }
}

function createCounterForm(): CounterFormState {
  return {
    consumableAmountYuan: 0,
    coin_consumed_m: 0,
    otherAmountYuan: 0,
    depositDeductAmountYuan: 0,
    reason: '',
    evidenceText: '',
  }
}

export function useOrderActions(options: UseOrderActionsOptions) {
  const route = useRoute()
  const router = useRouter()
  const session = useSessionStore()

  // Loading states
  const loading = ref(false)
  const cancelling = ref(false)
  const startingPayment = ref(false)
  const handoffing = ref(false)
  const confirming = ref(false)
  const returning = ref(false)
  const completing = ref(false)
  const countering = ref(false)
  const acceptingCheckout = ref(false)
  const rejectingCheckout = ref(false)
  const disputing = ref(false)
  const cancellingDispute = ref(false)
  const uploadingEvidence = ref(false)
  const openingChat = ref(false)

  // Data
  const order = ref<Order | null>(null)
  const handoffRecords = ref<HandoffRecord[]>([])
  const handoffContent = ref('')

  // Forms
  const checkoutForm = ref<CheckoutFormState>(createCheckoutForm())
  const resourceUsage = ref<Record<string, number>>({})
  const counterForm = ref<CounterFormState>(createCounterForm())
  const rejectReason = ref('')
  const disputeType = ref('cannot_login')
  const disputeDescription = ref('')
  const disputeEvidenceText = ref('')

  // 结账快照能力（资源金额、内容摘要、资源使用量规范化）
  const {
    checkoutResources,
    resourceChargeAmount,
    snapshotHafCoinM,
    remainingHafCoinM,
    hydrateResourceUsage,
    resourceLineAmount,
    checkoutContentWithSummary,
  } = useOrderCheckoutSnapshot({ order, checkoutForm, resourceUsage })

  // Computed
  const isOwner = computed(() => order.value?.owner_id === session.userId)
  const isRenter = computed(() => order.value?.renter_id === session.userId)
  const listingCode = computed(() =>
    order.value ? formatListingNo(order.value.listing_no, order.value.listing_id) : '-'
  )
  const orderAmountLabel = computed(() => (isOwner.value ? '预计租金' : '支付租金'))
  const orderRentDisplayAmount = computed(() =>
    order.value ? orderRentAmount(order.value, session.userId) : 0
  )
  const ownerIncomeDisplayAmount = computed(() =>
    order.value ? ownerActualIncome(order.value, session.userId) : null
  )
  const ownerIncomeLabel = computed(() =>
    order.value?.status === 'completed' ? '实际到手' : '结账预计到手'
  )
  const canOpenDispute = computed(() => {
    if (!order.value || (!isOwner.value && !isRenter.value)) return false
    return ![
      'completed',
      'cancelled',
      'closed',
      'disputing',
      'checkout_disputing',
      'abnormal',
    ].includes(order.value.status)
  })
  const canCancelDispute = computed(() => {
    return (
      !!order.value &&
      (isOwner.value || isRenter.value) &&
      ['disputing', 'checkout_disputing'].includes(order.value.status) &&
      order.value.active_dispute?.initiator_id === session.userId
    )
  })
  const isCheckoutDisputeStage = computed(() => {
    return (
      !!order.value &&
      ['pending_checkout_confirm', 'pending_checkout_accept'].includes(order.value.status)
    )
  })

  let autoPayHandled = false

  function needsConfirm(action: string): boolean {
    return options.actionsNeedingConfirm.includes(action)
  }

  function hydrateCounterForm() {
    if (!order.value?.checkout) return
    counterForm.value = hydrateCounterFormFromCheckout(order.value.checkout)
  }

  async function loadOrder() {
    loading.value = true
    try {
      order.value = await fetchOrder(String(route.params.id))
      handoffRecords.value = await fetchHandoffRecords(String(route.params.id))
      hydrateResourceUsage()
      hydrateCounterForm()
      if (
        !autoPayHandled &&
        route.query.pay === '1' &&
        order.value?.status === 'pending_payment' &&
        order.value?.renter_id === session.userId
      ) {
        autoPayHandled = true
        void router.replace({ path: route.path })
        void handlePay()
      }
    } catch (error) {
      options.notifyError(readError(error, '加载订单失败'))
    } finally {
      loading.value = false
    }
  }

  async function handleCancel() {
    if (!order.value) return
    if (needsConfirm('cancel')) {
      const ok = await options.confirm({
        title: '取消订单',
        message: '确定取消订单并释放账号吗？',
      })
      if (!ok) return
    }
    cancelling.value = true
    try {
      await cancelOrder(order.value.id)
      options.notifySuccess('订单已取消，账号已释放')
      await router.push(options.ordersPath)
    } catch (error) {
      options.notifyError(readError(error, '取消失败'))
    } finally {
      cancelling.value = false
    }
  }

  async function handlePay() {
    if (!order.value) return
    const payWay = await options.selectPayWay()
    if (!payWay) return
    startingPayment.value = true
    try {
      const payment = await startOrderPayment(order.value.id, { pay_way: payWay })
      if (payment.paid) {
        options.notifySuccess('支付成功，等待号主交接')
        await loadOrder()
        return
      }
      await options.startCashier(payment, loadOrder)
    } catch (error) {
      options.notifyError(readError(error, '支付失败'))
    } finally {
      startingPayment.value = false
    }
  }

  async function handleSubmitHandoff() {
    if (!order.value) return
    if (!handoffContent.value.trim()) {
      options.notifyWarning('请填写交接说明')
      return
    }
    handoffing.value = true
    try {
      await submitHandoff(order.value.id, handoffContent.value)
      handoffContent.value = ''
      options.notifySuccess('交接说明已提交')
      await loadOrder()
    } catch (error) {
      options.notifyError(readError(error, '提交交接失败'))
    } finally {
      handoffing.value = false
    }
  }

  async function handleConfirmReceive() {
    if (!order.value) return
    confirming.value = true
    try {
      await confirmReceive(order.value.id)
      options.notifySuccess('已确认收号，订单进入使用中')
      await loadOrder()
    } catch (error) {
      options.notifyError(readError(error, '确认收号失败'))
    } finally {
      confirming.value = false
    }
  }

  async function handleSubmitCheckout() {
    if (!order.value) return
    returning.value = true
    try {
      const consumableAmount = resourceChargeAmount.value
      checkoutForm.value.consumableAmountYuan = consumableAmount
      await submitCheckout(order.value.id, {
        content: checkoutContentWithSummary(),
        consumableAmountYuan: consumableAmount,
        coin_consumed_m: checkoutForm.value.coin_consumed_m,
        otherAmountYuan: checkoutForm.value.otherAmountYuan,
        evidence_urls: linesToList(checkoutForm.value.evidenceText),
      })
      checkoutForm.value = createCheckoutForm()
      resourceUsage.value = {}
      options.notifySuccess('结账已发起，等待号主确认')
      await loadOrder()
    } catch (error) {
      options.notifyError(readError(error, '发起结账失败'))
    } finally {
      returning.value = false
    }
  }

  async function handleConfirmCheckout() {
    if (!order.value) return
    if (needsConfirm('confirmCheckout')) {
      const ok = await options.confirm({
        title: '确认结账',
        message: '确认账号状态和扣款金额无误吗？确认后订单将完成。',
      })
      if (!ok) return
    }
    completing.value = true
    try {
      await confirmCheckout(order.value.id)
      options.notifySuccess('结账已确认，订单完成')
      await loadOrder()
    } catch (error) {
      options.notifyError(readError(error, '确认结账失败'))
    } finally {
      completing.value = false
    }
  }

  async function handleCounterCheckout() {
    if (!order.value) return
    countering.value = true
    try {
      const reasonText = counterForm.value.reason.trim()
      await counterCheckout(order.value.id, {
        content: reasonText,
        consumableAmountYuan: counterForm.value.consumableAmountYuan,
        coin_consumed_m: counterForm.value.coin_consumed_m,
        otherAmountYuan: counterForm.value.otherAmountYuan,
        depositDeductAmountYuan: counterForm.value.depositDeductAmountYuan,
        reason: reasonText,
        evidence_urls: linesToList(counterForm.value.evidenceText),
      })
      options.notifySuccess('结账修正已提交，等待租客确认')
      await loadOrder()
      options.onCounterCheckoutSuccess?.()
    } catch (error) {
      options.notifyError(readError(error, '修改结账失败'))
    } finally {
      countering.value = false
    }
  }

  async function handleAcceptCheckout() {
    if (!order.value) return
    if (needsConfirm('acceptCheckout')) {
      const ok = await options.confirm({
        title: '同意修正',
        message: '确定同意号主的结账修正提案吗？同意后订单将完成结算。',
      })
      if (!ok) return
    }
    acceptingCheckout.value = true
    try {
      await acceptCheckout(order.value.id)
      options.notifySuccess('已确认修正结账，订单完成')
      await loadOrder()
    } catch (error) {
      options.notifyError(readError(error, '确认修正失败'))
    } finally {
      acceptingCheckout.value = false
    }
  }

  async function handleRejectCheckout() {
    if (!order.value) return
    if (!rejectReason.value.trim()) {
      options.notifyWarning('请填写不同意原因')
      return
    }
    rejectingCheckout.value = true
    try {
      await createDispute(order.value.id, {
        type: 'checkout_dispute',
        description: rejectReason.value,
        evidence_urls: [],
      })
      rejectReason.value = ''
      options.notifySuccess('已拒绝修正并提交争议')
      await loadOrder()
      options.onRejectCheckoutSuccess?.()
    } catch (error) {
      options.notifyError(readError(error, '提交拒绝失败'))
    } finally {
      rejectingCheckout.value = false
    }
  }

  async function handleCreateDispute() {
    if (!order.value) return
    if (!disputeDescription.value.trim()) {
      options.notifyWarning('请填写争议经过说明')
      return
    }
    disputing.value = true
    try {
      const evidence_urls = linesToList(disputeEvidenceText.value)
      await createDispute(order.value.id, {
        type: isCheckoutDisputeStage.value ? 'checkout_dispute' : disputeType.value,
        description: disputeDescription.value,
        evidence_urls,
      })
      disputeDescription.value = ''
      disputeEvidenceText.value = ''
      options.notifySuccess('申诉已提交，订单进入仲裁')
      await loadOrder()
      options.onCreateDisputeSuccess?.()
    } catch (error) {
      options.notifyError(readError(error, '提交申诉失败'))
    } finally {
      disputing.value = false
    }
  }

  async function handleCancelDispute() {
    if (!order.value) return
    if (needsConfirm('cancelDispute')) {
      const ok = await options.confirm({
        title: order.value.status === 'checkout_disputing' ? '取消结账争议' : '取消申诉',
        message: '取消后订单将恢复到发起申诉前的流程，确定继续吗？',
      })
      if (!ok) return
    }
    cancellingDispute.value = true
    try {
      await cancelOrderDispute(order.value.id)
      options.notifySuccess('申诉已取消，订单已恢复')
      await loadOrder()
    } catch (error) {
      options.notifyError(readError(error, '取消申诉失败'))
    } finally {
      cancellingDispute.value = false
    }
  }

  async function handleEvidenceUpload(event: Event) {
    const input = event.target as HTMLInputElement
    const file = input.files?.[0]
    input.value = ''
    if (!file) return
    uploadingEvidence.value = true
    try {
      const uploaded = await uploadFile(file, 'dispute')
      disputeEvidenceText.value = [disputeEvidenceText.value, uploaded.url]
        .filter(Boolean)
        .join('\n')
      options.notifySuccess('证据文件已上传')
    } catch (error) {
      options.notifyError(readError(error, '上传失败'))
    } finally {
      uploadingEvidence.value = false
    }
  }

  /**
   * 反驳结账证据上传（Mobile 反驳弹窗独有：把 URL 写入 counterForm.evidenceText）。
   * PC 不使用，保留以供 Mobile 视图调用。
   */
  async function handleCounterEvidenceUpload(event: Event) {
    const input = event.target as HTMLInputElement
    const file = input.files?.[0]
    input.value = ''
    if (!file) return
    uploadingEvidence.value = true
    try {
      const uploaded = await uploadFile(file, 'dispute')
      counterForm.value.evidenceText = [counterForm.value.evidenceText, uploaded.url]
        .filter(Boolean)
        .join('\n')
      options.notifySuccess('证据文件已上传')
    } catch (error) {
      options.notifyError(readError(error, '上传失败'))
    } finally {
      uploadingEvidence.value = false
    }
  }

  async function openOrderChat() {
    if (!order.value || openingChat.value) return
    openingChat.value = true
    try {
      const chat = await fetchOrderChat(order.value.id)
      await router.push(`${options.chatPathPrefix}${chat.id}`)
    } catch {
      options.notifyError('订单群聊暂不可用')
    } finally {
      openingChat.value = false
    }
  }

  function orderEstimatedEndAt() {
    return readOrderEstimatedEndAt(order.value)
  }

  function orderRentedAt() {
    return order.value?.rented_at
  }

  onMounted(loadOrder)

  return {
    // Loading states
    loading,
    cancelling,
    startingPayment,
    handoffing,
    confirming,
    returning,
    completing,
    countering,
    acceptingCheckout,
    rejectingCheckout,
    disputing,
    cancellingDispute,
    uploadingEvidence,
    openingChat,

    // Data
    order,
    handoffRecords,
    handoffContent,

    // Forms
    checkoutForm,
    resourceUsage,
    counterForm,
    rejectReason,
    disputeType,
    disputeDescription,
    disputeEvidenceText,

    // Checkout snapshot
    checkoutResources,
    resourceChargeAmount,
    snapshotHafCoinM,
    remainingHafCoinM,
    hydrateResourceUsage,
    resourceLineAmount,
    checkoutContentWithSummary,

    // Computed
    isOwner,
    isRenter,
    listingCode,
    orderAmountLabel,
    orderRentDisplayAmount,
    ownerIncomeDisplayAmount,
    ownerIncomeLabel,
    canOpenDispute,
    canCancelDispute,
    isCheckoutDisputeStage,

    // Methods
    loadOrder,
    handleCancel,
    handlePay,
    handleSubmitHandoff,
    handleConfirmReceive,
    handleSubmitCheckout,
    handleConfirmCheckout,
    handleCounterCheckout,
    handleAcceptCheckout,
    handleRejectCheckout,
    handleCreateDispute,
    handleCancelDispute,
    handleEvidenceUpload,
    handleCounterEvidenceUpload,
    openOrderChat,
    orderEstimatedEndAt,
    orderRentedAt,
    hydrateCounterForm,
  }
}
