<script lang="ts" setup>
import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridListeners } from '#/adapter/vxe-table';

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

import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { useUserStore } from '@vben/stores';

import {
  Button,
  Image,
  message,
  Modal as AntdModal,
  Popconfirm,
  Popover,
  Space,
  Switch,
  Table,
  Tag,
} from 'ant-design-vue';

import dayjs from 'dayjs';

import type { ActionItem } from '#/components/table-action';

import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { TableAction } from '#/components/table-action';
import SensitiveText from '#/components/sensitive-text/SensitiveText.vue';
import {
  cancelOrderApi,
  changeDeliveryWarehouseApi,
  getOrderInfo,
  getOrderList,
  getVerifyRecentOrderAmounts,
  saleAmountApi,
  updateFreeShipping,
} from '#/views/business/order/product-order/api';
import { getDeliveryWarehouseOptionsByDrugs } from '#/views/doctor/doctor-reception/api';
import {
  accrueSalespersonCommissionApi,
  retryConfirmReceiveApi,
  reverseSalespersonCommissionApi,
  simulatePayApi,
} from '#/views/business/order/api/order-ops';
import ChinaErpSyncLogDrawer from '#/views/business/order/components/china-erp-sync-log-drawer.vue';
import OrderTraceDrawer from '#/views/business/order/components/order-trace-drawer.vue';
import OrderPricePercentAdjustDrawer from '#/views/business/order/components/OrderPricePercentAdjustDrawer.vue';
import { getOrderPriceAdjustConfig } from '#/api/order/priceAdjust';
import type { QuickDiscountOption } from '#/utils/pricePercentAdjust';
import { normalizeQuickOptions } from '#/utils/pricePercentAdjust';
import PrescriptionDetail from '#/views/doctor/doctor-reception/components/PrescriptionDetail.vue';
import DoctorCardModal from '#/views/doctor/doctor/components/DoctorCardModal.vue';
import StoreCardModal from '#/components/store-card/StoreCardModal.vue';
import {
  WxUserPatientDetailModal,
  WxUserPatientsModal,
} from '#/components/wx-user-patient';

import DetailModal from './components/detail.vue';
import OrderUserInfoCell from './components/cells/OrderUserInfoCell.vue';
import LogisticsModal from './components/logistics-modal.vue';
import FormModalDemo from './components/modal.vue';
import ProductOrderCardList from './components/ProductOrderCardList.vue';
import ProductOrderExportModal from './components/ProductOrderExportModal.vue';
import Refund from './components/refund.vue';
import {
  ORDER_STATUS_MAP,
  ORDER_TYPE_MAP,
  PRESCRIPTION_TYPE_MAP,
} from './config/constants';
import { formOptions } from './config/search';
import { gridOptions } from './config/table';
import { useViewMode, ViewModeSwitch } from '#/components/view-mode-switch';
import { StatIslands, type StatIslandItem } from '#/components/stat-islands';
import { isPlatformSuperAdmin } from '#/views/system/admin/_shared/platform-admin-role';

const router = useRouter();
const route = useRoute();
const userStore = useUserStore();
// vben 登录态 roles 为 string[] 与本地 PlatformAdminUserInfo 结构不同，仅取 role_id 判断，直接断言
const canViewInviterCommission = isPlatformSuperAdmin(
  userStore.userInfo as Parameters<typeof isPlatformSuperAdmin>[0],
);

const hasTopTableDropDownActions = ref(false);

function findRegisterOrderListPath(): null | string {
  const routes = router.getRoutes();
  const hit = routes.find(
    (r) =>
      typeof r.path === 'string' &&
      r.path.length > 0 &&
      !r.redirect &&
      /register/i.test(r.path) &&
      /order/i.test(r.path),
  );
  return hit?.path ?? null;
}

function goRegisterOrder(row: Record<string, any>) {
  const orderNo = row.register_order_no;
  if (!orderNo) {
    message.warning('无关联挂号订单号');
    return;
  }
  const path = findRegisterOrderListPath();
  if (!path) {
    message.warning('未找到挂号订单菜单路由，请从左侧菜单进入挂号订单');
    return;
  }
  void router.push({ path, query: { order_no: String(orderNo) } });
}

function formatRegisterAmount(row: Record<string, any>) {
  if (row.register_id == null || row.register_id === '') {
    return '—';
  }
  const n = Number(row.register_price);
  if (!Number.isFinite(n)) {
    return '—';
  }
  return `¥${n.toFixed(2)}`;
}

const gridEvents: VxeGridListeners<any> = {
  checkboxChange() {
    // eslint-disable-next-line no-use-before-define
    const records = gridApi.grid.getCheckboxRecords();
    hasTopTableDropDownActions.value = records.length > 0;
  },
  checkboxAll() {
    // eslint-disable-next-line no-use-before-define
    const records = gridApi.grid.getCheckboxRecords();
    hasTopTableDropDownActions.value = records.length > 0;
  },
};

/**
 * 从路由 query 生成带默认筛选的表单配置
 * VxeGrid 首屏 autoLoad 使用 latestSubmissionValues，需在挂载前写入 schema defaultValue
 */
function buildFormOptionsFromRoute(): VbenFormProps {
  const rawStoreId = route.query.store_id;
  const storeId = Array.isArray(rawStoreId) ? rawStoreId[0] : rawStoreId;
  if (!storeId) {
    return formOptions;
  }
  const rawTimeScope = route.query.time_scope;
  const timeScope = Array.isArray(rawTimeScope) ? rawTimeScope[0] : rawTimeScope;
  const schema = (formOptions.schema ?? []).map((item) => {
    if (item.fieldName === 'store_ids') {
      return { ...item, defaultValue: [Number(storeId)] };
    }
    if (item.fieldName === 'search_time') {
      if (timeScope === 'month') {
        // 与 RangePicker valueFormat 保持一致用字符串，defaultValue 会直接进入首屏搜索条件
        return {
          ...item,
          defaultValue: [
            dayjs().startOf('month').format('YYYY-MM-DD'),
            dayjs().format('YYYY-MM-DD'),
          ],
        };
      }
      if (timeScope === 'all') {
        return { ...item, defaultValue: null };
      }
    }
    return item;
  });
  return { ...formOptions, schema };
}

/** 列表/卡片双视图：通用 useViewMode 自带 localStorage 记忆 */
const viewMode = useViewMode('product-order-view-mode');
const cardListRef = ref<InstanceType<typeof ProductOrderCardList> | null>(null);

/** 生效的搜索表单配置（含路由 store_id/time_scope 默认值注入） */
const effectiveFormOptions = buildFormOptionsFromRoute();

/**
 * 从 schema 提取 defaultValue 作为首屏搜索条件
 * 列表首屏 query 与卡片首屏 reload 都要带默认时间范围，否则查询口径与表单显示不一致
 */
function collectDefaultSearchValues(): Record<string, any> {
  const values: Record<string, any> = {};
  for (const item of effectiveFormOptions.schema ?? []) {
    if (item.fieldName && item.defaultValue !== undefined) {
      values[item.fieldName] = item.defaultValue;
    }
  }
  return values;
}

/** 列表与卡片共用的搜索条件（提交/重置时整体替换，卡片靠 watch 自动拉数） */
const searchValues = ref<Record<string, any>>(collectDefaultSearchValues());

/**
 * 顶部统一搜索表单（从 grid 内嵌表单抽出，双视图共用）
 * 列表模式提交后 reload 回第 1 页；卡片模式改 searchValues 由 CardList watch 拉数
 */
const [SearchForm, searchFormApi] = useVbenForm({
  ...effectiveFormOptions,
  handleSubmit: async (values) => {
    searchValues.value = { ...(values || {}) };
    if (viewMode.value === 'list') {
      gridApi.reload();
    } else {
      // 卡片视图数据由 formValues watch 驱动，这里只需同步顶部销售统计
      saleAmount(searchValues.value);
    }
  },
  handleReset: async () => {
    // 自定义 handleReset 会接管默认行为，必须手动还原控件到 defaultValue（reset 为新 API，resetForm 已弃用）
    await searchFormApi.reset();
    searchValues.value = collectDefaultSearchValues();
    if (viewMode.value === 'list') {
      gridApi.reload();
    } else {
      saleAmount(searchValues.value);
    }
  },
});

const [Grid, gridApi] = useVbenVxeGrid({
  gridOptions: {
    ...gridOptions,
    // 搜索已抽出为顶部统一表单，关闭 grid 自带的表单开关按钮
    toolbarConfig: { ...gridOptions.toolbarConfig, search: false },
    proxyConfig: {
      ajax: {
        /** 始终合并顶部统一搜索条件；同时刷新顶部销售金额统计 */
        query: async ({ page }: { page: { currentPage: number; pageSize: number } }) => {
          saleAmount(searchValues.value);
          return await getOrderList({
            page: page.currentPage,
            pageSize: page.pageSize,
            ...searchValues.value,
          });
        },
      },
    },
  },
  gridEvents,
});

// 记忆持久化由 useViewMode 内部完成；这里只处理切回列表时 grid 被 v-if 卸载过需重查
watch(viewMode, (mode, prev) => {
  if (mode === 'list' && prev === 'card') {
    gridApi.query();
  }
});

/** 操作成功后的视图刷新：列表保当前页，卡片原地重拉已加载范围 */
async function refreshCurrentView() {
  await (viewMode.value === 'list'
    ? gridApi.query()
    : cardListRef.value?.refreshKeepPage?.());
}

/** 回第 1 页的强刷新（弹窗内部 reload 语义） */
function refreshCurrentViewFromPageOne() {
  if (viewMode.value === 'list') {
    gridApi.reload();
  } else {
    cardListRef.value?.reload?.();
  }
}

/**
 * 传给弹窗子组件的 gridApi 代理
 * 发货/退款等弹窗内部只会调 reload()/query() 刷新列表，
 * 卡片模式下需要转发给卡片列表，故不能直接把 gridApi 传进去
 */
const gridApiProxy = {
  reload: () => refreshCurrentViewFromPageOne(),
  query: () => refreshCurrentView(),
};

// 首屏是卡片模式时 grid 不渲染（ajax query 不会触发），顶部销售统计需要手动拉一次
onMounted(() => {
  if (viewMode.value === 'card') {
    saleAmount(searchValues.value);
  }
});
const [FormModal, formModalApi] = useVbenModal({
  connectedComponent: FormModalDemo,
});
const [Modal, modalApi] = useVbenModal({
  connectedComponent: DetailModal,
});
/** 独立物流动态弹窗：只拉 express-detail，与订单详情解耦 */
const [LogisticsModalComp, logisticsModalApi] = useVbenModal({
  connectedComponent: LogisticsModal,
});
const [RefundModal, RefundModalApi] = useVbenModal({
  connectedComponent: Refund,
});

const [ExportModal, exportModalApi] = useVbenModal({
  connectedComponent: ProductOrderExportModal,
});

const infoModal = (data: Record<string, any> = {}) => {
  modalApi.setData({
    // 带 id 走详情接口拿到 packages；values 作首屏兜底
    id: data?.id,
    values: data,
    gridApi: gridApiProxy,
    // 详情内「发本包裹」：关详情后打开发货弹窗（仅平台包会传 0）
    onShipPackage: (warehouseId: number) => {
      modalApi.close();
      wareSend(data, warehouseId);
    },
  });
  modalApi.open();
};

/**
 * 打开物流动态：仅传 order_id，弹窗内单独请求物流接口
 */
const openLogisticsModal = (data: Record<string, any> = {}) => {
  logisticsModalApi.setData({
    order_id: data?.id,
  });
  logisticsModalApi.open();
};

/**
 * 打开发货弹窗。
 * 列表不传 warehouse_id（后端平台默认 0）；详情按包发时仅传合法非负整数。
 * 注意：勿用 bind(null,row)，table-action 的 click 会把事件当成第 2 参污染 warehouse_id。
 */
const wareSend = (data: Record<string, any> = {}, warehouseId?: number) => {
  const values: Record<string, any> = {
    order_id: data?.id,
    order_no: data?.order_no,
  };
  if (
    warehouseId !== undefined &&
    warehouseId !== null &&
    Number.isFinite(Number(warehouseId)) &&
    Number(warehouseId) >= 0
  ) {
    values.warehouse_id = Number(warehouseId);
  }
  formModalApi.setData({
    values,
    gridApi: gridApiProxy,
  });
  formModalApi.open();
};
const expandAll = () => {
  gridApi.grid?.setAllRowExpand(true);
};

const collapseAll = () => {
  gridApi.grid?.setAllRowExpand(false);
};
const overviewItems = ref<StatIslandItem[]>([]);
const income = ref(0);
const total = ref(0);
/** 按当前筛选条件刷新顶部销售金额/收益（支持门店多选 store_ids，双视图共用） */
const saleAmount = (formValues?: Record<string, any>) => {
  const values = formValues ?? searchValues.value ?? {};
  saleAmountApi({
    search_time: values.search_time,
    store_ids: values.store_ids,
    id: Array.isArray(values.store_ids) && values.store_ids.length === 1
      ? values.store_ids[0]
      : undefined,
  }).then((res) => {
    income.value = res.income;
    total.value = res.total;
    // 紧凑统计岛（设计对齐提现管理），替代原 AnalysisOverview 大卡
    overviewItems.value = [
      {
        key: 'total',
        label: '销售金额',
        value: total.value,
        icon: 'lucide:trending-up',
      },
      {
        key: 'income',
        label: '我的收益',
        value: income.value,
        icon: 'lucide:wallet',
        emphasize: true,
      },
    ];
  });
};

const [PrescriptionDetailModal, PrescriptionDetailModalApi] = useVbenModal({
  connectedComponent: PrescriptionDetail,
});

const [DoctorCardModals, DoctorCardModalApi] = useVbenModal({
  connectedComponent: DoctorCardModal,
});

const [StoreCardModalComp, StoreCardModalApi] = useVbenModal({
  connectedComponent: StoreCardModal,
});

function openStoreCard(storeId?: number) {
  if (!storeId) return;
  StoreCardModalApi.setData({ storeId: Number(storeId) });
  StoreCardModalApi.open();
}

const [PatientsModal, PatientsModalApi] = useVbenModal({
  connectedComponent: WxUserPatientsModal,
});

const [PatientDetailModal, PatientDetailModalApi] = useVbenModal({
  connectedComponent: WxUserPatientDetailModal,
});

/** 从订单列表以只读模式打开医生档案 */
function showOrderDoctorCard(row: Record<string, any>) {
  const doctor = row.doctor;
  if (!doctor?.id && !row.su_id && !doctor?.su_id) {
    message.warning('该订单无关联医生');
    return;
  }
  DoctorCardModalApi.setData({
    id: doctor?.id,
    su_id: row.su_id ?? doctor?.su_id,
    readonly: true,
  });
  DoctorCardModalApi.open();
}

/** 点下单用户 → 该用户下就诊人列表 Modal */
function openOrderUserPatients(payload: {
  userId: number;
  nickname: string;
  avatarurl: string;
}) {
  if (!payload?.userId) {
    message.warning('缺少用户信息');
    return;
  }
  PatientsModalApi.setData({
    userId: payload.userId,
    nickname: payload.nickname,
    avatarurl: payload.avatarurl,
  });
  PatientsModalApi.open();
}

/** 点就诊人 → 详情 Modal */
function openOrderPatient(payload: { upId: number; patientName: string }) {
  if (!payload?.upId) {
    message.warning('缺少就诊人信息');
    return;
  }
  PatientDetailModalApi.setData({
    upId: payload.upId,
    patientName: payload.patientName,
  });
  PatientDetailModalApi.open();
}

const [TraceDrawer, traceDrawerApi] = useVbenDrawer({
  connectedComponent: OrderTraceDrawer,
});

const [ChinaErpSyncDrawer, chinaErpSyncDrawerApi] = useVbenDrawer({
  connectedComponent: ChinaErpSyncLogDrawer,
});

const [PercentAdjustDrawer, percentAdjustDrawerApi] = useVbenDrawer({
  connectedComponent: OrderPricePercentAdjustDrawer,
});

const priceAdjustMeta = ref({
  quickOptions: [] as QuickDiscountOption[],
});

async function loadPriceAdjustMeta() {
  const cfg = await getOrderPriceAdjustConfig();
  priceAdjustMeta.value = {
    quickOptions: normalizeQuickOptions(cfg?.order_discount_quick_options),
  };
}

void loadPriceAdjustMeta();

function canRowPercentAdjust(row: Record<string, any>) {
  return (
    Number(row?.is_pay) !== 1 &&
    Number(row?.store?.enable_order_price_percent_adjust) === 1
  );
}

async function openOrderPercentAdjust(row: Record<string, any>) {
  if (!canRowPercentAdjust(row)) return;
  let discount = Number(row.price_discount ?? 100);
  try {
    const detail = await getOrderInfo(row.id);
    discount = Number(detail?.price_discount ?? discount);
  } catch {
    // 列表字段缺失时沿用行内值
  }
  percentAdjustDrawerApi.setData({
    stage: 'post_order',
    priceDiscount: discount,
    price_discount: discount,
    productOrderId: row.id,
    quickOptions: normalizeQuickOptions(priceAdjustMeta.value.quickOptions),
    onSuccess: () => {
      refreshCurrentViewFromPageOne();
    },
  });
  percentAdjustDrawerApi.open();
}

function openChinaErpSyncLog(row: Record<string, any>) {
  chinaErpSyncDrawerApi.setData({
    order_id: row.id,
    order_no: row.order_no,
    is_sync_erp: row.is_sync_erp,
  });
  chinaErpSyncDrawerApi.open();
}

function openOrderTrace(row: Record<string, any>) {
  traceDrawerApi.setData({
    scene: 'product',
    order_id: row.id,
    order_no: row.order_no,
  });
  traceDrawerApi.open();
}

function handleSimulatePay(row: Record<string, any>) {
  AntdModal.confirm({
    title: '模拟支付',
    content: `确认为订单 ${row.order_no} 模拟易票联支付回调？`,
    okText: '确认',
    cancelText: '取消',
    onOk: async () => {
      await simulatePayApi({ order_type: 'product', order_id: row.id });
      message.success('模拟支付成功');
      await refreshCurrentView();
    },
  });
}

/**
 * 超管手动确认收货 / 重试解冻（自动确认队列失败后的人工补偿）
 * 仅 Super Admin 可见；待收货走完整签收，已确认收货仅重试解冻
 */
function handleRetryConfirmReceive(row: Record<string, any>) {
  const isWaitReceive = Number(row.status) === 2;
  AntdModal.confirm({
    title: isWaitReceive ? '确认收货' : '重试解冻',
    content: isWaitReceive
      ? `确认为订单 ${row.order_no} 手动确认收货？将更新为已确认收货并解冻供应商/配送仓分账冻结。`
      : `订单 ${row.order_no} 已确认收货，是否重试解冻分账冻结？（幂等，不会重复加账）`,
    okText: '确认',
    cancelText: '取消',
    onOk: async () => {
      const res = await retryConfirmReceiveApi({ order_id: Number(row.id) });
      message.success(
        res?.message || (isWaitReceive ? '确认收货成功' : '解冻重试成功'),
      );
      await refreshCurrentView();
    },
  });
}

const accruingOrderIds = ref<number[]>([]);
const reversingOrderIds = ref<number[]>([]);

async function handleAccrueSalesperson(row: Record<string, any>) {
  if (accruingOrderIds.value.includes(row.id)) {
    return;
  }
  accruingOrderIds.value.push(row.id);
  try {
    await accrueSalespersonCommissionApi({ order_id: row.id });
    message.success('分成成功');
    await refreshCurrentView();
  } catch (error: any) {
    message.error(error?.message || '分成失败');
  } finally {
    accruingOrderIds.value = accruingOrderIds.value.filter((id) => id !== row.id);
  }
}

/** 手动退回推广员分成 */
async function handleReverseSalesperson(row: Record<string, any>, salespersonId?: number) {
  const spId = salespersonId ?? row.salesperson_id;
  if (!spId || reversingOrderIds.value.includes(row.id)) {
    return;
  }
  reversingOrderIds.value.push(row.id);
  try {
    await reverseSalespersonCommissionApi({
      order_id: row.id,
      store_id: row.store_id || 0,
      salesperson_id: spId,
    });
    message.success('退回分成成功');
    await refreshCurrentView();
  } catch (error: any) {
    message.error(error?.message || '退回分成失败');
  } finally {
    reversingOrderIds.value = reversingOrderIds.value.filter((id) => id !== row.id);
  }
}

function isNegativeCommission(amount?: string | number) {
  return Number(amount ?? 0) < 0;
}

function formatExpressAddress(row: Record<string, any>) {
  if (Number(row.delivery_method) === 1) {
    return row.store?.position || row.store?.name || '到店自提';
  }
  const region = row.address?.region || row.express_region || '';
  const detail = row.address?.detail_address || row.express_address || '';
  return [region, detail].filter(Boolean).join(' ') || '—';
}

function salespersonStatusColor(text: string) {
  if (text === '已分成') return 'success';
  if (text === '未分成') return 'warning';
  if (text === '已冲销') return 'warning';
  if (text === '未支付') return 'default';
  return 'default';
}

function formatCommissionRecordDetail(record: Record<string, any>) {
  const typeText = record.record_type_text ? `${record.record_type_text} · ` : '';
  const path = record.commission_path_text || '—';
  const rule = record.commission_rule_text || '—';
  if (record.commission_mode_text === '比例分成') {
    return `${typeText}${path} · ${rule}`;
  }
  return `${typeText}${path} · ${record.commission_mode_text || '固定单价'} · ${rule}`;
}

const openPrescriptionDetail = (values: number) => {
  // 打开西药处方模态框逻辑
  PrescriptionDetailModalApi.setData({
    values,
  });
  PrescriptionDetailModalApi.open();
};

/**
 * 打开导出弹窗
 */
const openExportModal = () => {
  exportModalApi.open();
};

const openRefundModal = (id: number) => {
  RefundModalApi.setData({
    values: {
      order_id: id,
    },
    gridApi: gridApiProxy,
  });
  RefundModalApi.open();
};

/** 取消待支付订单 */
async function handleCancelOrder(row: Record<string, any>) {
  try {
    await cancelOrderApi({ order_id: row.id });
    message.success('订单已取消');
    await refreshCurrentView();
  } catch (error: any) {
    message.error(error?.message || '取消失败');
  }
}

/** 订单页改仓弹窗状态（按药分别选仓） */
const changeWhOpen = ref(false);
const changeWhSubmitting = ref(false);
const changeWhLoading = ref(false);
const changeWhOrderId = ref(0);
const changeWhFromId = ref(0);
const changeWhFromName = ref('');
/** 弹窗内药品行：每药独立选 to_warehouse_id */
const changeWhDrugRows = ref<
  Array<{
    order_item_id: number;
    drug_id: number;
    drug_name: string;
    image: string;
    specification: string;
    number: number;
    from_warehouse_id: number;
    to_warehouse_id: number;
    options: Array<{
      warehouse_id: number;
      warehouse_name: string;
      quote: string | null;
      disabled?: boolean;
    }>;
  }>
>([]);

const changeWhPendingCount = computed(
  () =>
    changeWhDrugRows.value.filter(
      (r) => Number(r.to_warehouse_id) !== Number(r.from_warehouse_id),
    ).length,
);

/**
 * 为单药构造仓卡片：本仓库 + 该药 options（排除不可用）
 */
function buildDrugWarehouseCards(
  drugOptions: any[],
  _fromWarehouseId: number,
): Array<{
  warehouse_id: number;
  warehouse_name: string;
  quote: string | null;
  disabled?: boolean;
}> {
  const local = {
    warehouse_id: 0,
    warehouse_name: '萧康医药本仓库',
    quote: null as string | null,
  };
  const seen = new Set<number>([0]);
  const cards = [local];
  for (const opt of drugOptions || []) {
    const id = Number(opt?.warehouse_id ?? 0);
    if (id <= 0 || seen.has(id)) continue;
    seen.add(id);
    cards.push({
      warehouse_id: id,
      warehouse_name: String(opt?.warehouse_name ?? `仓库#${id}`),
      quote: String(opt?.quote ?? '0'),
    });
  }
  return cards;
}

/**
 * 点击仓库 Tag：打开按药改仓弹窗
 */
async function openChangeWarehouse(
  row: Record<string, any>,
  wh: { id: number; name: string },
) {
  changeWhOrderId.value = Number(row.id ?? 0);
  changeWhFromId.value = Number(wh?.id ?? 0);
  changeWhFromName.value = String(wh?.name ?? '');
  changeWhDrugRows.value = [];
  changeWhOpen.value = true;
  changeWhLoading.value = true;
  try {
    const items = Array.isArray(row.product_order_items)
      ? row.product_order_items
      : [];
    const fromId = changeWhFromId.value;
    const scoped = items.filter((it: any) => {
      if (
        it?.delivery_warehouse_id === undefined ||
        it?.delivery_warehouse_id === null
      ) {
        return true;
      }
      const wid = Number(it.delivery_warehouse_id ?? 0);
      return fromId > 0 ? wid === fromId : wid <= 0;
    });
    const list = scoped.length ? scoped : items;
    const drugIds = [
      ...new Set(
        list
          .map((it: any) => Number(it?.drug_id ?? 0))
          .filter((id: number) => id > 0),
      ),
    ];
    if (list.length === 0) {
      message.warning('该仓库下没有可改仓的药品');
      return;
    }
    const res =
      drugIds.length > 0
        ? await getDeliveryWarehouseOptionsByDrugs({ drug_ids: drugIds })
        : {};
    const map = (res || {}) as Record<string, any[]>;
    changeWhDrugRows.value = list.map((it: any) => {
      const drugId = Number(it?.drug_id ?? 0);
      const itemId = Number(it?.id ?? 0);
      const opts = map[String(drugId)] || map[drugId] || [];
      const fromWid = Number(it?.delivery_warehouse_id ?? fromId ?? 0);
      return {
        order_item_id: itemId,
        drug_id: drugId,
        drug_name: String(it?.drug_name || it?.name || `药品#${drugId}`),
        image: String(it?.image || it?.drug?.image || ''),
        specification: String(
          it?.specification || it?.drug?.specification || '',
        ),
        number: Number(it?.number ?? it?.select_number ?? 1),
        from_warehouse_id: fromWid,
        // 默认仍为当前仓，用户需主动点选目标仓
        to_warehouse_id: fromWid,
        options: buildDrugWarehouseCards(opts, fromWid),
      };
    });
  } catch (error: any) {
    message.error(error?.message || '加载配送仓库失败');
  } finally {
    changeWhLoading.value = false;
  }
}

/** 确认按药改仓 */
async function submitChangeWarehouse() {
  const items = changeWhDrugRows.value
    .filter((r) => Number(r.to_warehouse_id) !== Number(r.from_warehouse_id))
    .map((r) => ({
      order_item_id: r.order_item_id,
      to_warehouse_id: Number(r.to_warehouse_id),
    }));
  if (items.length === 0) {
    message.warning('请至少为一种药品选择新的配送仓库');
    return;
  }
  changeWhSubmitting.value = true;
  try {
    await changeDeliveryWarehouseApi({
      order_id: changeWhOrderId.value,
      from_warehouse_id: changeWhFromId.value,
      items,
    });
    message.success(`改仓成功（${items.length} 种药品）`);
    changeWhOpen.value = false;
    await refreshCurrentView();
  } catch (error: any) {
    message.error(error?.message || '改仓失败');
  } finally {
    changeWhSubmitting.value = false;
  }
}

const toggleFreeShipping = async (row: any, checked: boolean) => {
  try {
    const res = await updateFreeShipping({ id: row.id, is_free_shipping: checked ? 1 : 0 });
    row.is_free_shipping = res.is_free_shipping;
    row.trans_expenses = res.trans_expenses;
    row.total_pay_price = res.total_pay_price;
    message.success('更新成功');
  } catch (error: any) {
    message.error(error.message || '更新失败');
  }
};

const verifyOpen = ref(false);
const verifyLoading = ref(false);
const verifyRows = ref<any[]>([]);
const verifyMeta = ref({ minutes: 10, count: 0, since: 0 });
const verifyMismatchOnly = ref(false);

const verifyColumns = [
  { title: '订单ID', dataIndex: 'order_id', key: 'order_id', width: 90 },
  { title: '订单号', dataIndex: 'order_no', key: 'order_no', width: 200, ellipsis: true },
  { title: '药品价(表)', dataIndex: 'items_price', key: 'items_price', width: 100 },
  { title: '药品价(算)', dataIndex: 'expected_items_price', key: 'exp_items', width: 100 },
  { title: '药品', key: 'items_match', width: 80 },
  { title: '应付(表)', dataIndex: 'total_pay_price', key: 'total_pay', width: 100 },
  { title: '应付(算)', dataIndex: 'expected_total_pay_price', key: 'exp_total', width: 100 },
  { title: '应付', key: 'total_match', width: 80 },
  { title: '全OK', key: 'ok', width: 70 },
  { title: '药品差', dataIndex: 'items_diff', key: 'items_diff', width: 80 },
  { title: '应付差', dataIndex: 'total_diff', key: 'total_diff', width: 80 },
];

const fetchOrderAmountVerify = async () => {
  verifyLoading.value = true;
  try {
    const res = await getVerifyRecentOrderAmounts({
      minutes: 10,
      mismatch_only: verifyMismatchOnly.value ? 1 : 0,
    });
    verifyMeta.value = {
      minutes: res.minutes,
      count: res.count,
      since: res.since,
    };
    verifyRows.value = res.orders ?? [];
    verifyOpen.value = true;
  } finally {
    verifyLoading.value = false;
  }
};

// 金额核对入口暂时下线（工具栏按钮已注释），恢复入口时一并取消本函数注释
// const openOrderAmountVerify = () => {
//   verifyMismatchOnly.value = false;
//   fetchOrderAmountVerify();
// };

/**
 * 列表槽用元数据取值 helper：v-if 双重索引无法类型收窄，统一在这里兜底
 */
function rowPrescriptionTypeMeta(row: Record<string, any>) {
  return PRESCRIPTION_TYPE_MAP[Number(row?.prescription_type)] ?? null;
}
function rowStatusMeta(row: Record<string, any>) {
  return ORDER_STATUS_MAP[Number(row?.status)] ?? null;
}

/**
 * 构造行操作（列表 #action 槽与卡片 footer 共用同一份定义）
 * 返回 TableAction 的 actions/dropDownActions，保证双视图按钮、权限（auth）、显隐条件完全一致
 */
function buildRowActions(row: Record<string, any>): {
  actions: ActionItem[];
  dropDownActions: ActionItem[];
} {
  return {
    actions: [
      {
        label: '详情',
        type: 'link',
        icon: 'marketeq:eye',
        size: 'small',
        onClick: infoModal.bind(null, row),
      },
      {
        label: '物流动态',
        type: 'link',
        icon: 'mdi:truck-delivery-outline',
        size: 'small',
        // 上门快递且已支付、非取消/待支付：可单独查看物流
        ifShow:
          row.delivery_method === 0 &&
          row.is_pay === 1 &&
          row.status !== 0 &&
          row.status !== 9,
        onClick: openLogisticsModal.bind(null, row),
      },
      {
        label: '溯源',
        type: 'link',
        icon: 'mdi:timeline-text',
        size: 'small',
        onClick: openOrderTrace.bind(null, row),
      },
      {
        label: '处方',
        type: 'link',
        icon: 'marketeq:eye',
        ifShow: row.order_type !== 2 && row.order_type !== 3,
        onClick: openPrescriptionDetail.bind(null, row.p_id),
      },
      {
        label: '模拟支付',
        type: 'link',
        icon: 'mdi:cash-check',
        auth: ['Super Admin'],
        ifShow: row.is_pay === 0,
        onClick: handleSimulatePay.bind(null, row),
      },
      {
        // 仅超管：待收货确认收货 / 已确认收货重试解冻
        label: Number(row.status) === 2 ? '确认收货' : '重试解冻',
        type: 'link',
        icon: 'mdi:package-check',
        auth: ['Super Admin'],
        ifShow:
          Number(row.is_pay) === 1 &&
          Number(row.cancel_status) === 0 &&
          Number(row.refund_status) === 0 &&
          (Number(row.status) === 2 || Number(row.status) === 7),
        onClick: handleRetryConfirmReceive.bind(null, row),
      },
      {
        label: '发货',
        type: 'link',
        icon: 'ri:send-plane-fill',
        auth: ['Super Admin', 'Admin'],
        onClick: () => wareSend(row),
      },
    ],
    dropDownActions: [
      {
        label: '取消订单',
        type: 'link',
        icon: 'mdi:cancel',
        auth: ['Super Admin', 'Admin'],
        ifShow:
          row.status === 0 && row.is_pay === 0 && row.cancel_status === 0,
        popConfirm: {
          title: '确定取消该待支付订单吗？',
          confirm: handleCancelOrder.bind(null, row),
        },
      },
      {
        label: '退款',
        type: 'link',
        icon: 'mingcute:refund-dollar-fill',
        auth: ['Super Admin', 'Admin'],
        ifShow: row.is_pay === 1,
        onClick: openRefundModal.bind(null, row.id),
      },
    ],
  };
}
</script>

<template>
  <Page auto-content-height title="订单管理">
    <FormModal />
    <Modal />
    <LogisticsModalComp />
    <AntdModal
      v-model:open="verifyOpen"
      title="近10分钟订单金额校验"
      width="min(1100px, 96vw)"
      :footer="null"
      destroy-on-close
    >
      <Space direction="vertical" style="width: 100%; margin-bottom: 12px">
        <div>
          与明细重算口径同调价/分账；已检 {{ verifyMeta.count }} 条；since={{ verifyMeta.since }}（Unix）
        </div>
        <Space wrap>
          <span>仅显示不一致</span>
          <Switch v-model:checked="verifyMismatchOnly" @update:checked="fetchOrderAmountVerify" />
          <Button :loading="verifyLoading" type="primary" @click="fetchOrderAmountVerify">
            重新检测
          </Button>
        </Space>
      </Space>
      <Table
        :columns="verifyColumns"
        :data-source="verifyRows"
        :loading="verifyLoading"
        :pagination="false"
        :scroll="{ x: 1200 }"
        size="small"
        row-key="order_id"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'items_match'">
            <Tag :color="record.items_match ? 'success' : 'error'">
              {{ record.items_match ? '一致' : '否' }}
            </Tag>
          </template>
          <template v-else-if="column.key === 'total_match'">
            <Tag :color="record.total_match ? 'success' : 'error'">
              {{ record.total_match ? '一致' : '否' }}
            </Tag>
          </template>
          <template v-else-if="column.key === 'ok'">
            <Tag :color="record.ok ? 'success' : 'error'">
              {{ record.ok ? '是' : '否' }}
            </Tag>
          </template>
        </template>
      </Table>
    </AntdModal>
    <RefundModal />
    <DoctorCardModals />
    <StoreCardModalComp />
    <PatientsModal />
    <PatientDetailModal />
    <ExportModal />
    <PrescriptionDetailModal />
    <TraceDrawer />
    <ChinaErpSyncDrawer @synced="() => refreshCurrentView()" />
    <!-- 紧凑统计岛：一行 4 格（仅占 2 格），设计对齐提现管理账户卡统计岛 -->
    <StatIslands class="mb-3" :items="overviewItems" :columns="4" />
    <!-- 顶部统一搜索（双视图共用，替代原 grid 内嵌表单） -->
    <div class="mb-3 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card,var(--background)))] p-3">
      <SearchForm />
    </div>
    <!-- 视图切换：列表 / 卡片看板；卡片模式下补充导出入口（列表模式导出在表格工具栏） -->
    <div class="mb-3 flex items-center justify-between gap-3">
      <ViewModeSwitch v-model="viewMode" />
      <Button v-if="viewMode === 'card'" type="primary" @click="openExportModal">
        导出
      </Button>
    </div>
    <Grid v-if="viewMode === 'list'">
      <template #toolbar-actions>
        <TableAction
          :flex="false"
          :actions="[
            // {
            //   label: '校验近10分钟金额',
            //   type: 'default',
            //   icon: 'ix:search-check',
            //   onClick: openOrderAmountVerify.bind(null),
            // },
            {
              label: '导出',
              type: 'primary',
              icon: 'ix:export-check',
              // auth: ['超级西（中成）药', 'sys:user:save'],
              onClick: openExportModal.bind(null),
            },
            {
              label: '展开全部',
              type: 'primary',
              // auth: ['超级菜单', 'sys:user:save'],
              onClick: expandAll.bind(null),
            },
            {
              label: '收起全部',
              type: 'primary',
              // auth: ['超级菜单', 'sys:user:save'],
              onClick: collapseAll.bind(null),
            },
          ]"
          :drop-down-actions="[]"
        >
          <template #more>
            <Button style="margin-left: 16px">
              批量操作
              <Icon icon="ant-design:down-outlined" />
            </Button>
          </template>
        </TableAction>
      </template>
      <template #order-user-info="{ row }">
        <OrderUserInfoCell
          :row="row"
          @open-doctor="showOrderDoctorCard"
          @open-user-patients="openOrderUserPatients"
          @open-patient="openOrderPatient"
        />
      </template>
      <template #order-store="{ row }">
        <div class="leading-snug">
          <div class="mb-1 flex flex-wrap items-center gap-1">
            <Tag v-if="row.is_online === 1" color="blue">在线问诊</Tag>
            <Tag v-else-if="row.is_online === 2" color="green">在线复诊（诊所）</Tag>
            <Tag v-else-if="row.is_online === 3" color="green">在线复诊（药店）</Tag>
            <Tag v-else color="default">线下就诊</Tag>
            <!-- 代支付标识放订单号列：状态列过窄且 showOverflow 会裁切底部 Tag -->
            <Tag
              v-if="row.is_proxy_pay || Number(row.pay_user_type) === 2"
              color="magenta"
            >
              代支付
            </Tag>
          </div>
          <div class="font-medium">{{ row.order_no }}</div>
          <div class="text-xs text-[hsl(var(--muted-foreground))]">
            <Button
              v-if="row.store?.id"
              class="!h-auto max-w-[xxx] whitespace-normal break-words !px-0 text-left"
              size="small"
              type="link"
              @click="openStoreCard(row.store.id)"
            >
              {{ row.store?.name || '—' }}
            </Button>
            <span v-else>{{ row.store?.name || '—' }}</span>
          </div>
          <div class="text-xs text-[hsl(var(--muted-foreground))]">
            下单时间： {{ row.created_at || '—' }}
          </div>
        </div>
      </template>
      <template #express-info="{ row }">
        <div class="space-y-0.5 text-sm leading-snug">
          <div>
            {{
              row.address?.name ||
              row.express_name ||
              row.patient ||
              row.cancel_remark ||
              '—'
            }}
          </div>
          <div class="text-gray-500">
            <SensitiveText
              :record="row.address"
              field="mobile"
              :fallback="{ record: row, field: 'patient_mobile' }"
            />
          </div>
          <div class="text-xs text-gray-500">{{ formatExpressAddress(row) }}</div>
        </div>
      </template>
      <!-- 患者配送仓库：点击 Tag 可改仓（本仓库 / 配送仓） -->
      <template #delivery-warehouses="{ row }">
        <div
          v-if="Array.isArray(row.delivery_warehouses) && row.delivery_warehouses.length"
          class="flex flex-wrap gap-1"
        >
          <Tag
            v-for="wh in row.delivery_warehouses"
            :key="wh.id"
            color="processing"
            class="cursor-pointer"
            @click="openChangeWarehouse(row, wh)"
          >
            {{ wh.name }}
          </Tag>
        </div>
        <span v-else class="text-[hsl(var(--muted-foreground))]">-</span>
      </template>
      <template #price-info="{ row }">
        <div class="space-y-0.5 text-sm leading-snug">
          <div>
            药品：
            <Button
              v-if="canRowPercentAdjust(row)"
              class="!h-auto !px-0 !py-0"
              type="link"
              @click="openOrderPercentAdjust(row)"
            >
              ¥{{ row.items_price ?? '0.00' }}
            </Button>
            <template v-else>¥{{ row.items_price ?? '0.00' }}</template>
          </div>
          <div>
            支付：
            <Button
              v-if="canRowPercentAdjust(row)"
              class="!h-auto !px-0 !py-0"
              type="link"
              @click="openOrderPercentAdjust(row)"
            >
              ¥{{ row.total_pay_price ?? '0.00' }}
            </Button>
            <template v-else>¥{{ row.total_pay_price ?? '0.00' }}</template>
          </div>
          <div>
            挂号：
            <Button
              v-if="row.register_order_no"
              class="!h-auto !px-0 !py-0"
              type="link"
              @click="goRegisterOrder(row)"
            >
              {{ formatRegisterAmount(row) }}
            </Button>
            <span v-else>{{ formatRegisterAmount(row) }}</span>
          </div>
        </div>
      </template>
      <template #salesperson="{ row }">
        <div v-if="row.salesperson?.id" class="space-y-1">
          <Popover trigger="click" placement="topLeft" overlay-class-name="salesperson-commission-popover">
            <template #title>
              <span class="font-semibold">推广员分成</span>
            </template>
            <template #content>
              <div class="w-80 space-y-3 text-sm">
                <div class="rounded-lg bg-gray-50 p-3">
                  <div class="mb-2 flex items-center justify-between">
                    <span class="font-semibold text-gray-800">直推推广员</span>
                    <span class="font-medium text-orange-600">
                      ¥{{ row.salesperson.commission_amount || '0.00' }}
                    </span>
                  </div>
                  <div class="mb-1 text-gray-600">{{ row.salesperson.nick_name || '—' }}</div>
                  <div
                    v-if="!(row.salesperson.commission_records?.length > 0)"
                    class="text-gray-400"
                  >
                    暂无分成明细
                  </div>
                  <div
                    v-for="(record, idx) in row.salesperson.commission_records || []"
                    :key="'d-' + idx"
                    class="flex items-start justify-between border-b border-gray-100 py-2 last:border-0"
                  >
                    <div class="min-w-0 flex-1 pr-2">
                      <div class="font-medium text-gray-800">{{ record.drug_name || '—' }}</div>
                      <div class="text-xs text-gray-500">
                        {{ formatCommissionRecordDetail(record) }}
                      </div>
                    </div>
                    <div
                      class="shrink-0 font-medium"
                      :class="isNegativeCommission(record.commission_amount) ? 'text-red-500' : 'text-orange-600'"
                    >
                      ¥{{ record.commission_amount }}
                    </div>
                  </div>
                  <div v-if="row.salesperson.can_reverse_commission" class="mt-2 text-right">
                    <Popconfirm
                      title="确认退回直推推广员分成？"
                      @confirm="handleReverseSalesperson(row)"
                    >
                      <Button
                        type="link"
                        size="small"
                        danger
                        class="!h-auto !px-0 !py-0"
                        :loading="reversingOrderIds.includes(row.id)"
                      >
                        退回分成
                      </Button>
                    </Popconfirm>
                  </div>
                </div>
                <div
                  v-if="canViewInviterCommission && row.salesperson.has_inviter && row.salesperson.inviter"
                  class="rounded-lg bg-orange-50 p-3"
                >
                  <div class="mb-2 flex items-center justify-between">
                    <span class="font-semibold text-gray-800">
                      邀请人（{{ row.salesperson.inviter.inviter_split }}%）
                    </span>
                    <span class="font-medium text-orange-600">
                      ¥{{ row.salesperson.inviter.commission_amount || '0.00' }}
                    </span>
                  </div>
                  <div class="mb-1 text-gray-600">{{ row.salesperson.inviter.nick_name || '—' }}</div>
                  <div
                    v-if="!(row.salesperson.inviter.commission_records?.length > 0)"
                    class="text-gray-400"
                  >
                    暂无邀请分成明细
                  </div>
                  <div
                    v-for="(record, idx) in row.salesperson.inviter.commission_records || []"
                    :key="'i-' + idx"
                    class="flex items-start justify-between border-b border-orange-100 py-2 last:border-0"
                  >
                    <div class="min-w-0 flex-1 pr-2">
                      <div class="font-medium text-gray-800">{{ record.drug_name || '—' }}</div>
                      <div class="text-xs text-gray-500">
                        {{ formatCommissionRecordDetail(record) }}
                      </div>
                    </div>
                    <div
                      class="shrink-0 font-medium"
                      :class="isNegativeCommission(record.commission_amount) ? 'text-red-500' : 'text-orange-600'"
                    >
                      ¥{{ record.commission_amount }}
                    </div>
                  </div>
                  <div
                    v-if="canViewInviterCommission && row.salesperson.inviter?.can_reverse_commission"
                    class="mt-2 text-right"
                  >
                    <Popconfirm
                      title="确认退回邀请人分成？"
                      @confirm="handleReverseSalesperson(row, row.salesperson.inviter.id)"
                    >
                      <Button
                        type="link"
                        size="small"
                        danger
                        class="!h-auto !px-0 !py-0"
                        :loading="reversingOrderIds.includes(row.id)"
                      >
                        退回邀请分成
                      </Button>
                    </Popconfirm>
                  </div>
                </div>
              </div>
            </template>
            <div class="flex cursor-pointer items-center gap-2 hover:opacity-80">
              <Image
                :src="row.salesperson.avatar || '/img/user-default-avatar.png'"
                :width="32"
                :height="32"
                class="shrink-0 rounded-full object-cover"
              />
              <div class="min-w-0 flex-1">
                <div class="flex items-center gap-1.5">
                  <span class="truncate text-sm font-medium">{{
                    row.salesperson.nick_name || '—'
                  }}</span>
                  <Tag
                    :color="salespersonStatusColor(row.salesperson.commission_status_text)"
                    class="!m-0 shrink-0"
                  >
                    {{ row.salesperson.commission_status_text }}
                  </Tag>
                </div>
                <div class="text-sm font-medium text-orange-600">
                  ¥{{ row.salesperson.commission_amount || '0.00' }}
                </div>
              </div>
            </div>
          </Popover>
          <Button
            v-if="
              row.is_pay === 1 &&
              row.salesperson_id > 0 &&
              !row.salesperson.has_commission
            "
            class="!h-auto !px-0 !py-0"
            type="link"
            size="small"
            :loading="accruingOrderIds.includes(row.id)"
            @click="handleAccrueSalesperson(row)"
          >
            立即分成
          </Button>
          <Popconfirm
            v-else-if="row.is_pay === 1 && row.salesperson.can_reverse_commission"
            title="确认退回推广员分成？"
            @confirm="handleReverseSalesperson(row)"
          >
            <Button
              class="!h-auto !px-0 !py-0"
              type="link"
              size="small"
              danger
              :loading="reversingOrderIds.includes(row.id)"
            >
              退回分成
            </Button>
          </Popconfirm>
        </div>
        <span v-else class="text-sm text-gray-500">
          {{ row.salesperson?.commission_status_text || '无推广员' }}
        </span>
      </template>
      <template #pay-time="{ row }">
        {{ row?.pay_time || '未支付' }}
      </template>
      <template #is-sync-erp="{ row }">
        <template v-if="row.prescription_type === 1">
          <Tag v-if="row.is_sync_erp === 1" color="green">已同步</Tag>
          <Tag v-else color="red">未同步</Tag>
          <Button
            class="!h-auto !px-0 !py-0"
            size="small"
            type="link"
            @click="openChinaErpSyncLog(row)"
          >
            记录
          </Button>
        </template>
        <template v-else>
          <Tag v-if="row.is_sync_erp === 1" color="green">已同步</Tag>
          <Tag v-else color="red">未同步</Tag>
        </template>
      </template>
      <template #is-free-shipping="{ row }">
        <Switch
          :checked="row.is_free_shipping === 1"
          checked-children="包邮"
          un-checked-children="不包邮"
          @change="(checked: any) => toggleFreeShipping(row, Boolean(checked))"
        />
      </template>
      <template #is-online="{ row }">
        <Tag v-if="row.is_online === 1" color="blue">在线问诊</Tag>
        <Tag v-else-if="row.is_online === 2" color="green">在线复诊（诊所）</Tag>
        <Tag v-else-if="row.is_online === 3" color="green">在线复诊（药店）</Tag>
        <Tag v-else color="default">线下就诊</Tag>
      </template>
      <template #delivery-method="{ row }">
        <!-- 订单类型：非处方订单（order_type=2）显示订单类型；其余按处方类型全量映射（含特色方 0） -->
        <div v-if="row.order_type === 2">
          <Tag color="yellow">
            {{ ORDER_TYPE_MAP[row.order_type]?.label || '预约购药订单' }}
          </Tag>
        </div>
        <div v-else>
          <Tag v-if="rowPrescriptionTypeMeta(row)" :color="rowPrescriptionTypeMeta(row)!.color">
            处方订单【{{ rowPrescriptionTypeMeta(row)!.label }}】
          </Tag>
        </div>
        <div class="mt-3">
          <Tag v-if="row.delivery_method === 1" color="blue">【到店自提】</Tag>
          <Tag v-else-if="row.delivery_method === 0" color="green">
            【上门快递】
          </Tag>
        </div>
        <div class="mt-3">
          <Tag v-if="rowStatusMeta(row)" :color="rowStatusMeta(row)!.color">
            {{ rowStatusMeta(row)!.label }}
          </Tag>
        </div>
      </template>
      <template #toolbar-tools></template>
      <template #action="{ row }">
        <!-- 行操作与卡片视图共用 buildRowActions，双视图按钮/权限/显隐保持一致 -->
        <TableAction
          :actions="buildRowActions(row).actions"
          :drop-down-actions="buildRowActions(row).dropDownActions"
        />
      </template>

      <template #expand-content="{ row }">
        <div
          v-if="row.prescription_type === 2 || row.prescription_type === 5"
          class="product-list mt-5"
        >
          <div
            v-for="(item, index) in row.product_order_items"
            :key="index"
            class="box-card mb-6 rounded-lg p-4"
          >
            <div class="flex items-start">
              <div>
                <div
                  class="mr-6 h-32 w-32 overflow-hidden rounded-lg bg-gray-200 dark:bg-gray-800"
                >
                  <Image
                    :src="item.drug_image"
                    alt=""
                    height="100%"
                    width="100%"
                  />
                </div>
                <div class="ml-3 mt-5 text-sm">
                  <span class="text-gray-500 dark:text-gray-400">商品编号：</span>
                  X00{{ Number(index) + 1 }}
                </div>
              </div>
              <div class="flex-grow space-y-2">
                <div class="text-sm">
                  <span class="text-gray-500 dark:text-gray-400">商品名称:</span>
                  {{ item.display_drug_name || item.drug_name }}
                </div>
                <div class="text-sm">
                  <span class="text-gray-500 dark:text-gray-400">商品规格:</span>
                  {{ item.drug ? item.drug.specification : '暂无' }}
                </div>
                <div class="text-sm">
                  <span class="text-gray-500 dark:text-gray-400">商品数量:</span>
                  {{ item.number }}
                </div>
                <div class="text-sm">
                  <span class="text-gray-500 dark:text-gray-400">商品厂家:</span>
                  {{
                    item.drug
                      ? item.drug.source_info != null
                        ? item.drug.source_info.name
                        : item.drug.source
                      : '暂无'
                  }}
                </div>
                <div class="text-sm">
                  <span class="text-gray-500 dark:text-gray-400">商品价格:</span>
                  {{ item.price }} 元
                </div>
              </div>
            </div>
          </div>
        </div>

        <div
          v-if="row.prescription_type === 1"
          class="medication-details mt-5 px-4 pb-4 w-[60%]"
        >
          <span class="mb-3 block font-medium">药品明细：</span>
          <div class="flex flex-wrap gap-3">
            <div
              v-for="(item, index) in row.product_order_items"
              :key="index"
              class="tcm-drug-chip w-[200px] max-w-full flex-shrink-0 rounded-lg border border-gray-200 bg-white p-3 text-sm dark:border-gray-600 dark:bg-gray-900"
            >
              <div class="font-medium">
                【{{ item.drug?.drug_number }}】{{ item.display_drug_name || item.drug_name }}
              </div>
              <div class="mt-1 text-gray-600 dark:text-gray-400">
                数量：*{{ item.number * (item.dosage > 0 ? item.dosage : 1) }}
              </div>
              <div class="mt-1 text-gray-600 dark:text-gray-400">
                供货价：{{
                  item.buy_price != null && item.buy_price !== ''
                    ? `${item.buy_price} 元/${item.drug?.unit?.name || item.unit?.name || 'g'}`
                    : '—'
                }}
              </div>
              <div class="mt-1 text-gray-600 dark:text-gray-400">
                售价：{{
                  item.buy_price != null && item.buy_price !== ''
                    ? `${item.price} 元/${item.drug?.unit?.name || item.unit?.name || 'g'}`
                    : '—'
                }}
              </div>
            </div>
          </div>
        </div>
        <div v-if="!row.prescription_type"></div>
        <div
          class="order-summary mt-6 flex justify-center space-x-4 rounded-lg bg-gray-100 p-4 dark:bg-gray-800"
        >
          <span class="text-sm">采购价：{{ row.market_price || '0.00' }}</span>
          <span class="text-sm">快递费：{{ row.trans_expenses || '0.00' }}</span>
          <span class="text-sm">诊疗费：{{ row.treatement_price || '0.00' }}</span>
          <span class="text-sm">加工费：{{ row.process_price || '0.00' }}</span>
        </div>
      </template>
    </Grid>
    <!-- 卡片看板视图：展示内容与列表一致，行操作/弹窗全部复用父级逻辑 -->
    <div v-else class="po-card-wrap">
      <ProductOrderCardList
        ref="cardListRef"
        :form-values="searchValues"
        :build-row-actions="buildRowActions"
        :can-percent-adjust="canRowPercentAdjust"
        @open-store="openStoreCard"
        @open-doctor="showOrderDoctorCard"
        @open-user-patients="openOrderUserPatients"
        @open-patient="openOrderPatient"
        @open-warehouse="openChangeWarehouse"
        @toggle-free-shipping="toggleFreeShipping"
        @percent-adjust="openOrderPercentAdjust"
        @go-register="goRegisterOrder"
      />
    </div>
    <PercentAdjustDrawer />
    <!-- 订单改仓：按药分别选仓 -->
    <AntdModal
      v-model:open="changeWhOpen"
      title="修改配送仓库"
      :confirm-loading="changeWhSubmitting"
      :ok-button-props="{ disabled: changeWhPendingCount <= 0 }"
      destroy-on-close
      width="720px"
      @ok="submitChangeWarehouse"
    >
      <div class="text-muted-foreground mb-3 text-sm">
        当前仓库：{{ changeWhFromName || '—' }}
        <span v-if="!changeWhLoading" class="ml-2">
          · 将改仓 {{ changeWhPendingCount }} 种药品
        </span>
      </div>
      <div v-if="changeWhLoading" class="text-muted-foreground py-4 text-center">
        加载可选仓库…
      </div>
      <div v-else class="change-wh-drug-list space-y-4">
        <div
          v-for="row in changeWhDrugRows"
          :key="row.order_item_id"
          class="border-border rounded-lg border p-3"
        >
          <div class="mb-2 flex items-start gap-3">
            <img
              v-if="row.image"
              :src="row.image"
              alt=""
              class="h-12 w-12 shrink-0 rounded object-cover"
            />
            <div
              v-else
              class="bg-muted text-muted-foreground flex h-12 w-12 shrink-0 items-center justify-center rounded text-xs"
            >
              无图
            </div>
            <div class="min-w-0 flex-1">
              <div class="text-foreground truncate font-medium">
                {{ row.drug_name }}
              </div>
              <div class="text-muted-foreground mt-0.5 text-xs">
                规格：{{ row.specification || '--' }} · 数量 {{ row.number }}
              </div>
            </div>
          </div>
          <div class="flex flex-wrap gap-2">
            <button
              v-for="opt in row.options"
              :key="`${row.order_item_id}-${opt.warehouse_id}`"
              type="button"
              class="min-w-[120px] rounded-lg border px-3 py-2 text-left transition-colors"
              :class="
                row.to_warehouse_id === opt.warehouse_id
                  ? 'border-primary bg-primary/10 ring-primary ring-1'
                  : 'border-border hover:border-primary/50'
              "
              @click="row.to_warehouse_id = opt.warehouse_id"
            >
              <div class="text-foreground text-sm font-medium">
                {{ opt.warehouse_name }}
              </div>
              <div
                v-if="opt.quote != null"
                class="text-muted-foreground mt-1 text-xs"
              >
                供货价 {{ opt.quote }}
              </div>
            </button>
          </div>
        </div>
        <div
          v-if="changeWhDrugRows.length === 0"
          class="text-muted-foreground text-sm"
        >
          暂无可改仓药品
        </div>
      </div>
    </AntdModal>
  </Page>
</template>
<style scoped lang="scss">
.tcm-drug-chip {
  box-shadow: 0 1px 2px rgb(0 0 0 / 4%);
}

/* 卡片看板容器：撑满剩余高度，内部滚动（统计岛 + 收起态搜索一行 + 切换行约 220px，min-height 兜底） */
.po-card-wrap {
  height: calc(100% - 220px);
  min-height: 420px;
}
</style>
