﻿<script setup>
import { ref, reactive, computed, onMounted, onUnmounted } from "vue";
import { useRoute, useRouter, RouterLink } from "vue-router";
import { useI18n } from "vue-i18n";
import { useToastStore } from "@/stores/toast";
import { usePageTitle } from "@/composables/usePageTitle";
import { purchaseApi } from "@/api/purchase";
import { useUserStore } from "@/stores/user";
import { useUsersStore } from "@/stores/users";
import ConfirmDialog from "@/components/ConfirmDialog.vue";
import {
  IconChevronLeft,
  IconExternalLink,
  IconPhoto,
  IconCheck,
  IconLoader2,
  IconX,
  IconUpload,
  IconTrash,
  IconSearch,
  IconFile,
} from "@tabler/icons-vue";

usePageTitle("purchase.order_detail");
const { t, locale } = useI18n();
const route = useRoute();
const router = useRouter();
const toast = useToastStore();
const usersStore = useUsersStore();
const userStore = useUserStore();

const orderId = computed(() => parseInt(route.params.id));

const order = ref(null);
const costs = ref([]);
const photos = ref([]);
const commits = ref([]);
const workOrders = ref([]);
const canModify = ref(false);
const loading = ref(true);
const notFound = ref(false);
const updatingStatus = ref(false);
const showStatusDialog = ref(false);
const pendingStatus = ref("");
const pendingComment = ref("");

// 工单关联搜索
const workOrderSearchQuery = ref('')
const workOrderSearchResults = ref([])
const workOrderSearchLoading = ref(false)
const workOrderDropdownVisible = ref(false)
const workOrderDropdownRef = ref(null)
let workOrderSearchTimer = null

function onDocumentClick(e) {
  if (workOrderDropdownRef.value && !workOrderDropdownRef.value.contains(e.target)) {
    workOrderDropdownVisible.value = false
  }
}

// 状态变更附带的图片
const pendingPhotos = ref([]); // { hash, url, uploading, error }
const photoInputRef = ref(null);

// 删除进度相关
const showDeleteConfirm = ref(false);
const pendingDeleteCommitId = ref(null);

// 判断是否可以删除进度
function canDeleteCommit(commit, index) {
  // 最新状态（第0条）不显示删除按钮
  if (index === 0) return false;
  // 订单创建者
  if (order.value?.UserID === userStore.user?.ID) return true;
  // 进度创建者
  if (commit.userId === userStore.user?.ID) return true;
  // 管理员
  if (userStore.user?.Type === 'admin') return true;
  return false;
}

function handleDeleteCommit(commitId) {
  pendingDeleteCommitId.value = commitId;
  showDeleteConfirm.value = true;
}

async function confirmDeleteCommit() {
  if (!pendingDeleteCommitId.value) return;
  try {
    const { errCode } = await purchaseApi.deleteCommit(orderId.value, pendingDeleteCommitId.value);
    if (errCode === 0) {
      toast.success(t("message.delete_ok"));
      // 前端直接移除该 commit，保持滚动位置
      commits.value = commits.value.filter(c => c.id !== pendingDeleteCommitId.value);
    } else {
      toast.error(t("message.server_error"));
    }
  } catch {
    toast.error(t("message.server_error"));
  } finally {
    pendingDeleteCommitId.value = null;
    showDeleteConfirm.value = false;
  }
}

// 状态选项
const statusOptions = [
  { value: "pending", labelKey: "status_pending", color: "yellow" },
  { value: "ordered", labelKey: "status_ordered", color: "blue" },
  { value: "arrived", labelKey: "status_arrived", color: "purple" },
  { value: "received", labelKey: "status_received", color: "green" },
  { value: "lost", labelKey: "status_lost", color: "red" },
  { value: "returned", labelKey: "status_returned", color: "gray" },
];

// 状态颜色映射
const statusColorClass = computed(() => ({
  pending:
    "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/40 dark:text-yellow-400",
  ordered: "bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-400",
  arrived:
    "bg-purple-100 text-purple-700 dark:bg-purple-900/40 dark:text-purple-400",
  received:
    "bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-400",
  lost:
    "bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-400",
  returned:
    "bg-gray-200 text-gray-600 dark:bg-gray-700 dark:text-gray-300",
}));

// 货币选项
const currencyOptions = { 1: "CNY", 2: "MOP", 3: "HKD", 4: "USD" };

// 费用类型映射
const costTypeMap = computed(() => ({
  1: t("cost_type.unit_price"),
  2: t("cost_type.freight"),
}));

// 合计费用
const costTotalYuan = computed(() => {
  return (
    costs.value.reduce(
      (sum, c) => sum + (c.Price || 0) * (c.Quantity || 0),
      0,
    ) / 100
  );
});

// 按货币分组统计
const costsByCurrency = computed(() => {
  const groups = {};
  costs.value.forEach((c) => {
    const cur = currencyOptions[c.CurrencyType] || "Unknown";
    const amount =
      c.Price && c.Quantity
        ? ((c.Price * c.Quantity) / 100).toFixed(2)
        : "0.00";
    if (!groups[cur]) groups[cur] = 0;
    groups[cur] += parseFloat(amount);
  });
  return Object.entries(groups).map(([currency, total]) => ({
    currency,
    total: total.toFixed(2),
  }));
});

function formatDate(dateStr) {
  if (!dateStr) return "-";
  const d = new Date(dateStr);
  if (isNaN(d.getTime())) return "-";
  return new Intl.DateTimeFormat(locale.value, {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
    hour12: false,
  }).format(d);
}

function formatPrice(priceInCents) {
  if (!priceInCents) return "0.00";
  return (priceInCents / 100).toFixed(2);
}

function getPhotoUrl(file) {
  return `/api/files/get/${file.Sha256}`;
}

function openLink() {
  if (!order.value?.Link) return;
  let url = order.value.Link.trim();
  if (!/^https?:\/\//i.test(url)) url = "https://" + url;
  window.open(url, "_blank");
}

function copyLink() {
  if (!order.value?.Link) return;
  navigator.clipboard.writeText(order.value.Link.trim()).then(() => {
    const toast = useToastStore()
    toast.success('链接已复制')
  })
}

function getStatusLabel(status) {
  if (!status) return "";
  const opt = statusOptions.find((o) => o.value === status);
  return opt ? t("purchase." + opt.labelKey) || status : status;
}

function getStatusColorClass(status) {
  return statusColorClass.value[status] || "bg-gray-100 text-gray-600";
}

function openStatusDialog(newStatus) {
  pendingStatus.value = newStatus;
  pendingComment.value = "";
  pendingPhotos.value = [];
  showStatusDialog.value = true;
}

function closeStatusDialog() {
  showStatusDialog.value = false;
  pendingStatus.value = "";
  pendingComment.value = "";
  pendingPhotos.value = [];
}

// 触发文件选择
function openPhotoPicker() {
  photoInputRef.value?.click();
}

// 选择文件后上传
async function handlePhotoChange(event) {
  const files = Array.from(event.target.files || []);
  if (!files.length) return;
  event.target.value = ""; // 清空，允许重复选同一文件

  for (const file of files) {
    if (pendingPhotos.value.length >= 10) break;
    const tempId = Date.now() + Math.random();
    const entry = {
      tempId,
      url: URL.createObjectURL(file),
      uploading: true,
      error: false,
      hash: null,
    };
    pendingPhotos.value.push(entry);

    try {
      const formData = new FormData();
      formData.append("file", file);
      formData.append("cookie", userStore.cookieValue);
      const res = await fetch("/api/files/upload/image", {
        method: "POST",
        body: formData,
      });
      const json = await res.json();
      if (json.errCode === 0 || json.return?.hash) {
        const p = pendingPhotos.value.find((p) => p.tempId === tempId);
        if (p) {
          p.hash = json.return.hash;
          p.uploading = false;
        }
      } else {
        const p = pendingPhotos.value.find((p) => p.tempId === tempId);
        if (p) {
          p.uploading = false;
          p.error = true;
        }
      }
    } catch {
      const p = pendingPhotos.value.find((p) => p.tempId === tempId);
      if (p) {
        p.uploading = false;
        p.error = true;
      }
    }
  }
}

// 移除待上传的图片
function removePendingPhoto(tempId) {
  const idx = pendingPhotos.value.findIndex((p) => p.tempId === tempId);
  if (idx !== -1) {
    const p = pendingPhotos.value[idx];
    if (p.url) URL.revokeObjectURL(p.url);
    pendingPhotos.value.splice(idx, 1);
  }
}

async function confirmStatusChange() {
  // 等所有图片上传完
  await new Promise((resolve) => setTimeout(resolve, 200));
  const stillUploading = pendingPhotos.value.some((p) => p.uploading);
  if (stillUploading) {
    toast.error("图片正在上传中，请稍候");
    return;
  }
  const photoHashes = pendingPhotos.value
    .filter((p) => !p.error)
    .map((p) => p.hash);

  updatingStatus.value = true;
  showStatusDialog.value = false;
  try {
    const { errCode } = await purchaseApi.updateOrderStatus(
      orderId.value,
      pendingStatus.value,
      pendingComment.value,
      photoHashes,
    );
    if (errCode === 0) {
      order.value.OrderStatus = pendingStatus.value;
      toast.success(t("message.save_success"));
      await fetchOrder();
    } else {
      toast.error(t("message.server_error"));
    }
  } catch {
    toast.error(t("message.server_error"));
  } finally {
    updatingStatus.value = false;
    pendingStatus.value = "";
    pendingComment.value = "";
  }
}

async function fetchOrder() {
  loading.value = true;
  try {
    const { errCode, data } = await purchaseApi.getOrder(orderId.value);
    if (errCode === 0 && data) {
      order.value = data.order ?? null;
      canModify.value = data.canModify ?? false;
      costs.value = data.costs ?? [];
      photos.value = data.photos ?? [];
      commits.value = data.commits ?? [];
      workOrders.value = data.workOrders ?? [];
    } else {
      notFound.value = true;
    }
  } catch {
    notFound.value = true;
  } finally {
    loading.value = false;
  }
}

// ── 工单搜索 ──
async function searchWorkOrders() {
  workOrderSearchLoading.value = true
  try {
    const { errCode, data } = await purchaseApi.searchWorkOrders(workOrderSearchQuery.value, 10)
    if (errCode === 0) {
      workOrderSearchResults.value = data.orders || []
    }
  } catch {
    workOrderSearchResults.value = []
  } finally {
    workOrderSearchLoading.value = false
  }
}

function onWorkOrderSearchInput() {
  workOrderDropdownVisible.value = true
  clearTimeout(workOrderSearchTimer)
  workOrderSearchTimer = setTimeout(() => searchWorkOrders(), 300)
}

function getWorkOrderStatusClass(status) {
  const map = {
    pending:       'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/40 dark:text-yellow-400',
    checked:       'bg-purple-100 text-purple-700 dark:bg-purple-900/40 dark:text-purple-400',
    parts_ordered: 'bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-400',
    repaired:      'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-400',
    returned:      'bg-gray-200 text-gray-600 dark:bg-gray-700 dark:text-gray-300',
    unrepairable:  'bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-400',
  }
  return map[status] || 'bg-gray-100 text-gray-600'
}

function getWorkOrderStatusLabel(status) {
  return t(`work_order.status_${status}`) || status
}

function openNewWorkOrder() {
  if (!order.value) return
  const prefillData = {
    purchaseOrderId: order.value.ID,
    purchaseOrderTitle: order.value.Title,
  }
  localStorage.setItem('prefill_work_order', JSON.stringify(prefillData))
  router.push('/work_order/add')
}

onMounted(() => {
  fetchOrder()
  document.addEventListener('click', onDocumentClick)
})

onUnmounted(() => {
  document.removeEventListener('click', onDocumentClick)
})
</script>

<template>
  
  <div class="mx-auto max-w-6xl px-6 py-6">
    <!-- 顶部操作栏：返回 + 编辑 -->
    <div class="mb-4 flex items-center justify-between">
      <button
        @click="$router.back()"
        class="inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-dk-card dark:hover:text-gray-200"
      >
        <IconChevronLeft :size="16" />
        {{ t("purchase.back_to_list") }}
      </button>
      <!-- 编辑按钮 -->
      <RouterLink
        v-if="canModify"
        :to="`/purchase/editorder/${order.ID}`"
        class="inline-flex items-center gap-1.5 rounded-lg border border-gray-300 bg-white px-3 py-1.5 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 dark:border-dk-muted dark:bg-dk-card dark:text-gray-300 dark:hover:bg-dk-base"
      >
        <svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
        </svg>
        {{ t("purchase.edit_order") }}
      </RouterLink>
    </div>

    <!-- Loading -->
    <div v-if="loading" class="flex items-center justify-center py-24">
      <svg
        class="h-8 w-8 animate-spin text-blue-500"
        viewBox="0 0 24 24"
        fill="none"
      >
        <circle
          class="opacity-25"
          cx="12"
          cy="12"
          r="10"
          stroke="currentColor"
          stroke-width="4"
        />
        <path
          class="opacity-75"
          fill="currentColor"
          d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
        />
      </svg>
      <span class="ml-3 text-gray-500">Loading...</span>
    </div>

    <!-- Not Found -->
    <div
      v-else-if="notFound"
      class="rounded-xl border border-gray-200 bg-white py-16 text-center shadow-lg dark:border-dk-muted dark:bg-dk-card"
    >
      <p class="text-gray-400">{{ t("purchase.order_not_found") }}</p>
    </div>

    <!-- Order Detail -->
    <div v-else class="flex flex-col gap-6">
      <!-- Header -->
      <div
        class="rounded-xl border border-gray-200 bg-white shadow-lg dark:border-dk-muted dark:bg-dk-card"
      >
        <div
          class="flex items-center justify-between border-b border-gray-100 px-6 py-4 dark:border-dk-muted"
        >
          <div class="flex items-center gap-3">
            <h2 class="text-lg font-semibold text-gray-900 dark:text-white">
              {{ t("purchase.order_detail") }} #{{ orderId }}
            </h2>
            <!-- 当前状态标签 -->
            <span
              v-if="order?.OrderStatus"
              class="inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-semibold"
              :class="getStatusColorClass(order.OrderStatus)"
            >
              <span
                v-if="updatingStatus"
                class="inline-flex items-center gap-1"
              >
                <IconLoader2 :size="10" class="animate-spin" />
              </span>
              {{ getStatusLabel(order.OrderStatus) }}
            </span>
            <!-- 创建者 -->
            <span
              v-if="order?.UserID"
              class="ml-1 flex items-center gap-1.5 rounded-full border border-gray-200 bg-gray-50 px-2 py-0.5 text-xs text-gray-500 dark:border-dk-muted dark:bg-dk-base dark:text-gray-400"
            >
              <img
                :src="usersStore.getAvatarUrlFromUserID(order.UserID)"
                class="rounded-full object-cover"
                style="width:18px;height:18px;"
              />
              {{ usersStore.getUsernameFromUserID(order.UserID) }}
            </span>
          </div>
          <span class="text-sm text-gray-400">{{
            formatDate(order?.CreatedAt)
          }}</span>
        </div>

        <!-- 状态快捷切换按钮 -->
        <div
          class="flex flex-wrap gap-2 border-b border-gray-100 px-6 py-3 dark:border-dk-muted"
        >
          <span class="text-sm text-gray-500 dark:text-gray-400"
            >{{ t("purchase.change_status") }}:</span
          >
          <button
            v-for="opt in statusOptions.slice(0, 4)"
            :key="opt.value"
            class="inline-flex items-center gap-1 rounded-full border px-3 py-1 text-xs font-medium transition-all"
            :class="
              order?.OrderStatus === opt.value
                ? [getStatusColorClass(opt.value), 'border-transparent']
                : 'border-gray-200 text-gray-500 hover:border-gray-300 hover:bg-gray-50 dark:border-dk-muted dark:text-gray-400 dark:hover:bg-dk-base'
            "
            :disabled="updatingStatus"
            @click="openStatusDialog(opt.value)"
          >
            <IconCheck v-if="order?.OrderStatus === opt.value" :size="12" />
            {{ t("purchase." + opt.labelKey) }}
          </button>
          <!-- 异常状态右对齐 -->
          <span class="flex-1" />
          <button
            v-for="opt in statusOptions.slice(4)"
            :key="opt.value"
            class="inline-flex items-center gap-1 rounded-full border px-3 py-1 text-xs font-medium transition-all"
            :class="
              order?.OrderStatus === opt.value
                ? [getStatusColorClass(opt.value), 'border-transparent']
                : 'border-gray-200 text-gray-500 hover:border-gray-300 hover:bg-gray-50 dark:border-dk-muted dark:text-gray-400 dark:hover:bg-dk-base'
            "
            :disabled="updatingStatus"
            @click="openStatusDialog(opt.value)"
          >
            <IconCheck v-if="order?.OrderStatus === opt.value" :size="12" />
            {{ t("purchase." + opt.labelKey) }}
          </button>
        </div>

        <!-- Order Info -->
        <div class="space-y-4 px-6 py-5">
          <h4 class="text-sm font-semibold text-gray-500 dark:text-gray-400">
            {{ t("purchase.order_info") }}
          </h4>

          <div class="grid gap-4 sm:grid-cols-2">
            <div>
              <label class="mb-1 block text-xs font-medium text-gray-400">{{
                t("purchase_addorder.part_name")
              }}</label>
              <p class="font-medium text-gray-900 dark:text-white">
                {{ order?.Title || "-" }}
              </p>
            </div>

            <div>
              <label class="mb-1 block text-xs font-medium text-gray-400">{{
                t("purchase.link")
              }}</label>
              <div v-if="order?.Link" class="flex flex-wrap items-center gap-2">
                <a
                  :href="order.Link.trim().startsWith('http') ? order.Link.trim() : 'https://' + order.Link.trim()"
                  target="_blank"
                  class="max-w-[400px] truncate rounded bg-gray-100 px-3 py-1.5 text-xs text-blue-600 hover:bg-gray-200 dark:bg-dk-base dark:text-blue-400 dark:hover:bg-gray-800"
                  :title="order.Link"
                >
                  {{ order.Link }}
                </a>
                <button
                  class="inline-flex items-center gap-1 rounded bg-blue-100 px-3 py-1.5 text-xs font-medium text-blue-700 hover:bg-blue-200 dark:bg-blue-900/40 dark:text-blue-300 dark:hover:bg-blue-900/60"
                  @click="copyLink"
                >
                  <svg class="h-3.5 w-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" />
                  </svg>
                  {{ t('purchase.copy_link') }}
                </button>
                <button
                  class="inline-flex items-center gap-1 rounded px-2 py-1 text-xs text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800"
                  @click="openLink"
                >
                  <IconExternalLink :size="14" />
                  {{ t("purchase.open_link") }}
                </button>
              </div>
              <p v-else class="text-gray-400">-</p>
            </div>

            <div v-if="order?.Styles">
              <label class="mb-1 block text-xs font-medium text-gray-400">{{
                t("purchase_addorder.style_remarks")
              }}</label>
              <p class="text-gray-700 dark:text-gray-200">{{ order.Styles }}</p>
            </div>

            <div v-if="order?.Remark" class="sm:col-span-2">
              <label class="mb-1 block text-xs font-medium text-gray-400">{{
                t("purchase_addorder.remarks")
              }}</label>
              <p class="whitespace-pre-wrap text-gray-700 dark:text-gray-200">
                {{ order.Remark }}
              </p>
            </div>
          </div>
        </div>
      </div>

      <!-- 费用明细 -->
      <div
        class="rounded-xl border border-gray-200 bg-white shadow-lg dark:border-dk-muted dark:bg-dk-card"
      >
        <div class="border-b border-gray-100 px-6 py-4 dark:border-dk-muted">
          <h4 class="text-sm font-semibold text-gray-500 dark:text-gray-400">
            {{ t("purchase.cost_detail") }}
          </h4>
        </div>

        <div v-if="costs.length" class="overflow-x-auto px-0">
          <table class="w-full text-left text-sm">
            <thead>
              <tr
                class="border-b border-gray-100 bg-gray-50 text-gray-500 dark:border-dk-muted dark:bg-dk-base"
              >
                <th class="px-6 py-3 font-medium">
                  {{ t("purchase_addorder.fee_type") }}
                </th>
                <th class="px-6 py-3 font-medium">
                  {{ t("purchase_addorder.quantity") }}
                </th>
                <th class="px-6 py-3 font-medium">
                  {{ t("purchase.unit_price") }}
                </th>
                <th class="px-6 py-3 font-medium">
                  {{ t("purchase.total_price") }}
                </th>
                <th class="px-6 py-3 font-medium">
                  {{ t("purchase_addorder.currency") }}
                </th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="(item, idx) in costs"
                :key="idx"
                class="border-b border-gray-50 dark:border-dk-muted/50"
              >
                <td class="px-6 py-3 font-medium text-gray-800 dark:text-white">
                  {{ costTypeMap[item.CostType] || item.CostType }}
                </td>
                <td class="px-6 py-3 text-gray-600 dark:text-gray-300">
                  {{ item.Quantity }}
                </td>
                <td class="px-6 py-3 text-gray-600 dark:text-gray-300">
                  {{ formatPrice(item.Price) }}
                </td>
                <td class="px-6 py-3 font-medium text-gray-900 dark:text-white">
                  {{ formatPrice(item.Price * item.Quantity) }}
                </td>
                <td class="px-6 py-3 text-gray-600 dark:text-gray-300">
                  {{ currencyOptions[item.CurrencyType] || "-" }}
                </td>
              </tr>
            </tbody>
            <tfoot>
              <tr class="bg-gray-50 dark:bg-dk-base">
                <td
                  colspan="3"
                  class="px-6 py-3 text-sm font-semibold text-gray-600 dark:text-gray-300"
                >
                  {{ t("purchase.cost_total") }}
                </td>
                <td
                  class="px-6 py-3 text-base font-bold text-gray-900 dark:text-white"
                >
                  <!-- {{ costTotalYuan.toFixed(2) }} -->
                </td>
                <td class="px-6 py-3">
                  <span
                    v-for="g in costsByCurrency"
                    :key="g.currency"
                    class="mr-2 inline-block rounded bg-blue-100 px-1.5 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-900/40 dark:text-blue-300"
                  >
                    {{ g.currency }} {{ g.total }}
                  </span>
                </td>
              </tr>
            </tfoot>
          </table>
        </div>

        <div v-else class="px-6 py-8 text-center text-gray-400">
          {{ t("purchase.no_costs") }}
        </div>
      </div>

      <!-- 图片备注 -->
      <div
        class="rounded-xl border border-gray-200 bg-white shadow-lg dark:border-dk-muted dark:bg-dk-card"
      >
        <div class="border-b border-gray-100 px-6 py-4 dark:border-dk-muted">
          <h4 class="text-sm font-semibold text-gray-500 dark:text-gray-400">
            {{ t("purchase.photo_remarks") }}
          </h4>
        </div>

        <div v-if="photos.length" class="flex flex-wrap gap-3 px-6 py-5">
          <a
            v-for="photo in photos"
            :key="photo.ID"
            :href="getPhotoUrl(photo)"
            target="_blank"
            class="group relative block overflow-hidden rounded-lg border border-gray-200 dark:border-dk-muted"
            style="width: 120px; height: 120px"
          >
            <img
              :src="getPhotoUrl(photo)"
              :alt="photo.Name || 'photo'"
              class="h-full w-full object-cover transition-transform group-hover:scale-105"
            />
          </a>
        </div>

        <div
          v-else
          class="flex flex-col items-center justify-center gap-2 px-6 py-10 text-gray-400"
        >
          <IconPhoto :size="32" class="opacity-40" />
          <span class="text-sm">{{ t("purchase.no_photos") }}</span>
        </div>
      </div>

      <!-- 关联工单 -->
      <div class="rounded-xl border border-gray-200 bg-white shadow-lg dark:border-dk-muted dark:bg-dk-card">
        <div class="flex items-center justify-between border-b border-gray-100 px-6 py-4 dark:border-dk-muted">
          <h4 class="text-sm font-semibold text-gray-500 dark:text-gray-400">
            {{ t('work_order.list_title') }}
          </h4>

        </div>

        <!-- 已关联工单列表 -->
        <div v-if="workOrders.length > 0" class="space-y-2 px-6 py-4">
          <RouterLink
            v-for="wo in workOrders"
            :key="wo.id"
            :to="`/work_order/show/${wo.id}`"
            class="rounded-xl border border-gray-200 bg-white px-4 py-3 flex items-center justify-between gap-3 hover:shadow transition-shadow dark:border-dk-muted dark:bg-dk-base dark:hover:shadow-none"
          >
            <div class="flex items-center gap-3 min-w-0">
              <IconFile :size="16" class="text-blue-500 flex-shrink-0" />
              <span class="font-medium text-sm text-gray-900 truncate dark:text-white">#{{ wo.id }} {{ wo.title }}</span>
            </div>
            <span
              class="flex-shrink-0 rounded-full px-2.5 py-0.5 text-xs font-medium"
              :class="getWorkOrderStatusClass(wo.status)"
            >
              {{ getWorkOrderStatusLabel(wo.status) }}
            </span>
          </RouterLink>
        </div>
        <div v-else class="px-6 py-8 text-center text-sm text-gray-400">
          {{ t('warehouse.no_work_orders') }}
        </div>
      </div>

      <!-- 状态记录（Commit History） -->
      <div
        class="rounded-xl border border-gray-200 bg-white shadow-lg dark:border-dk-muted dark:bg-dk-card"
      >
        <div class="border-b border-gray-100 px-6 py-4 dark:border-dk-muted">

          <h4 class="text-sm font-semibold text-gray-500 dark:text-gray-400">
            {{ t("purchase.commit_history") }}
          </h4>
        </div>

        <div
          v-if="commits.length"
          class="divide-y divide-gray-50 px-6 py-2 dark:divide-dk-muted/50"
        >
          <div
            v-for="(commit, index) in commits"
            :key="commit.id"
            class="flex items-start gap-3 py-3 rounded-lg border border-gray-100 bg-gray-50/50 px-4 my-2 dark:border-dk-muted dark:bg-dk-base/30"
          >
            <!-- 左侧：头像 + 用户名 -->
            <div class="flex w-20 flex-shrink-0 flex-col items-center gap-1">
              <img
                :src="usersStore.getAvatarUrlFromUserID(commit.userId)"
                class="rounded-full border border-gray-200 object-cover dark:border-dk-muted"
                style="width:32px;height:32px;"
              />
              <span
                class="w-full truncate text-center"
                style="font-size:11px;color:var(--text-secondary,#6b7280);"
                :title="usersStore.getUsernameFromUserID(commit.userId)"
              >
                {{ usersStore.getUsernameFromUserID(commit.userId) }}
              </span>
            </div>

            <!-- 中间：时间线点 -->
            <div class="flex flex-shrink-0 flex-col items-center pt-1">
              <div
                class="h-3 w-3 rounded-full border-2 border-white dark:border-dk-base"
                :class="getStatusColorClass(commit.status)"
              />
            </div>

            <!-- 右侧：状态 + 备注 + 图片 -->
            <div class="flex-1 min-w-0">
              <div class="flex flex-wrap items-center gap-2">
                <span
                  class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium"
                  :class="getStatusColorClass(commit.status)"
                >
                  {{ getStatusLabel(commit.status) }}
                </span>
                <span
                  v-if="commit.action === 'create'"
                  class="text-xs text-gray-400"
                >
                  {{ t("purchase.commit_create") }}
                </span>
                <span v-else class="text-xs text-gray-400">
                  {{
                    commit.oldStatus
                      ? getStatusLabel(commit.oldStatus) + " → "
                      : ""
                  }}{{ getStatusLabel(commit.status) }}
                </span>
                <span class="ml-auto text-xs text-gray-400">{{
                  formatDate(commit.createdAt)
                }}</span>
                <!-- 删除按钮 -->
                <button
                  v-if="canDeleteCommit(commit, index)"
                  class="ml-2 rounded-lg border border-red-200 bg-red-50 px-3 py-1 text-xs font-medium text-red-600 transition-colors hover:bg-red-100 hover:border-red-300 dark:border-red-900/50 dark:bg-red-900/30 dark:text-red-400 dark:hover:bg-red-900/50"
                  @click="handleDeleteCommit(commit.id)"
                >
                  <IconTrash :size="14" class="mr-1 inline align-middle" />
                  删除
                </button>
              </div>
              <p
                v-if="commit.comment"
                class="mt-1 text-sm text-gray-600 dark:text-gray-300"
              >
                {{ commit.comment }}
              </p>
              <div
                v-if="commit.photos?.length"
                class="mt-2 flex flex-wrap gap-1.5"
              >
                <a
                  v-for="hash in commit.photos"
                  :key="hash"
                  :href="`/api/files/get/${hash}`"
                  target="_blank"
                  class="block overflow-hidden rounded border border-gray-200 dark:border-dk-muted transition-transform hover:scale-105"
                  style="width:48px;height:48px;"
                >
                  <img
                    :src="`/api/files/get/${hash}`"
                    class="h-full w-full object-cover"
                  />
                </a>
              </div>
            </div>
          </div>
        </div>

        <div v-else class="px-6 py-8 text-center text-sm text-gray-400">
          {{ t("purchase.no_commits") }}
        </div>
      </div>
    </div>
  </div>

  <!-- 状态变更弹窗 -->
  <Teleport to="body">
    <Transition name="fade">
      <div
        v-if="showStatusDialog"
        class="fixed inset-0 z-50 flex items-center justify-center bg-black/40 px-4"
        @click.self="closeStatusDialog"
      >
        <div
          class="w-full max-w-md rounded-xl border border-gray-200 bg-white shadow-2xl dark:border-dk-muted dark:bg-dk-card"
        >
          <!-- Header -->
          <div
            class="flex items-center justify-between border-b border-gray-100 px-5 py-4 dark:border-dk-muted"
          >
            <h3 class="font-semibold text-gray-900 dark:text-white">
              {{ t("purchase.change_status") }}
            </h3>
            <button
              class="rounded p-1 text-gray-400 hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-dk-base"
              @click="closeStatusDialog"
            >
              <IconX :size="18" />
            </button>
          </div>

          <!-- Body -->
          <div class="space-y-4 px-5 py-5">
            <!-- 新状态 -->
            <div>
              <label
                class="mb-2 block text-sm text-gray-500 dark:text-gray-400"
              >
                {{ t("purchase.status") }}
              </label>
              <div class="flex items-center gap-2">
                <span
                  class="inline-flex items-center gap-1 rounded-full px-3 py-1 text-sm font-semibold"
                  :class="getStatusColorClass(pendingStatus)"
                >
                  <IconLoader2
                    v-if="updatingStatus"
                    :size="12"
                    class="animate-spin"
                  />
                  <IconCheck v-else :size="12" />
                  {{ getStatusLabel(pendingStatus) }}
                </span>
              </div>
            </div>

            <!-- 变更备注 -->
            <div>
              <label
                class="mb-2 block text-sm text-gray-500 dark:text-gray-400"
              >
                {{ t("purchase.change_remark") }}
              </label>
              <textarea
                v-model="pendingComment"
                rows="3"
                class="w-full rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm text-gray-900 placeholder-gray-400 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 disabled:bg-gray-50 dark:border-dk-muted dark:bg-dk-base dark:text-white dark:placeholder-gray-500"
                :placeholder="t('purchase.commit_placeholder')"
                :disabled="updatingStatus"
                @keydown.ctrl.enter="confirmStatusChange"
              />
            </div>

            <!-- 变更图片 -->
            <div>
              <label
                class="mb-2 block text-sm text-gray-500 dark:text-gray-400"
              >
                {{ t("purchase.status_photos") }}
              </label>

              <!-- 隐藏的文件选择框 -->
              <input
                ref="photoInputRef"
                type="file"
                accept="image/*"
                multiple
                class="hidden"
                @change="handlePhotoChange"
              />

              <!-- 已选图片预览 -->
              <div
                v-if="pendingPhotos.length"
                class="mb-2 flex flex-wrap gap-2"
              >
                <div
                  v-for="p in pendingPhotos"
                  :key="p.tempId"
                  class="group relative overflow-hidden rounded-lg border border-gray-200 dark:border-dk-muted"
                  style="width: 60px; height: 60px"
                >
                  <img :src="p.url" class="h-full w-full object-cover" />
                  <!-- 上传中遮罩 -->
                  <div
                    v-if="p.uploading"
                    class="absolute inset-0 flex items-center justify-center bg-black/40"
                  >
                    <IconLoader2 :size="16" class="animate-spin text-white" />
                  </div>
                  <!-- 失败遮罩 -->
                  <div
                    v-else-if="p.error"
                    class="absolute inset-0 flex items-center justify-center bg-red-500/60"
                  >
                    <IconX :size="14" class="text-white" />
                  </div>
                  <!-- 移除按钮 -->
                  <button
                    v-if="!p.uploading"
                    class="absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 text-white opacity-0 transition-opacity group-hover:opacity-100"
                    @click="removePendingPhoto(p.tempId)"
                  >
                    <IconX :size="10" />
                  </button>
                </div>
              </div>

              <!-- 上传按钮 -->
              <button
                class="inline-flex items-center gap-1.5 rounded-lg border border-dashed border-gray-300 px-3 py-2 text-sm text-gray-500 transition-colors hover:border-blue-400 hover:text-blue-500 disabled:opacity-50 dark:border-dk-muted dark:text-gray-400 dark:hover:border-blue-500 dark:hover:text-blue-400"
                :disabled="
                  updatingStatus ||
                  pendingPhotos.filter((p) => !p.uploading).length >= 10
                "
                @click="openPhotoPicker"
              >
                <IconUpload :size="14" />
                {{ t("purchase.upload_photos") }}
              </button>
            </div>
          </div>

          <!-- Footer -->
          <div
            class="flex justify-end gap-3 border-t border-gray-100 px-5 py-4 dark:border-dk-muted"
          >
            <button
              class="rounded-lg border border-gray-200 px-4 py-2 text-sm font-medium text-gray-600 transition-colors hover:bg-gray-50 disabled:opacity-50 dark:border-dk-muted dark:text-gray-300 dark:hover:bg-dk-base"
              :disabled="updatingStatus"
              @click="closeStatusDialog"
            >
              {{ t("settings.cancel") }}
            </button>
            <button
              class="flex items-center gap-2 rounded-lg bg-blue-500 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-600 disabled:opacity-50"
              :disabled="updatingStatus"
              @click="confirmStatusChange"
            >
              <IconLoader2
                v-if="updatingStatus"
                :size="14"
                class="animate-spin"
              />
              {{ t("message.submit") }}
            </button>
          </div>
        </div>
      </div>
    </Transition>
  </Teleport>

  <!-- 删除进度确认弹窗 -->
  <ConfirmDialog
    v-model="showDeleteConfirm"
    :message="t('purchase.confirm_delete_commit')"
    danger
    @confirm="confirmDeleteCommit"
  />
</template>

<style scoped>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.15s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>
