<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { showToast, showDialog } from "vant";

import { fetchOrderChat } from "@/features/chats/api/chats";
import { createDispute } from "@/features/disputes/api/disputes";
import { uploadFile } from "@/shared/api/files";
import {
  acceptCheckout,
  cancelOrder,
  confirmCheckout,
  confirmReceive,
  counterCheckout,
  fetchHandoffRecords,
  fetchOrder,
  startOrderPayment,
  submitCheckout,
  submitHandoff,
  type HandoffRecord,
  type Order,
  type PaymentOrder,
} from "@/features/orders/api/orders";
import { useSessionStore } from "@/stores/session";
import { handoffStatusLabel, orderStatusLabel } from "@/utils/statusLabels";
import { formatDateTime } from "@/utils/time";

const route = useRoute();
const router = useRouter();
const session = useSessionStore();
const loading = ref(false);
const cancelling = ref(false);
const paying = 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 uploadingEvidence = ref(false);
const openingChat = ref(false);
const order = ref<Order | null>(null);
const handoffRecords = ref<HandoffRecord[]>([]);
const handoffContent = ref("");
const checkoutForm = ref({
  content: "",
  consumable_amount: 0,
  coin_consumed_m: 0,
  other_amount: 0,
  evidenceText: "",
});
const resourceUsage = ref<Record<string, number>>({});
const counterForm = ref({
  consumable_amount: 0,
  coin_consumed_m: 0,
  other_amount: 0,
  deposit_deduct_amount: 0,
  reason: "",
  evidenceText: "",
});
const rejectReason = ref("");
const disputeType = ref("cannot_login");
const disputeDescription = ref("");
const disputeEvidenceText = ref("");

// Show state controls
const activeNames = ref<string[]>([]);
const showDisputePopup = ref(false);
const showCounterPopup = ref(false);
const showRejectPopup = ref(false);

const isOwner = computed(() => order.value?.owner_id === session.userId);
const isRenter = computed(() => order.value?.renter_id === session.userId);
const orderAmountLabel = computed(() => (isOwner.value ? "预计租金" : "支付租金"));
const orderRentDisplayAmount = computed(() => (order.value ? orderRentAmount(order.value) : 0));
const ownerIncomeDisplayAmount = computed(() => (order.value ? ownerActualIncome(order.value) : 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 isCheckoutDisputeStage = computed(() => {
  return !!order.value && ["pending_checkout_confirm", "pending_checkout_accept"].includes(order.value.status);
});
const checkoutResources = computed(() => {
  const resources = readSnapshotResources();
  return resources.filter((item) => item.quantity > 0);
});
const resourceChargeAmount = computed(() => {
  return roundMoney(
    checkoutResources.value.reduce((sum, item) => {
      if (!isChargedResource(item)) return sum;
      const used = readResourceUsage(item.key);
      return sum + used * item.unitPrice;
    }, 0)
  );
});
const snapshotHafCoinM = computed(() => {
  const snapshot = readSnapshot();
  return roundQuantity(readNumber(snapshot?.haf_coin_amount) / 1000000);
});
const remainingHafCoinM = computed(() => {
  return roundQuantity(Math.max(snapshotHafCoinM.value - Number(checkoutForm.value.coin_consumed_m || 0), 0));
});

onMounted(loadOrder);

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();
  } catch {
    showToast({ message: "加载订单失败", icon: "cross" });
  } finally {
    loading.value = false;
  }
}

async function handleCancel() {
  if (!order.value) return;
  showDialog({
    title: "取消订单",
    message: "确定取消订单并释放账号吗？",
    showCancelButton: true,
  }).then(async () => {
    cancelling.value = true;
    try {
      await cancelOrder(order.value!.id);
      showToast({ message: "订单已取消，账号已释放", icon: "passed" });
      await router.push("/m/orders");
    } catch (error) {
      showToast({ message: readError(error, "取消失败"), icon: "cross" });
    } finally {
      cancelling.value = false;
    }
  });
}

async function handlePay() {
  if (!order.value) return;
  paying.value = true;
  try {
    const payment = await startOrderPayment(order.value.id);
    if (payment.paid) {
      showToast({ message: "支付成功，等待号主交接", icon: "passed" });
      await loadOrder();
    } else {
      openPaymentCashier(payment);
    }
  } catch (error) {
    showToast({ message: readError(error, "支付失败"), icon: "cross" });
  } finally {
    paying.value = false;
  }
}

function openPaymentCashier(payment: PaymentOrder) {
  const payURL = payment.jspay_url || payment.td_code || payment.jspay_info || "";
  if (payURL && /^https?:\/\//i.test(payURL)) {
    window.location.href = payURL;
    return;
  }
  showDialog({
    title: "订单支付",
    message: payURL || "支付单已创建，请稍后刷新订单状态。",
    confirmButtonText: "知道了",
  });
}

async function handleSubmitHandoff() {
  if (!order.value) return;
  if (!handoffContent.value.trim()) {
    showToast({ message: "请填写交接说明", icon: "warning-o" });
    return;
  }
  handoffing.value = true;
  try {
    await submitHandoff(order.value.id, handoffContent.value);
    handoffContent.value = "";
    showToast({ message: "交接说明已提交", icon: "passed" });
    await loadOrder();
  } catch (error) {
    showToast({ message: readError(error, "提交交接失败"), icon: "cross" });
  } finally {
    handoffing.value = false;
  }
}

async function handleConfirmReceive() {
  if (!order.value) return;
  confirming.value = true;
  try {
    await confirmReceive(order.value.id);
    showToast({ message: "已确认收号，订单进入使用中", icon: "passed" });
    await loadOrder();
  } catch (error) {
    showToast({ message: readError(error, "确认收号失败"), icon: "cross" });
  } finally {
    confirming.value = false;
  }
}

async function handleSubmitCheckout() {
  if (!order.value) return;
  returning.value = true;
  try {
    const consumableAmount = resourceChargeAmount.value;
    checkoutForm.value.consumable_amount = consumableAmount;
    await submitCheckout(order.value.id, {
      content: checkoutContentWithSummary(),
      consumable_amount: consumableAmount,
      coin_consumed_m: checkoutForm.value.coin_consumed_m,
      other_amount: checkoutForm.value.other_amount,
      evidence_urls: linesToList(checkoutForm.value.evidenceText),
    });
    checkoutForm.value = {
      content: "",
      consumable_amount: 0,
      coin_consumed_m: 0,
      other_amount: 0,
      evidenceText: "",
    };
    resourceUsage.value = {};
    showToast({ message: "结账已发起，等待号主确认", icon: "passed" });
    await loadOrder();
  } catch (error) {
    showToast({ message: readError(error, "发起结账失败"), icon: "cross" });
  } finally {
    returning.value = false;
  }
}

async function handleConfirmCheckout() {
  if (!order.value) return;
  showDialog({
    title: "确认结账",
    message: "确认账号状态和扣款金额无误吗？确认后订单将完成。",
    showCancelButton: true,
  }).then(async () => {
    completing.value = true;
    try {
      await confirmCheckout(order.value!.id);
      showToast({ message: "结账已确认，订单完成", icon: "passed" });
      await loadOrder();
    } catch (error) {
      showToast({ message: readError(error, "确认结账失败"), icon: "cross" });
    } finally {
      completing.value = false;
    }
  });
}

async function handleCounterCheckout() {
  if (!order.value) return;
  countering.value = true;
  try {
    await counterCheckout(order.value.id, {
      consumable_amount: counterForm.value.consumable_amount,
      coin_consumed_m: counterForm.value.coin_consumed_m,
      other_amount: counterForm.value.other_amount,
      deposit_deduct_amount: counterForm.value.deposit_deduct_amount,
      reason: counterForm.value.reason,
      evidence_urls: linesToList(counterForm.value.evidenceText),
    });
    showToast({ message: "结账修正已提交，等待租客确认", icon: "passed" });
    showCounterPopup.value = false;
    await loadOrder();
  } catch (error) {
    showToast({ message: readError(error, "修改结账失败"), icon: "cross" });
  } finally {
    countering.value = false;
  }
}

async function handleAcceptCheckout() {
  if (!order.value) return;
  showDialog({
    title: "同意修正",
    message: "确定同意号主的结账修正提案吗？同意后订单将完成结算。",
    showCancelButton: true,
  }).then(async () => {
    acceptingCheckout.value = true;
    try {
      await acceptCheckout(order.value!.id);
      showToast({ message: "已确认修正结账，订单完成", icon: "passed" });
      await loadOrder();
    } catch (error) {
      showToast({ message: readError(error, "确认修正失败"), icon: "cross" });
    } finally {
      acceptingCheckout.value = false;
    }
  });
}

async function handleRejectCheckout() {
  if (!order.value) return;
  if (!rejectReason.value.trim()) {
    showToast({ message: "请填写不同意原因", icon: "warning-o" });
    return;
  }
  rejectingCheckout.value = true;
  try {
    await createDispute(order.value.id, {
      type: "checkout_dispute",
      description: rejectReason.value,
      evidence_urls: [],
    });
    rejectReason.value = "";
    showToast({ message: "已拒绝修正并提交争议", icon: "passed" });
    showRejectPopup.value = false;
    await loadOrder();
  } catch (error) {
    showToast({ message: readError(error, "提交拒绝失败"), icon: "cross" });
  } finally {
    rejectingCheckout.value = false;
  }
}

async function handleCreateDispute() {
  if (!order.value) return;
  if (!disputeDescription.value.trim()) {
    showToast({ message: "请填写争议经过说明", icon: "warning-o" });
    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 = "";
    showToast({ message: "申诉已提交，订单进入仲裁", icon: "passed" });
    showDisputePopup.value = false;
    await loadOrder();
  } catch (error) {
    showToast({ message: readError(error, "提交申诉失败"), icon: "cross" });
  } finally {
    disputing.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");
    showToast({ message: "证据文件已上传", icon: "passed" });
  } catch (error) {
    showToast({ message: readError(error, "上传失败"), icon: "cross" });
  } finally {
    uploadingEvidence.value = false;
  }
}

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");
    showToast({ message: "证据文件已上传", icon: "passed" });
  } catch (error) {
    showToast({ message: readError(error, "上传失败"), icon: "cross" });
  } finally {
    uploadingEvidence.value = false;
  }
}

function readError(error: unknown, fallback: string) {
  if (typeof error === "object" && error && "response" in error) {
    const response = (error as { response?: { data?: { message?: string } } }).response;
    return response?.data?.message || fallback;
  }
  return fallback;
}

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

function orderEstimatedEndAt() {
  if (!order.value) return undefined;
  const rentedAt = orderRentedAt();
  const durationHours = Number(order.value.estimated_duration_hours || 0);
  if (!rentedAt || durationHours <= 0) return undefined;
  return new Date(new Date(rentedAt).getTime() + durationHours * 60 * 60 * 1000).toISOString();
}

interface CheckoutResource {
  key: string;
  label: string;
  price: string;
  mode: string;
  quantity: number;
  unitPrice: number;
}

function readSnapshot(): any {
  const snapshot = order.value?.account_snapshot;
  if (isRecord(snapshot)) return snapshot;
  return null;
}

function readAssetSummary(): any {
  const summary = readSnapshot()?.asset_summary;
  if (isRecord(summary)) return summary;
  return null;
}

function readSnapshotResources(): CheckoutResource[] {
  const resources = readAssetSummary()?.resources;
  if (!Array.isArray(resources)) return [];
  return resources
    .filter(isRecord)
    .map((item) => {
      const key = String(item.key || item.label || "");
      const label = String(item.label || key || "额外消耗品");
      const price = String(item.price || "");
      return {
        key,
        label,
        price,
        mode: String(item.mode || "收费"),
        quantity: readNumber(item.quantity),
        unitPrice: readUnitPrice(price),
      };
    })
    .filter((item) => item.key && item.quantity > 0);
}

function hydrateResourceUsage() {
  const next: Record<string, number> = {};
  for (const item of checkoutResources.value) {
    next[item.key] = Math.min(Math.max(Number(resourceUsage.value[item.key] || 0), 0), item.quantity);
  }
  resourceUsage.value = next;
}

function readResourceUsage(key: string) {
  return Math.max(Number(resourceUsage.value[key] || 0), 0);
}

function isChargedResource(item: CheckoutResource) {
  return item.mode !== "赠送";
}

function resourceLineAmount(item: CheckoutResource) {
  return roundMoney(readResourceUsage(item.key) * item.unitPrice);
}

function checkoutContentWithSummary() {
  const lines = [checkoutForm.value.content.trim()].filter(Boolean);
  const usedResources = checkoutResources.value.filter((item) => readResourceUsage(item.key) > 0);
  if (usedResources.length) {
    lines.push(
      `额外消耗品：${usedResources
        .map(
          (item) =>
            `${item.label} ${readResourceUsage(item.key)}/${item.quantity}${
              isChargedResource(item) ? `，金额¥${money(resourceLineAmount(item))}` : "，赠送不扣款"
            }`
        )
        .join("；")}`
    );
  }
  if (Number(checkoutForm.value.coin_consumed_m || 0) > 0) {
    lines.push(`哈夫币消耗：${quantity(Number(checkoutForm.value.coin_consumed_m))}M，预计剩余${quantity(remainingHafCoinM.value)}M`);
  }
  if (lines.length === 0) {
    lines.push("租客发起结账。");
  }
  return lines.join("\n");
}

function readUnitPrice(priceText: string) {
  const normalized = priceText.replace(/，/g, ",").trim();
  const fractionMatch = normalized.match(/(\d+(?:\.\d+)?)\s*元\s*\/\s*(\d+(?:\.\d+)?)/);
  if (fractionMatch) {
    const amount = Number(fractionMatch[1]);
    const count = Number(fractionMatch[2]);
    return count > 0 ? roundMoney(amount / count) : 0;
  }
  const singleMatch = normalized.match(/(\d+(?:\.\d+)?)\s*元/);
  if (singleMatch) return Number(singleMatch[1]);
  const fallback = normalized.match(/(\d+(?:\.\d+)?)/);
  return fallback ? Number(fallback[1]) : 0;
}

function roundMoney(value: number) {
  return Math.round(value);
}

function roundQuantity(value: number) {
  return Math.round(value * 100) / 100;
}

function money(value: unknown) {
  return `${roundMoney(readNumber(value))}`;
}

function orderRentAmount(item: Order) {
  if (item.owner_id === session.userId) return Number(item.owner_rent_amount ?? item.display_amount ?? 0);
  if (item.renter_id === session.userId) return Number(item.rent_amount ?? item.display_amount ?? 0);
  return Number(item.display_amount ?? 0);
}

function ownerActualIncome(item: Order) {
  if (item.owner_id !== session.userId) return null;
  const value = item.checkout?.owner_income_amount;
  return typeof value === "number" ? value : null;
}

function quantity(value: unknown) {
  const rounded = roundQuantity(readNumber(value));
  return Number.isInteger(rounded) ? `${rounded}` : rounded.toFixed(2);
}

function readNumber(value: unknown) {
  const number = Number(value || 0);
  return Number.isFinite(number) ? number : 0;
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null;
}

function hydrateCounterForm() {
  if (!order.value?.checkout) return;
  const checkout = order.value.checkout;
  counterForm.value.consumable_amount = checkout.consumable_amount;
  counterForm.value.coin_consumed_m = checkout.coin_consumed_m;
  counterForm.value.other_amount = checkout.other_amount;
  counterForm.value.deposit_deduct_amount = checkout.deposit_deduct_amount;
}

function linesToList(value: string) {
  return value
    .split("\n")
    .map((item) => item.trim())
    .filter(Boolean);
}

async function openOrderChat() {
  if (!order.value || openingChat.value) return;
  openingChat.value = true;
  try {
    const chat = await fetchOrderChat(order.value.id);
    router.push(`/m/chats/${chat.id}`);
  } catch {
    showToast({ message: "订单群聊暂不可用", icon: "warning-o" });
  } finally {
    openingChat.value = false;
  }
}

/* Status Theme Color Mapping */
function getStatusTagType(status: string) {
  if (["completed", "received"].includes(status)) return "success";
  if (["pending_payment", "pending_confirm"].includes(status)) return "warning";
  if (["renting"].includes(status)) return "primary";
  if (["cancelled", "closed"].includes(status)) return "danger";
  return "danger";
}
</script>

<template>
  <main class="mobile-order-detail-view">
    <header class="page-header">
      <button class="back-btn" @click="router.back()">
        <van-icon name="arrow-left" :size="20" />
      </button>
      <h1>订单详情</h1>
      <button v-if="order" class="chat-btn" type="button" :disabled="openingChat" @click="openOrderChat">
        <van-icon name="chat-o" :size="19" />
      </button>
      <span v-else class="header-spacer"></span>
    </header>

    <van-loading v-if="loading" class="center-loading" size="24px" vertical>
      加载中...
    </van-loading>

    <template v-else-if="order">
      <!-- 状态及核心信息卡片 -->
      <section class="card-section info-card">
        <div class="card-header-row">
          <span class="order-no">{{ order.order_no }}</span>
          <van-tag :type="getStatusTagType(order.status)" size="medium">
            {{ orderStatusLabel(order.status) }}
          </van-tag>
        </div>
        <h2 class="order-title">{{ order.title }}</h2>
        <div class="order-meta-grid">
          <div class="meta-item">
            <span class="meta-label">{{ orderAmountLabel }}</span>
            <strong class="meta-value accent">¥{{ money(orderRentDisplayAmount) }}</strong>
          </div>
          <div v-if="isOwner && ownerIncomeDisplayAmount !== null" class="meta-item">
            <span class="meta-label">{{ ownerIncomeLabel }}</span>
            <strong class="meta-value income">¥{{ money(ownerIncomeDisplayAmount) }}</strong>
          </div>
          <div class="meta-item">
            <span class="meta-label">押金</span>
            <strong class="meta-value">¥{{ money(order.deposit_amount) }}</strong>
          </div>
          <div class="meta-item">
            <span class="meta-label">交接状态</span>
            <strong class="meta-value">{{ handoffStatusLabel(order.handoff_status) }}</strong>
          </div>
        </div>
      </section>

      <!-- 时间节点卡片 -->
      <section class="card-section">
        <van-cell-group inset :border="false">
          <van-cell title="开始时间" :value="formatDateTime(orderRentedAt(), '未开始')" />
          <van-cell title="预计截止" :value="formatDateTime(orderEstimatedEndAt(), '未设置')" />
        </van-cell-group>
      </section>

      <!-- Renter Action: Pay / Cancel -->
      <section v-if="order.status === 'pending_payment'" class="card-section action-card">
        <p class="action-hint">订单已创建，请确认并在有效期内完成支付。过期订单将自动关闭。</p>
        <div class="action-buttons">
          <van-button
            v-if="isRenter"
            type="primary"
            block
            round
            :loading="paying"
            loading-text="支付中..."
            @click="handlePay"
          >
            支付订单
          </van-button>
          <van-button
            type="danger"
            block
            plain
            round
            :loading="cancelling"
            loading-text="取消中..."
            @click="handleCancel"
          >
            取消订单并释放账号
          </van-button>
        </div>
      </section>

      <!-- Handoff Panel: Owner Handoff Info Submission -->
      <section v-if="isOwner && order.status === 'pending_handoff' && order.handoff_status === 'pending_owner'" class="card-section action-card">
        <h3 class="section-title">提交交接说明</h3>
        <p class="action-hint">提交登录所需的账号密码、密保注意事项或扫码交接联系方式。</p>
        <van-field
          v-model="handoffContent"
          rows="3"
          autosize
          label="交接说明"
          type="textarea"
          placeholder="请在这里填写登录方式、注意事项或扫码联系渠道"
          class="action-field"
        />
        <van-button
          type="primary"
          block
          round
          :loading="handoffing"
          loading-text="正在提交..."
          @click="handleSubmitHandoff"
        >
          提交交接说明
        </van-button>
      </section>

      <!-- Handoff Panel: Renter Confirm Handoff Received -->
      <section v-if="isRenter && order.status === 'pending_handoff' && order.handoff_status === 'pending_renter_confirm'" class="card-section action-card">
        <h3 class="section-title">确认收到账号</h3>
        <p class="action-hint">请按照号主提交的交接说明进行登录测试，确认无误后点击下方按钮确认收号，租期将正式开始计算。</p>
        <div class="action-buttons">
          <van-button
            type="primary"
            block
            round
            :loading="confirming"
            loading-text="确认中..."
            @click="handleConfirmReceive"
          >
            确认收到账号
          </van-button>
          <van-button
            type="danger"
            block
            plain
            round
            :loading="cancelling"
            loading-text="取消中..."
            @click="handleCancel"
          >
            未收到/无法登录，取消订单
          </van-button>
        </div>
      </section>

      <!-- Handoff Records list -->
      <section class="card-section">
        <h3 class="section-title">交接日志</h3>
        <van-empty v-if="handoffRecords.length === 0" image="search" description="暂无交接日志记录" />
        <div v-else class="log-timeline">
          <div v-for="record in handoffRecords" :key="record.id" class="log-item">
            <div class="log-dot"></div>
            <div class="log-content-wrap">
              <strong class="log-type">{{ record.type }}</strong>
              <p class="log-desc">{{ record.content }}</p>
              <span class="log-time">{{ formatDateTime(record.created_at) }}</span>
            </div>
          </div>
        </div>
      </section>

      <!-- Renter Action: Return Account & Initiate Checkout -->
      <section v-if="isRenter && ['renting', 'overdue'].includes(order.status)" class="card-section action-card">
        <h3 class="section-title">退号发起结账</h3>
        <p class="action-hint">使用完毕，请输入在此期间消耗的物资与哈夫币进行结账申请。</p>
        
        <van-field
          v-model="checkoutForm.content"
          rows="3"
          autosize
          label="结账备注"
          type="textarea"
          placeholder="可在此说明物品消耗情况或归还留言"
          class="action-field"
        />

        <!-- Checkout resource usage selection -->
        <div v-if="checkoutResources.length" class="resource-usage-panel">
          <strong class="resource-panel-title">额外物资消耗登记</strong>
          <div v-for="item in checkoutResources" :key="item.key" class="resource-row">
            <div class="resource-meta">
              <span class="resource-name">{{ item.label }}</span>
              <span class="resource-price-text">上限 {{ item.quantity }} · {{ item.mode }} · {{ item.price }}</span>
            </div>
            <div class="stepper-wrap">
              <van-stepper
                v-model="resourceUsage[item.key]"
                integer
                min="0"
                :max="item.quantity"
              />
              <span class="resource-line-amount">¥{{ money(resourceLineAmount(item)) }}</span>
            </div>
          </div>
          <div class="resource-panel-footer">
            <span>物资金额合计：</span>
            <strong>¥{{ money(resourceChargeAmount) }}</strong>
          </div>
        </div>

        <van-cell-group inset :border="false" class="action-field">
          <van-field label="消耗哈夫币" label-width="100px">
            <template #input>
              <div class="coin-input-wrap">
                <input
                  v-model.number="checkoutForm.coin_consumed_m"
                  type="number"
                  placeholder="消耗数量"
                  class="custom-inline-input"
                />
                <span class="input-unit">M</span>
              </div>
            </template>
          </van-field>
          <div class="coin-hint">
            订单快照 {{ quantity(snapshotHafCoinM) }}M，预计剩余 {{ quantity(remainingHafCoinM) }}M
          </div>
          <van-field label="其他押金赔付" label-width="100px">
            <template #input>
              <div class="coin-input-wrap">
                <input
                  v-model.number="checkoutForm.other_amount"
                  type="number"
                  placeholder="不含上方额外物资"
                  class="custom-inline-input"
                />
                <span class="input-unit">元</span>
              </div>
            </template>
          </van-field>
          <div class="deposit-deduct-hint">仅填写封禁、违规、资产损坏等需要从押金赔付的费用。</div>
        </van-cell-group>
        <div class="checkout-fee-preview">
          <div>
            <span>额外消耗品已用</span>
            <strong>¥{{ money(resourceChargeAmount) }}</strong>
            <em>计入实际结算租金</em>
          </div>
          <div>
            <span>其他押金赔付</span>
            <strong>¥{{ money(checkoutForm.other_amount) }}</strong>
            <em>从押金赔付扣除</em>
          </div>
        </div>

        <van-field
          v-model="checkoutForm.evidenceText"
          rows="2"
          autosize
          label="结账证据"
          type="textarea"
          placeholder="结账截图链接（每行一个）"
          class="action-field"
        />

        <van-button
          type="primary"
          block
          round
          :loading="returning"
          loading-text="正在提交结账..."
          @click="handleSubmitCheckout"
        >
          提交结账归还
        </van-button>
      </section>

      <!-- Checkout Details Display -->
      <section v-if="order.checkout && ['pending_checkout_confirm', 'pending_checkout_accept'].includes(order.status)" class="card-section">
        <h3 class="section-title">结账结算账单</h3>
        <van-cell-group inset :border="false">
          <van-cell title="实际结算租金" :value="`¥${money(order.checkout.display_amount)}`" />
          <van-cell title="押金总额" :value="`¥${money(order.checkout.deposit_amount)}`" />
          <van-cell title="额外消耗品已用" :value="`¥${money(order.checkout.consumable_amount)}`" />
          <van-cell title="押金赔付扣除" :value="`¥${money(order.checkout.deposit_deduct_amount)}`" value-class="red-text" />
          <van-cell v-if="isRenter" title="退还租客" :value="`¥${money(order.checkout.renter_refund_amount)}`" value-class="green-text" />
          <van-cell v-if="isOwner" title="号主最终收入" :value="`¥${money(order.checkout.owner_income_amount)}`" value-class="green-text" />
          <van-cell v-if="order.checkout.content" title="结账备注" :label="order.checkout.content" />
          <van-cell v-if="order.checkout.owner_adjustment_reason" title="号主修正原因" :label="order.checkout.owner_adjustment_reason" />
        </van-cell-group>
      </section>

      <!-- Owner Action: Confirm Checkout / Make Counter Adjustment Proposal -->
      <section v-if="isOwner && order.status === 'pending_checkout_confirm'" class="card-section action-card">
        <h3 class="section-title">结账处理</h3>
        <p class="action-hint">租客已发起结账并归还账号。确认无误后点击“确认结账”；若扣款不足，可以提出“修改结账”反向提案。</p>
        <div class="action-buttons">
          <van-button
            type="primary"
            block
            round
            :loading="completing"
            loading-text="处理中..."
            @click="handleConfirmCheckout"
          >
            同意并确认结账
          </van-button>
          <van-button
            type="warning"
            block
            plain
            round
            @click="showCounterPopup = true"
          >
            修改扣款金额
          </van-button>
        </div>
      </section>

      <!-- Renter Action: Accept Counter Checkout Proposal / Refuse and Dispute -->
      <section v-if="isRenter && order.status === 'pending_checkout_accept'" class="card-section action-card">
        <h3 class="section-title">号主结账修正审批</h3>
        <p class="action-hint">号主修改了您的结账申请并对押金进行了扣除。请审查，同意将完成结算，不同意将进入仲裁申诉。</p>
        <div class="action-buttons">
          <van-button
            type="primary"
            block
            round
            :loading="acceptingCheckout"
            loading-text="同意中..."
            @click="handleAcceptCheckout"
          >
            同意修正并结账
          </van-button>
          <van-button
            type="danger"
            block
            plain
            round
            @click="showRejectPopup = true"
          >
            拒绝修正并提起申诉
          </van-button>
        </div>
      </section>

      <!-- Universal Action: File a Dispute -->
      <section v-if="canOpenDispute" class="card-section action-card">
        <van-button
          type="warning"
          block
          plain
          round
          @click="showDisputePopup = true"
        >
          {{ isCheckoutDisputeStage ? '对结账发起申诉争议' : '发起订单申诉争议' }}
        </van-button>
      </section>

      <!-- Snapshot Account Details Accordion -->
      <section class="card-section">
        <van-collapse v-model="activeNames">
          <van-collapse-item title="查看订单账号快照信息" name="snapshot">
            <template v-if="readSnapshot()">
              <van-cell-group :border="false">
                <van-cell title="区服" :value="order.server_region" />
                <van-cell title="登录平台" :value="order.login_platform" />
                <van-cell title="烽火等级" :value="readAssetSummary()?.fire_level || '--'" />
                <van-cell title="绝密KD" :value="readAssetSummary()?.secret_kd || '--'" />
                <van-cell title="常用登录地区" :value="readAssetSummary()?.common_regions?.join('、') || '--'" />
                <van-cell title="封禁记录" :value="readAssetSummary()?.ban_record || '无'" />
                <van-cell title="体力等级" :value="readAssetSummary()?.stamina_level || '--'" />
                <van-cell title="负重等级" :value="readAssetSummary()?.load_level || '--'" />
                <van-cell title="账号备注" :label="readSnapshot()?.description || '无'" />
              </van-cell-group>
            </template>
            <template v-else>
              <div class="no-snapshot-hint">暂无快照数据</div>
            </template>
          </van-collapse-item>
        </van-collapse>
      </section>
    </template>

    <div v-else class="empty-wrap">
      <van-empty image="search" description="订单不存在或已被删除" />
    </div>

    <!-- POPUP: Owner Counter Checkout Adjustments -->
    <van-popup
      v-model:show="showCounterPopup"
      position="bottom"
      round
      class="mobile-popup-form"
    >
      <header class="popup-header">
        <h3>修改结账扣款金额</h3>
        <button class="popup-close" @click="showCounterPopup = false">✕</button>
      </header>
      <div class="popup-body">
        <p class="form-hint-info">在此调整实际使用的租金项目和押金赔付金额，提案将交由租客二次确认。</p>
        <van-cell-group :border="false">
          <van-field label="额外消耗品已用">
            <template #input>
              <input v-model.number="counterForm.consumable_amount" type="number" class="custom-inline-input" />
            </template>
          </van-field>
          <van-field label="消耗哈夫币 M">
            <template #input>
              <input v-model.number="counterForm.coin_consumed_m" type="number" class="custom-inline-input" />
            </template>
          </van-field>
          <van-field label="其他押金扣款">
            <template #input>
              <input v-model.number="counterForm.other_amount" type="number" class="custom-inline-input" />
            </template>
          </van-field>
          <van-field label="押金赔付扣除" required>
            <template #input>
              <input v-model.number="counterForm.deposit_deduct_amount" type="number" class="custom-inline-input" />
            </template>
          </van-field>
        </van-cell-group>
        <van-field
          v-model="counterForm.reason"
          rows="2"
          autosize
          label="修改原因"
          type="textarea"
          placeholder="请说明调整扣款的原因，说服租客确认"
          class="popup-field"
        />
        <van-field
          v-model="counterForm.evidenceText"
          rows="2"
          autosize
          label="扣款证据"
          type="textarea"
          placeholder="证据链接（每行一个）"
          class="popup-field"
        />
        <div class="evidence-upload-row">
          <span>上传新证据截图：</span>
          <input type="file" accept="image/*" @change="handleCounterEvidenceUpload" />
        </div>
        <van-button
          type="warning"
          block
          round
          :loading="countering"
          loading-text="提交中..."
          @click="handleCounterCheckout"
          class="popup-submit"
        >
          提交提案给租客确认
        </van-button>
      </div>
    </van-popup>

    <!-- POPUP: Renter Reject Counter Proposal Reason -->
    <van-popup
      v-model:show="showRejectPopup"
      position="bottom"
      round
      class="mobile-popup-form"
    >
      <header class="popup-header">
        <h3>拒绝修正扣款说明</h3>
        <button class="popup-close" @click="showRejectPopup = false">✕</button>
      </header>
      <div class="popup-body">
        <p class="form-hint-info">拒绝号主的修正提案后，订单将立即自动发起争议，由客服介入根据证据判定。</p>
        <van-field
          v-model="rejectReason"
          rows="3"
          autosize
          label="拒绝原因"
          type="textarea"
          placeholder="请详细叙述拒绝号主扣款的理由，这些信息将被客服作为判定依据"
          class="popup-field"
        />
        <van-button
          type="danger"
          block
          round
          :loading="rejectingCheckout"
          loading-text="发起争议中..."
          @click="handleRejectCheckout"
          class="popup-submit"
        >
          提交原因并提起争议
        </van-button>
      </div>
    </van-popup>

    <!-- POPUP: Create Generic Order Dispute -->
    <van-popup
      v-model:show="showDisputePopup"
      position="bottom"
      round
      class="mobile-popup-form"
    >
      <header class="popup-header">
        <h3>发起申诉争议</h3>
        <button class="popup-close" @click="showDisputePopup = false">✕</button>
      </header>
      <div class="popup-body">
        <van-field
          v-if="!isCheckoutDisputeStage"
          label="申诉类型"
          class="popup-field"
        >
          <template #input>
            <select v-model="disputeType" class="custom-select">
              <option value="cannot_login">无法登录</option>
              <option value="false_description">虚假描述</option>
              <option value="account_banned">账号被封</option>
              <option value="asset_loss">资产损失</option>
              <option value="haf_coin_dispute">哈夫币争议</option>
              <option value="handoff_timeout">超时未交接</option>
              <option value="return_timeout">超时未归还</option>
            </select>
          </template>
        </van-field>
        <van-field
          v-model="disputeDescription"
          rows="3"
          autosize
          label="经过说明"
          type="textarea"
          placeholder="请在此描述您的诉求、事件经过、时间点等详细情况"
          class="popup-field"
        />
        <van-field
          v-model="disputeEvidenceText"
          rows="2"
          autosize
          label="证据列表"
          type="textarea"
          placeholder="证据链接（每行一个）"
          class="popup-field"
        />
        <div class="evidence-upload-row">
          <span>上传证据截图：</span>
          <input type="file" accept="image/*" @change="handleEvidenceUpload" />
        </div>
        <van-button
          type="warning"
          block
          round
          :loading="disputing"
          loading-text="正在发起申诉..."
          @click="handleCreateDispute"
          class="popup-submit"
        >
          提交申诉客服仲裁
        </van-button>
      </div>
    </van-popup>
  </main>
</template>

<style scoped>
.mobile-order-detail-view {
  min-height: 100dvh;
  background: #f5f7fa;
  padding-bottom: 40px;
}

/* ========== Header ========== */
.page-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  height: 48px;
  padding: 0 12px;
  background: #fff;
  border-bottom: 1px solid #eee;
}

.page-header h1 {
  flex: 1;
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  text-align: center;
}

.back-btn,
.chat-btn {
  display: grid;
  width: 36px;
  height: 36px;
  place-items: center;
  border: none;
  background: none;
  color: #333;
  cursor: pointer;
}

.chat-btn:disabled {
  color: #a1a1aa;
}

.header-spacer {
  width: 36px;
}

.center-loading {
  display: flex;
  justify-content: center;
  padding: 60px 0;
}

/* ========== Card layout ========== */
.card-section {
  margin: 12px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
  overflow: hidden;
  padding: 14px;
}

.info-card {
  padding: 16px;
}

.card-header-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.order-no {
  font-size: 12px;
  color: #999;
  font-family: monospace;
}

.order-title {
  font-size: 18px;
  font-weight: 700;
  color: #1a1a1a;
  margin: 0 0 14px 0;
}

.order-meta-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  background: #f8f9fa;
  border-radius: 8px;
  padding: 10px;
}

.meta-item {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.meta-label {
  font-size: 11px;
  color: #8c96a0;
  margin-bottom: 4px;
}

.meta-value {
  font-size: 13px;
  color: #2c3e50;
  font-weight: 600;
}

.meta-value.accent {
  color: #ff5f00;
  font-weight: 700;
}

.meta-value.income {
  color: #16a34a;
  font-weight: 700;
}

.action-card {
  padding: 16px;
}

.section-title {
  font-size: 15px;
  font-weight: 700;
  color: #2c3e50;
  margin: 0 0 8px 0;
}

.action-hint {
  font-size: 12px;
  color: #7f8c8d;
  line-height: 1.5;
  margin: 0 0 14px 0;
}

.action-buttons {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.action-field {
  background: #f8fafc;
  border-radius: 8px;
  margin-bottom: 12px;
  overflow: hidden;
}

/* ========== Log Timeline ========== */
.log-timeline {
  display: flex;
  flex-direction: column;
  position: relative;
  padding-left: 16px;
  margin-top: 10px;
}

.log-timeline::after {
  content: "";
  position: absolute;
  top: 6px;
  bottom: 6px;
  left: 4px;
  width: 1px;
  background: #e2e8f0;
}

.log-item {
  position: relative;
  padding-bottom: 16px;
}

.log-item:last-child {
  padding-bottom: 0;
}

.log-dot {
  position: absolute;
  top: 5px;
  left: -15px;
  z-index: 2;
  width: 7px;
  height: 7px;
  background: #1477ff;
  border-radius: 50%;
}

.log-content-wrap {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.log-type {
  font-size: 13px;
  color: #2d3748;
}

.log-desc {
  font-size: 12px;
  color: #718096;
  margin: 0;
  line-height: 1.4;
}

.log-time {
  font-size: 11px;
  color: #a0aec0;
}

/* ========== Resource Panel ========== */
.resource-usage-panel {
  background: #f8fafc;
  border-radius: 8px;
  padding: 12px;
  margin-bottom: 12px;
}

.resource-panel-title {
  display: block;
  font-size: 13px;
  font-weight: 700;
  margin-bottom: 10px;
  color: #2d3748;
}

.resource-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px dashed #e2e8f0;
}

.resource-row:last-child {
  border-bottom: none;
}

.resource-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.resource-name {
  font-size: 13px;
  color: #2d3748;
  font-weight: 600;
}

.resource-price-text {
  font-size: 11px;
  color: #a0aec0;
}

.stepper-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
}

.resource-line-amount {
  min-width: 50px;
  text-align: right;
  font-size: 13px;
  font-weight: 700;
  color: #ff5f00;
}

.resource-panel-footer {
  display: flex;
  justify-content: flex-end;
  align-items: baseline;
  margin-top: 10px;
  font-size: 12px;
  color: #4a5568;
}

.resource-panel-footer strong {
  font-size: 15px;
  color: #ff5f00;
}

.deposit-deduct-hint {
  padding: 0 16px 10px;
  color: #8a94a6;
  font-size: 12px;
  line-height: 1.5;
}

.checkout-fee-preview {
  display: grid;
  gap: 8px;
  margin: 0 16px 12px;
}

.checkout-fee-preview div {
  display: grid;
  gap: 4px;
  padding: 10px 12px;
  border-radius: 8px;
  background: #f8fafc;
}

.checkout-fee-preview span {
  color: #4a5568;
  font-size: 12px;
  font-weight: 700;
}

.checkout-fee-preview strong {
  color: #ff5f00;
  font-size: 16px;
  font-weight: 800;
}

.checkout-fee-preview em {
  color: #8a94a6;
  font-size: 11px;
  font-style: normal;
}

.coin-input-wrap {
  display: flex;
  align-items: center;
  width: 100%;
}

.custom-inline-input {
  border: none;
  background: transparent;
  outline: none;
  font-size: 14px;
  flex: 1;
}

.input-unit {
  font-size: 14px;
  color: #718096;
  margin-left: 6px;
}

.coin-hint {
  font-size: 11px;
  color: #a0aec0;
  padding: 0 16px 8px 16px;
  margin-top: -6px;
}

.no-snapshot-hint {
  text-align: center;
  padding: 10px;
  color: #cbd5e0;
  font-size: 13px;
}

/* ========== Popups ========== */
.mobile-popup-form {
  max-height: 85%;
  padding-bottom: env(safe-area-inset-bottom);
}

.popup-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #edf2f7;
}

.popup-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
}

.popup-close {
  border: none;
  background: transparent;
  font-size: 16px;
  color: #a0aec0;
  cursor: pointer;
}

.popup-body {
  padding: 16px;
  overflow-y: auto;
}

.form-hint-info {
  font-size: 12px;
  color: #718096;
  line-height: 1.5;
  margin: 0 0 12px 0;
}

.popup-field {
  background: #f7fafc;
  border-radius: 8px;
  margin-bottom: 12px;
}

.evidence-upload-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 13px;
  color: #4a5568;
  margin-bottom: 16px;
}

.popup-submit {
  margin-top: 10px;
}

.custom-select {
  border: none;
  background: transparent;
  width: 100%;
  font-size: 14px;
  color: #2d3748;
  outline: none;
}

/* Utilities */
.red-text {
  color: #ef4444;
}

.green-text {
  color: #10b981;
}

.empty-wrap {
  padding: 60px 0;
}
</style>
