<template>
  <div class="table-box appointment-info">
    <!-- 筛选：点击搜索后生效（与翻页联动）；列表参数 reservationUserName、orderStatus -->
    <div class="filter-bar">
      <div class="filter-row">
        <span class="filter-label">姓名</span>
        <el-input v-model="searchForm.reservationUserName" placeholder="请输入姓名" clearable style="width: 160px" />
        <span class="filter-label">状态</span>
        <el-select v-model="searchForm.orderStatus" placeholder="请选择" clearable style="width: 180px">
          <el-option
            v-for="opt in statusOptions"
            :key="`${opt.label}-${String(opt.value)}`"
            :label="opt.label"
            :value="opt.value"
          />
        </el-select>
        <div style="width: 600px">
          <span class="filter-label">预订日期</span>
          <el-date-picker
            v-model="searchForm.dateRange"
            type="daterange"
            range-separator="至"
            start-placeholder="请选择"
            end-placeholder="请选择"
            value-format="YYYY-MM-DD"
            style="width: 80%; margin-left: 10px"
          />
        </div>
        <el-button type="primary" @click="handleSearch"> 搜索 </el-button>
        <el-button @click="handleReset"> 重置 </el-button>
      </div>
    </div>

    <ProTable ref="proTable" :columns="columns" :request-api="getTableList" :init-param="initParam" :pagination="false">
      <template #tableHeader>
        <div class="table-header">
          <!-- <el-button type="primary" @click="handleNew"> 新建 </el-button> -->
        </div>
      </template>
      <template #statusText="{ row }">
        <el-tag :type="getStatusTagType(row.orderStatus)" size="small">
          {{ row.statusText }}
        </el-tag>
      </template>
      <template #remark="{ row }">
        <el-tooltip v-if="row.remark" :content="row.remark" placement="top" :show-after="200">
          <span class="remark-cell">{{ row.remark }}</span>
        </el-tooltip>
        <span v-else>—</span>
      </template>
      <!-- 操作按钮与 group_merchant scheduledInfo.vue 一致（orderStatus 判断顺序一致） -->
      <template #operation="scope">
        <div class="op-actions">
          <el-button v-if="hasReasonText(scope.row)" link type="primary" @click="openReasonDialog(scope.row)">
            查看原因
          </el-button>
          <template v-if="isOrderStatus(scope.row, 1)">
            <el-button link type="primary" @click="handleCancel(scope.row)"> 取消 </el-button>
          </template>
          <template
            v-else-if="
              (isOrderStatus(scope.row, 2) || isOrderStatus(scope.row, 7) || isOrderStatus(scope.row, 3)) &&
              isMoreThanThreeHoursAfterEnd(scope.row)
            "
          >
            <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
          </template>
          <template
            v-else-if="
              (isOrderStatus(scope.row, 2) || isOrderStatus(scope.row, 7) || isOrderStatus(scope.row, 3)) &&
              !isMoreThanThreeHoursAfterEnd(scope.row)
            "
          >
            <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
          </template>
          <template v-else-if="isOrderStatus(scope.row, 7) && !isMoreThanThreeHoursAfterEnd(scope.row)">
            <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
          </template>
          <template
            v-else-if="isOrderStatus(scope.row, 3) && !isMoreThanThreeHoursAfterEnd(scope.row) && orderCostTypeIsPaid(scope.row)"
          >
            <el-button link type="primary" @click="handleRefund(scope.row)"> 退款 </el-button>
            <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
          </template>
          <template v-else-if="isOrderStatus(scope.row, 4) && !orderCostTypeIsPaid(scope.row)">
            <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
          </template>
          <template v-else-if="orderCostTypeIsPaid(scope.row) && isOrderStatus(scope.row, 4) && cancelReasonIsEmpty(scope.row)">
            <el-button link type="primary" @click="handleRefund(scope.row)"> 退款 </el-button>
            <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
          </template>
          <template v-else-if="isOrderStatus(scope.row, 2) && !isMoreThanThreeHoursAfterEnd(scope.row)">
            <el-button link type="primary" @click="handleAddTime(scope.row)"> 加时 </el-button>
          </template>
        </div>
      </template>
    </ProTable>

    <!-- 查看原因 -->
    <el-dialog v-model="reasonDialogVisible" title="原因" width="420px" append-to-body destroy-on-close>
      <div class="reason-dialog-body">取消原因：</div>
      <div class="reason-dialog-body">
        {{ reasonDialogText || "—" }}
      </div>
      <template #footer>
        <el-button type="primary" @click="reasonDialogVisible = false"> 知道了 </el-button>
      </template>
    </el-dialog>

    <!-- 取消原因（与 group_merchant scheduledInfo：reservationId + cancelReason） -->
    <el-dialog
      v-model="cancelReasonVisible"
      title="取消原因"
      width="480px"
      append-to-body
      destroy-on-close
      class="cancel-reason-dialog"
      @closed="resetCancelReasonDialog"
    >
      <el-form label-position="top" class="cancel-reason-form">
        <el-form-item label="取消原因" required>
          <el-input
            v-model="cancelReasonText"
            type="textarea"
            :rows="4"
            maxlength="500"
            show-word-limit
            placeholder="请输入取消原因"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="cancelReasonVisible = false"> 取消 </el-button>
        <el-button type="primary" :loading="cancelReasonLoading" @click="confirmCancelReason"> 确定 </el-button>
      </template>
    </el-dialog>

    <!-- 加时弹窗（与 group_merchant scheduledInfo：1-99 分钟、reservationId + addTimeMinutes + addTimeStart） -->
    <el-dialog
      v-model="addTimeVisible"
      title="加时"
      width="480px"
      append-to-body
      destroy-on-close
      class="add-time-dialog"
      @closed="resetAddTimeDialog"
    >
      <el-form :model="addTimeForm" label-position="top" require-asterisk-position="right" class="add-time-form">
        <el-form-item label="加时时长" required>
          <el-input
            :model-value="addTimeForm.minutesInput"
            placeholder="请输入"
            clearable
            maxlength="2"
            @update:model-value="onAddTimeMinutesInput"
          >
            <template #append>
              <span class="add-time-append-unit">分钟</span>
            </template>
          </el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="addTimeVisible = false"> 取消 </el-button>
        <el-button type="primary" :loading="addTimeLoading" @click="confirmAddTime"> 确定 </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import ProTable from "@/components/ProTable/index.vue";
import type { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
import {
  reservationList,
  reservationAddTime,
  reservationCancel,
  reservationDelete,
  reservationRefund
} from "@/api/modules/scheduledService";
import { localGet } from "@/utils";

export interface ReservationRow {
  id: number | string;
  /** 与商家端加时接口一致，缺省时用 id */
  reservationId?: number | string;
  _seq?: number;
  date: string;
  weekDay: string;
  location: string;
  peopleCount: string | number;
  tableNo: string;
  timeRange: string;
  amount: string | number;
  customerName: string;
  phone: string;
  /** 兼容旧字段展示/筛选 */
  status: number | string;
  statusText: string;
  /** 与商家端 1.vue 一致：订单状态 */
  orderStatus: number;
  /** 0 免费 1 付费（退款按钮用） */
  orderCostType: number;
  /** 与 1.vue item.reason 一致：空=用户取消，非空=商家取消等 */
  reason: string;
  reservationDateRaw: string;
  timeSlotRaw: string;
  endTimeRaw?: string | Date;
  remark: string;
  cancelReason?: string;
  refundReason?: string;
  canRefund?: boolean;
}

const proTable = ref<ProTableInstance>();

const columns: ColumnProps<ReservationRow>[] = [
  { prop: "_seq", label: "序号", width: 60, align: "center" },
  { prop: "date", label: "日期", width: 100, align: "center" },
  { prop: "weekDay", label: "星期", width: 70, align: "center" },
  { prop: "location", label: "位置", minWidth: 90, showOverflowTooltip: true },
  { prop: "peopleCount", label: "人数", width: 70, align: "center" },
  { prop: "tableNo", label: "桌号", minWidth: 90, showOverflowTooltip: true },
  { prop: "timeRange", label: "时间", width: 120, align: "center" },
  { prop: "customerName", label: "姓名", width: 100, showOverflowTooltip: true },
  { prop: "phone", label: "电话", width: 120, showOverflowTooltip: true },
  { prop: "statusText", label: "状态", width: 96, align: "center" },
  { prop: "remark", label: "备注", minWidth: 100, showOverflowTooltip: true },
  { prop: "operation", label: "操作", fixed: "right", width: 240, align: "center" }
];

/**
 * 筛选状态：商家取消 / 用户取消 均为 orderStatus=4，列表展示区分见 mapReservationRow（reason 空=用户取消）
 * 接口仅支持 orderStatus 时，请求 4 后在本地按 reason 再筛一层
 */
const STATUS_FILTER_MERCHANT_CANCEL = "merchant_cancel";
const STATUS_FILTER_USER_CANCEL = "user_cancel";

const statusOptions: { label: string; value: number | string }[] = [
  { label: "全部", value: "" },
  { label: "待使用", value: 1 },
  { label: "退款成功", value: 7 },
  { label: "商家取消", value: STATUS_FILTER_MERCHANT_CANCEL },
  { label: "用户取消", value: STATUS_FILTER_USER_CANCEL },
  { label: "已过期", value: 3 },
  { label: "已完成", value: 2 }
];

/** orderStatus 文案，与 1.vue ORDER_STATUS_TEXT 一致 */
const ORDER_STATUS_TEXT: Record<number, string> = {
  0: "待支付",
  1: "待使用",
  2: "已完成",
  3: "已过期",
  4: "已取消",
  5: "已关闭",
  6: "退款中",
  7: "已退款",
  8: "商家预订"
};

/** 旧版 Web 列表 status → orderStatus（无 orderStatus 字段时的兜底） */
const LEGACY_STATUS_TO_ORDER: Record<number, number> = {
  0: 1, // 待使用
  1: 2, // 已完成
  2: 4, // 用户取消 → 已取消
  3: 4, // 商家取消 → 已取消
  4: 3, // 已过期
  5: 6, // 退款中
  6: 7 // 退款成功 → 已退款
};

const THREE_HOURS_MS = 3 * 60 * 60 * 1000;

const initParam = reactive({
  storeId: localGet("geeker-user")?.userInfo?.storeId ?? localGet("createdId") ?? ""
});

/** 已生效的查询条件（点击搜索后写入；接口字段 reservationUserName、orderStatus） */
const listFilter = reactive({
  reservationUserName: "",
  orderStatus: "" as number | string,
  startDate: "",
  endDate: ""
});

const searchForm = reactive({
  reservationUserName: "",
  orderStatus: "" as number | string,
  dateRange: [] as string[]
});

const addTimeVisible = ref(false);
const addTimeLoading = ref(false);
const addTimeForm = reactive({ minutesInput: "" });
const currentAddTimeRow = ref<ReservationRow | null>(null);

/** 取消预约：原因弹窗（对齐 scheduledInfo） */
const cancelReasonVisible = ref(false);
const cancelReasonLoading = ref(false);
const cancelReasonText = ref("");
const cancelCurrentRow = ref<ReservationRow | null>(null);

function getStoreId(): number | string | null {
  return localGet("geeker-user")?.userInfo?.storeId ?? localGet("createdId") ?? null;
}

/** 与 scheduledInfo normalizeReservationItem：pending(0,1,8) | done(2) | refund(6,7) | closed(3,4,5) */
function getStatusTagType(orderStatus: number | string): "primary" | "success" | "warning" | "danger" | "info" {
  const s = Number(orderStatus);
  if (s === 2) return "success";
  if (s === 6 || s === 7) return "warning";
  if (s === 3 || s === 4 || s === 5) return "info";
  if (s === 0 || s === 1 || s === 8) return "primary";
  return "info";
}

function isOrderStatus(row: ReservationRow, n: number) {
  return Number(row.orderStatus) === n;
}

function orderCostTypeIsPaid(row: ReservationRow) {
  return Number(row.orderCostType) === 1;
}

/** 与 1.vue 一致：reason === '' 时视为用户取消（付费可退款+删除） */
function cancelReasonIsEmpty(row: ReservationRow) {
  return String(row.reason ?? "").trim() === "";
}

function hasReasonText(row: ReservationRow) {
  return String(row.reason ?? "").trim() !== "";
}

const reasonDialogVisible = ref(false);
const reasonDialogText = ref("");

function openReasonDialog(row: ReservationRow) {
  reasonDialogText.value = String(row.reason ?? "").trim() || "—";
  reasonDialogVisible.value = true;
}

function parseRowEndDateTime(row: ReservationRow): Date | null {
  const et = row.endTimeRaw;
  if (et != null && et !== "") {
    const d = et instanceof Date ? et : new Date(et as string);
    if (!isNaN(d.getTime())) return d;
  }
  const date = String(row.reservationDateRaw || "")
    .trim()
    .replace(/\//g, "-");
  const slot = String(row.timeSlotRaw || "").trim();
  const parts = slot.split("-");
  const endTimeStr = parts.length > 1 ? parts[parts.length - 1].trim() : "";
  if (date && endTimeStr) {
    const normalized = endTimeStr.length <= 5 ? `${date} ${endTimeStr}:00` : `${date} ${endTimeStr}`;
    const parsed = new Date(normalized.replace(/-/g, "/"));
    if (!isNaN(parsed.getTime())) return parsed;
  }
  return null;
}

/** 结束时间已过且当前时间超过结束 3 小时（与 1.vue 一致） */
function isMoreThanThreeHoursAfterEnd(row: ReservationRow) {
  const end = parseRowEndDateTime(row);
  if (!end) return false;
  return Date.now() > end.getTime() + THREE_HOURS_MS;
}

function formatDateCol(val: string): string {
  if (!val) return "—";
  const d = new Date(val);
  if (isNaN(d.getTime())) return String(val);
  const m = d.getMonth() + 1;
  const day = d.getDate();
  return `${String(m).padStart(2, "0")}月${String(day).padStart(2, "0")}日`;
}

function getWeekDay(val: string): string {
  if (!val) return "—";
  const d = new Date(val);
  if (isNaN(d.getTime())) return "—";
  const week = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
  return week[d.getDay()];
}

function mapReservationRow(item: any): ReservationRow {
  const date = item.reservationDate ?? item.bookingDate ?? item.date ?? "";
  const timeStart = item.startTime ?? item.bookingStartTime ?? "";
  const timeEnd = item.bookingEndTime ?? item.endTime ?? "";
  const customerName =
    item.customerName != null && String(item.customerName).trim() !== ""
      ? String(item.customerName).trim()
      : (item.name ?? item.userName ?? item.contactName ?? "—");

  const hasOrderStatusField =
    (item.orderStatus != null && item.orderStatus !== "") || (item.statusType != null && item.statusType !== "");
  const legacySt = Number(item.status ?? item.reservationStatus ?? NaN);

  let orderStatus: number;
  if (item.orderStatus != null && item.orderStatus !== "") {
    orderStatus = Number(item.orderStatus);
  } else if (item.statusType != null && item.statusType !== "") {
    orderStatus = Number(item.statusType);
  } else if (Number.isFinite(legacySt) && LEGACY_STATUS_TO_ORDER[legacySt] !== undefined) {
    orderStatus = LEGACY_STATUS_TO_ORDER[legacySt];
  } else if (Number.isFinite(legacySt)) {
    orderStatus = legacySt;
  } else {
    orderStatus = 1;
  }

  let reason = String(item.reason ?? item.cancelReason ?? "").trim();
  if (!hasOrderStatusField && legacySt === 2) reason = "";
  if (!hasOrderStatusField && legacySt === 3 && !reason) reason = "商家取消";

  const orderCostType = Number(item.orderCostType ?? item.costType ?? item.reservationCostType ?? 0);

  const timeSlotRaw = item.timeSlot ?? (timeStart && timeEnd ? `${String(timeStart).trim()}-${String(timeEnd).trim()}` : "");

  return {
    id: item.id,
    reservationId: item.reservationId ?? item.id,
    date: formatDateCol(date),
    weekDay: item.weekDay ?? getWeekDay(date),
    location: item.locationName ?? item.categoryName ?? item.location ?? "—",
    peopleCount: item.peopleCount ?? item.personCount ?? item.guestCount ?? "—",
    tableNo: item.tableNo ?? item.tableNumber ?? item.tableNumbers ?? "—",
    timeRange: timeStart && timeEnd ? `${timeStart}-${timeEnd}` : (item.timeRange ?? "—"),
    amount:
      item.depositAmount != null && item.depositAmount !== ""
        ? item.depositAmount
        : item.amount != null && item.amount !== ""
          ? item.amount
          : "—",
    customerName,
    phone: item.phone ?? item.mobile ?? item.contactPhone ?? "—",
    status: orderStatus,
    orderStatus,
    orderCostType,
    reason,
    reservationDateRaw: String(date).trim(),
    timeSlotRaw,
    endTimeRaw: item.endTime ?? item.bookingEndTime ?? item.reservationEndTime,
    /** scheduledInfo：orderStatus==4 时 reason 空=用户取消，非空=商家取消 */
    statusText:
      orderStatus === 4
        ? reason === ""
          ? "用户取消"
          : "商家取消"
        : (item.orderStatusText && String(item.orderStatusText).trim()) ||
          ORDER_STATUS_TEXT[orderStatus] ||
          item.statusText ||
          "—",
    remark: item.remark ?? item.remarkDesc ?? "",
    cancelReason: item.cancelReason ?? item.reason ?? "",
    refundReason: item.refundReason,
    canRefund: item.canRefund
  };
}

/** ProTable / useTable 约定：返回 { data: { list, total } } */
async function getTableList(params: any) {
  const storeId = params.storeId ?? initParam.storeId;
  if (!storeId) {
    return { data: { list: [] as ReservationRow[], total: 0 } };
  }
  const pageNum = params.pageNum ?? 1;
  const pageSize = params.pageSize ?? 10;
  const req: Record<string, any> = {
    storeId: Number(storeId),
    pageNum,
    pageSize
  };
  if (listFilter.reservationUserName?.trim()) {
    req.reservationUserName = listFilter.reservationUserName.trim();
  }
  const sf = listFilter.orderStatus;
  if (sf !== undefined && sf !== "" && sf !== null) {
    if (sf === STATUS_FILTER_USER_CANCEL || sf === STATUS_FILTER_MERCHANT_CANCEL) {
      req.orderStatus = 4;
    } else {
      req.orderStatus = sf;
    }
  }
  if (listFilter.startDate && listFilter.endDate) {
    req.dateFrom = listFilter.startDate;
    req.dateTo = listFilter.endDate;
  }
  try {
    const res: any = await reservationList(req);
    const body = res?.data ?? res;
    const inner = body?.data ?? body;
    const list = inner?.list ?? inner?.records ?? (Array.isArray(inner) ? inner : []);
    const arr = Array.isArray(list) ? list : [];
    const apiTotal = Number(inner?.total ?? body?.total ?? res?.total ?? 0) || 0;
    let rows = arr.map((item: any) => mapReservationRow(item));
    if (sf === STATUS_FILTER_USER_CANCEL) {
      rows = rows.filter(r => r.orderStatus === 4 && cancelReasonIsEmpty(r));
    } else if (sf === STATUS_FILTER_MERCHANT_CANCEL) {
      rows = rows.filter(r => r.orderStatus === 4 && !cancelReasonIsEmpty(r));
    }
    const finalRows = rows.map((r, i) => ({
      ...r,
      _seq: (pageNum - 1) * pageSize + i + 1
    }));
    const total = sf === STATUS_FILTER_USER_CANCEL || sf === STATUS_FILTER_MERCHANT_CANCEL ? finalRows.length : apiTotal;
    return { data: { list: finalRows, total } };
  } catch (e: any) {
    ElMessage.error(e?.message || "加载失败");
    return { data: { list: [] as ReservationRow[], total: 0 } };
  }
}

function handleSearch() {
  listFilter.reservationUserName = searchForm.reservationUserName;
  listFilter.orderStatus = searchForm.orderStatus;
  if (searchForm.dateRange?.length === 2) {
    listFilter.startDate = searchForm.dateRange[0];
    listFilter.endDate = searchForm.dateRange[1];
  } else {
    listFilter.startDate = "";
    listFilter.endDate = "";
  }
  proTable.value?.getTableList();
}

function handleReset() {
  searchForm.reservationUserName = "";
  searchForm.orderStatus = "";
  searchForm.dateRange = [];
  listFilter.reservationUserName = "";
  listFilter.orderStatus = "";
  listFilter.startDate = "";
  listFilter.endDate = "";
  proTable.value?.getTableList();
}

function handleNew() {
  ElMessage.info("新建预约功能可在此处跳转或打开弹窗");
}

function handleCancel(row: ReservationRow) {
  cancelCurrentRow.value = row;
  cancelReasonText.value = "";
  cancelReasonVisible.value = true;
}

function resetCancelReasonDialog() {
  cancelCurrentRow.value = null;
  cancelReasonText.value = "";
}

async function confirmCancelReason() {
  const reason = (cancelReasonText.value || "").trim();
  if (!reason) {
    ElMessage.warning("请输入取消原因");
    return;
  }
  const row = cancelCurrentRow.value;
  const reservationId = row?.reservationId ?? row?.id;
  if (reservationId == null || reservationId === "") {
    ElMessage.warning("缺少预订ID");
    return;
  }
  cancelReasonLoading.value = true;
  try {
    const apiRes: any = await reservationCancel({ reservationId, cancelReason: reason });
    ElMessage.success(apiRes?.msg || "已取消");
    cancelReasonVisible.value = false;
    resetCancelReasonDialog();
    proTable.value?.getTableList();
  } catch (e: any) {
    if (typeof e?.code !== "number") {
      ElMessage.error(e?.msg || e?.data?.msg || e?.message || "取消失败");
    }
  } finally {
    cancelReasonLoading.value = false;
  }
}

/** 与 scheduledInfo confirmAddTime：当前时间 yyyy-MM-dd HH:mm */
function formatAddTimeStartFromNow(): string {
  const now = new Date();
  return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")} ${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`;
}

/** 与 scheduledInfo onAddTimeMinutesInput：最多 2 位数字 1-99 */
function onAddTimeMinutesInput(val: string | number) {
  const v = String(val ?? "")
    .replace(/\D/g, "")
    .slice(0, 2);
  addTimeForm.minutesInput = v;
}

function resetAddTimeDialog() {
  currentAddTimeRow.value = null;
  addTimeForm.minutesInput = "";
}

function handleAddTime(row: ReservationRow) {
  currentAddTimeRow.value = row;
  addTimeForm.minutesInput = "";
  addTimeVisible.value = true;
}

async function confirmAddTime() {
  const row = currentAddTimeRow.value;
  if (!row) return;
  const raw = String(addTimeForm.minutesInput ?? "").trim();
  if (!raw) {
    ElMessage.warning("请输入加时时长");
    return;
  }
  const addTimeMinutesNum = parseInt(raw, 10);
  if (isNaN(addTimeMinutesNum) || addTimeMinutesNum < 1 || addTimeMinutesNum > 99) {
    ElMessage.warning("加时时长为1-99的整数");
    return;
  }
  const reservationId = row.reservationId ?? row.id;
  if (reservationId == null || reservationId === "") {
    ElMessage.warning("缺少预订ID");
    return;
  }
  const addTimeStart = formatAddTimeStartFromNow();
  addTimeLoading.value = true;
  try {
    const apiRes: any = await reservationAddTime({
      reservationId,
      addTimeMinutes: addTimeMinutesNum,
      addTimeStart
    });
    ElMessage.success(apiRes?.msg || "加时成功");
    addTimeVisible.value = false;
    resetAddTimeDialog();
    proTable.value?.getTableList();
  } catch (e: any) {
    // 业务 code≠200 时 indexApi 响应拦截器已提示 msg，避免重复 Toast
    if (typeof e?.code !== "number") {
      ElMessage.error(e?.msg || e?.data?.msg || e?.message || "加时失败");
    }
  } finally {
    addTimeLoading.value = false;
  }
}

function handleDelete(row: ReservationRow) {
  ElMessageBox.confirm("确认删除该预约记录？", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(async () => {
      try {
        await reservationDelete({ id: row.id });
        ElMessage.success("删除成功");
        proTable.value?.getTableList();
      } catch (e: any) {
        ElMessage.error(e?.message || "删除失败");
      }
    })
    .catch(() => {});
}

function handleRefund(row: ReservationRow) {
  ElMessageBox.confirm("确认对该预约发起退款？", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(async () => {
      try {
        await reservationRefund({ id: row.id });
        ElMessage.success("退款申请已提交");
        proTable.value?.getTableList();
      } catch (e: any) {
        ElMessage.error(e?.message || "退款失败");
      }
    })
    .catch(() => {});
}
</script>

<style scoped lang="scss">
.appointment-info {
  padding: 0;
}
.filter-bar {
  padding: 0 4px;
  margin-bottom: 12px;
}
.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}
.filter-label {
  font-size: 14px;
  color: #606266;
  white-space: nowrap;
}
.table-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 12px 0;
}
.tip-text {
  font-size: 12px;
  color: #909399;
}
.remark-cell {
  display: inline-block;
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: default;
}
.op-actions {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  align-items: center;
  justify-content: center;
}
.reason-dialog-body {
  padding: 8px 4px;
  font-size: 14px;
  line-height: 1.6;
  color: #303133;
  word-break: break-word;
  white-space: pre-wrap;
}
</style>

<!-- append-to-body 时弹窗挂到 body，需非 scoped 命中 -->
<style lang="scss">
.add-time-dialog.el-dialog .el-dialog__body {
  padding-top: 8px;
}
.add-time-form {
  width: 100%;
}
.add-time-form .el-form-item {
  margin-bottom: 8px;
}
.add-time-form .el-form-item__label {
  font-weight: 500;
  color: #303133;
}
.add-time-form .el-input-group {
  width: 100%;
}
.add-time-form .el-input__wrapper {
  flex: 1;
  min-width: 0;
}
.add-time-append-unit {
  padding: 0 4px;
  font-size: 14px;
  color: #606266;
}
.cancel-reason-dialog.el-dialog .el-dialog__body {
  padding-top: 8px;
}
.cancel-reason-form {
  width: 100%;
}
.cancel-reason-form .el-form-item {
  margin-bottom: 0;
}
</style>
