<script setup lang="ts">
import { computed, reactive, ref } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { adminApi, type AdminAppraisalTaskDetail, type AdminFileAsset } from "../../api/admin";
import { showErrorToast, showInfoToast, withLoading } from "../../utils/feedback";

const loading = ref(false);
const submitting = ref(false);
const supplementSubmitting = ref(false);
const uploading = ref(false);
const pageReady = ref(false);
const loadError = ref("");
const detail = ref<AdminAppraisalTaskDetail | null>(null);
const taskId = ref(0);
const activeSection = ref<"result" | "supplement" | "zhongjian">("result");

const resultText = ref("");
const resultDesc = ref("");
const conditionGrade = ref("");
const conditionDesc = ref("");
const valuationMin = ref("");
const valuationMax = ref("");
const valuationDesc = ref("");
const externalRemark = ref("");
const internalRemark = ref("");
const zhongjianReportNo = ref("");
const productName = ref("");
const categoryName = ref("");
const brandName = ref("");
const color = ref("");
const sizeSpec = ref("");
const serialNo = ref("");
const zhongjianFiles = ref<AdminFileAsset[]>([]);
const evidenceFiles = ref<AdminFileAsset[]>([]);
const activePreviewVideo = ref<AdminFileAsset | null>(null);
const supplementForm = reactive({
  reason: "",
  deadline: "",
  items: [{ item_name: "", guide_text: "", is_required: true }],
});

const isZhongjian = computed(() => detail.value?.task_info.service_provider === "zhongjian");
const isTaskReadonly = computed(() => {
  const status = detail.value?.task_info.status || "";
  return status === "submitted" || status === "completed";
});
const internalTagNo = computed(() => detail.value?.task_info.internal_tag_no || "");
const resultSummary = computed(() => detail.value?.result_info.result_text || "暂未填写");
const reportSummary = computed(() => detail.value?.report_summary?.report_no || "");
type AppraisalTemplate = NonNullable<AdminAppraisalTaskDetail["appraisal_template"]>;

function hasConditionFields(template?: AppraisalTemplate | null) {
  return (template?.condition_options?.length || 0) > 0;
}

function hasValuationFields(template?: AppraisalTemplate | null) {
  return Boolean((template?.valuation_hint || "").trim());
}

const showConditionFields = computed(() => hasConditionFields(detail.value?.appraisal_template));
const showValuationFields = computed(() => hasValuationFields(detail.value?.appraisal_template));

function formatMoneyInput(value: string | number) {
  const num = Number(value || 0);
  return Number.isFinite(num) ? num : 0;
}

function hydrate(detailData: AdminAppraisalTaskDetail) {
  detail.value = detailData;
  activeSection.value = detailData.task_info.service_provider === "zhongjian"
    ? "zhongjian"
    : (detailData.supplement_task ? "supplement" : "result");

  resultText.value = detailData.result_info.result_text || "";
  resultDesc.value = detailData.result_info.result_desc || "";
  if (hasConditionFields(detailData.appraisal_template)) {
    conditionGrade.value = detailData.result_info.condition_grade || "";
    conditionDesc.value = detailData.result_info.condition_desc || "";
  } else {
    conditionGrade.value = "";
    conditionDesc.value = "";
  }
  if (hasValuationFields(detailData.appraisal_template)) {
    valuationMin.value = detailData.result_info.valuation_min ? String(detailData.result_info.valuation_min) : "";
    valuationMax.value = detailData.result_info.valuation_max ? String(detailData.result_info.valuation_max) : "";
    valuationDesc.value = detailData.result_info.valuation_desc || "";
  } else {
    valuationMin.value = "";
    valuationMax.value = "";
    valuationDesc.value = "";
  }
  externalRemark.value = detailData.result_info.external_remark || "";
  internalRemark.value = detailData.result_info.internal_remark || "";
  zhongjianReportNo.value = detailData.zhongjian_report?.report_no || "";
  productName.value = detailData.product_info.product_name || "";
  categoryName.value = detailData.product_info.category_name || "";
  brandName.value = detailData.product_info.brand_name || "";
  color.value = detailData.product_info.color || "";
  sizeSpec.value = detailData.product_info.size_spec || "";
  serialNo.value = detailData.product_info.serial_no || "";
  zhongjianFiles.value = [...(detailData.zhongjian_report?.files || [])];
  evidenceFiles.value = [...(detailData.result_info.attachments || [])];

  if (detailData.supplement_task) {
    supplementForm.reason = detailData.supplement_task.reason || "";
    supplementForm.deadline = detailData.supplement_task.deadline || "";
    supplementForm.items.splice(
      0,
      supplementForm.items.length,
      ...(detailData.supplement_task.items.length
        ? detailData.supplement_task.items.map((item) => ({
            item_name: item.item_name,
            guide_text: item.guide_text,
            is_required: item.is_required,
          }))
        : [{ item_name: "", guide_text: "", is_required: true }]),
    );
  } else {
    supplementForm.reason = "";
    supplementForm.deadline = "";
    supplementForm.items.splice(0, supplementForm.items.length, {
      item_name: "",
      guide_text: "",
      is_required: true,
    });
  }
}

async function fetchDetail() {
  if (!taskId.value) return;
  loading.value = true;
  if (!pageReady.value) {
    loadError.value = "";
  }
  try {
    const data = await adminApi.getAppraisalTaskDetail(taskId.value);
    hydrate(data);
    pageReady.value = true;
  } catch (error) {
    if (!pageReady.value) {
      loadError.value = "工单详情加载失败，请稍后重试。";
    }
    showErrorToast(error, "工单详情加载失败");
  } finally {
    loading.value = false;
  }
}

function addSupplementItem() {
  if (isTaskReadonly.value) {
    showInfoToast("当前任务已完成，不能再编辑");
    return;
  }
  supplementForm.items.push({ item_name: "", guide_text: "", is_required: true });
}

function removeSupplementItem(index: number) {
  if (isTaskReadonly.value) {
    showInfoToast("当前任务已完成，不能再编辑");
    return;
  }
  if (supplementForm.items.length === 1) {
    supplementForm.items[0].item_name = "";
    supplementForm.items[0].guide_text = "";
    supplementForm.items[0].is_required = true;
    return;
  }
  supplementForm.items.splice(index, 1);
}

async function removeEvidenceFile(fileUrl: string) {
  if (isTaskReadonly.value || !detail.value) {
    showInfoToast("当前任务已完成，不能再删除附件");
    return;
  }
  try {
    await adminApi.deleteAppraisalEvidenceFile(fileUrl, detail.value.task_info.id);
    evidenceFiles.value = evidenceFiles.value.filter((item) => item.file_url !== fileUrl);
    showInfoToast("附件已删除");
  } catch (error) {
    showErrorToast(error, "附件删除失败");
  }
}

async function removeZhongjianFile(fileUrl: string) {
  if (isTaskReadonly.value || !detail.value) {
    showInfoToast("当前任务已完成，不能再删除文件");
    return;
  }
  try {
    await adminApi.deleteAppraisalEvidenceFile(fileUrl, detail.value.task_info.id);
    zhongjianFiles.value = zhongjianFiles.value.filter((item) => item.file_url !== fileUrl);
    showInfoToast("文件已删除");
  } catch (error) {
    showErrorToast(error, "文件删除失败");
  }
}

function isImageAsset(item: AdminFileAsset) {
  return item.file_type === "image" || item.mime_type?.startsWith("image/");
}

function isVideoAsset(item: AdminFileAsset) {
  return item.file_type === "video" || item.mime_type?.startsWith("video/");
}

function attachmentTypeLabel(item: AdminFileAsset) {
  if (isImageAsset(item)) return "图片";
  if (isVideoAsset(item)) return "视频";
  return "附件";
}

function previewAttachment(files: AdminFileAsset[], item: AdminFileAsset) {
  if (isImageAsset(item)) {
    const urls = files.filter(isImageAsset).map((asset) => asset.file_url);
    uni.previewImage({ urls, current: item.file_url });
    return;
  }

  if (isVideoAsset(item)) {
    activePreviewVideo.value = item;
    return;
  }

  showInfoToast("当前附件暂不支持预览");
}

function closePreviewVideo() {
  activePreviewVideo.value = null;
}

function updateTemplatePoint(index: number, key: "point_value" | "point_remark", value: string) {
  if (isTaskReadonly.value) return;
  const template = detail.value?.appraisal_template;
  if (!template) return;
  const current = template.key_points[index];
  if (!current) return;
  current[key] = value;
}

function updateTemplatePointFromInput(
  index: number,
  key: "point_value" | "point_remark",
  event: Event,
) {
  const target = event.target as HTMLInputElement | HTMLTextAreaElement | null;
  updateTemplatePoint(index, key, target?.value || "");
}

function templateKeyPointsPayload() {
  return detail.value?.appraisal_template?.key_points?.map((item) => ({
    point_code: item.point_code,
    point_name: item.point_name,
    point_value: item.point_value || "",
    point_remark: item.point_remark || "",
  })) || [];
}

function returnToWorkOrders(message: string) {
  showInfoToast(message);
  setTimeout(() => {
    uni.switchTab({ url: "/pages/work-order/index" });
  }, 700);
}

function confirmPublishReport() {
  return new Promise<boolean>((resolve) => {
    uni.showModal({
      title: "提交确认",
      content: "是否已鉴定完成并确定发布报告？",
      cancelText: "取消",
      confirmText: "去绑定",
      success: (result) => resolve(Boolean(result.confirm)),
      fail: () => resolve(false),
    });
  });
}

function promptMaterialTagQrInput() {
  return new Promise<string>((resolve, reject) => {
    uni.showModal({
      title: "绑定验真吊牌",
      content: "本地预览无法直接扫码，请输入或粘贴吊牌二维码内容。",
      editable: true,
      placeholderText: "二维码内容 / 验真吊牌编号",
      cancelText: "取消",
      confirmText: "绑定",
      success: (result) => {
        if (!result.confirm) {
          reject(new Error("已取消绑定验真吊牌"));
          return;
        }

        const qrInput = String(result.content || "").trim();
        if (!qrInput) {
          reject(new Error("请输入验真吊牌二维码内容"));
          return;
        }

        resolve(qrInput);
      },
      fail: () => reject(new Error("已取消绑定验真吊牌")),
    });
  });
}

function scanMaterialTagQr() {
  return new Promise<string>((resolve, reject) => {
    uni.scanCode({
      scanType: ["barCode", "qrCode"],
      success: (result) => {
        const qrInput = String(result.result || "").trim();
        if (!qrInput) {
          reject(new Error("未识别到验真吊牌二维码"));
          return;
        }
        resolve(qrInput);
      },
      fail: () => {
        // #ifdef H5
        promptMaterialTagQrInput().then(resolve).catch(reject);
        // #endif
        // #ifndef H5
        reject(new Error("已取消绑定验真吊牌"));
        // #endif
      },
    });
  });
}

async function confirmAndScanMaterialTag() {
  const confirmed = await confirmPublishReport();
  if (!confirmed) {
    return "";
  }

  try {
    return await scanMaterialTagQr();
  } catch (error) {
    showErrorToast(error, "验真吊牌扫码失败");
    return "";
  }
}

async function chooseEvidenceImage() {
  if (isTaskReadonly.value || !detail.value) {
    showInfoToast("当前任务已完成，不能再上传附件");
    return;
  }
  try {
    const result = await uni.chooseImage({
      count: 9,
      sizeType: ["compressed"],
      sourceType: ["album", "camera"],
    });
    if (!result.tempFilePaths?.length) return;
    uploading.value = true;
    for (const filePath of result.tempFilePaths) {
      const asset = await adminApi.uploadAppraisalEvidenceFile(filePath, detail.value.task_info.id);
      evidenceFiles.value.push(asset);
    }
    showInfoToast("图片上传成功");
  } catch (error) {
    showErrorToast(error, "图片上传失败");
  } finally {
    uploading.value = false;
  }
}

async function chooseEvidenceVideo() {
  if (isTaskReadonly.value || !detail.value) {
    showInfoToast("当前任务已完成，不能再上传附件");
    return;
  }
  try {
    const result = await uni.chooseVideo({
      sourceType: ["album", "camera"],
    });
    const filePath = result.tempFilePath;
    if (!filePath) return;
    uploading.value = true;
    const asset = await adminApi.uploadAppraisalEvidenceFile(filePath, detail.value.task_info.id);
    evidenceFiles.value.push(asset);
    showInfoToast("视频上传成功");
  } catch (error) {
    showErrorToast(error, "视频上传失败");
  } finally {
    uploading.value = false;
  }
}

async function chooseZhongjianImage() {
  if (isTaskReadonly.value || !detail.value) {
    showInfoToast("当前任务已完成，不能再上传文件");
    return;
  }
  try {
    const result = await uni.chooseImage({
      count: 9,
      sizeType: ["compressed"],
      sourceType: ["album", "camera"],
    });
    if (!result.tempFilePaths?.length) return;
    uploading.value = true;
    for (const filePath of result.tempFilePaths) {
      const asset = await adminApi.uploadAppraisalEvidenceFile(filePath, detail.value.task_info.id);
      zhongjianFiles.value.push(asset);
    }
    showInfoToast("图片上传成功");
  } catch (error) {
    showErrorToast(error, "图片上传失败");
  } finally {
    uploading.value = false;
  }
}

async function chooseZhongjianVideo() {
  if (isTaskReadonly.value || !detail.value) {
    showInfoToast("当前任务已完成，不能再上传文件");
    return;
  }
  try {
    const result = await uni.chooseVideo({
      sourceType: ["album", "camera"],
    });
    const filePath = result.tempFilePath;
    if (!filePath) return;
    uploading.value = true;
    const asset = await adminApi.uploadAppraisalEvidenceFile(filePath, detail.value.task_info.id);
    zhongjianFiles.value.push(asset);
    showInfoToast("视频上传成功");
  } catch (error) {
    showErrorToast(error, "视频上传失败");
  } finally {
    uploading.value = false;
  }
}

async function submitResult(action: "save" | "submit") {
  if (!detail.value) return;
  if (isTaskReadonly.value) {
    showInfoToast("当前任务已完成，不能再提交");
    return;
  }
  if (isZhongjian.value) {
    showInfoToast("中检订单请切换到中检报告区");
    activeSection.value = "zhongjian";
    return;
  }

  if (action === "submit" && !resultText.value.trim()) {
    showInfoToast("请先填写鉴定结论");
    return;
  }

  const qrInput = action === "submit" ? await confirmAndScanMaterialTag() : "";
  if (action === "submit" && !qrInput) {
    return;
  }

  submitting.value = true;
  try {
    const conditionPayload = showConditionFields.value
      ? {
          condition_grade: conditionGrade.value.trim(),
          condition_desc: conditionDesc.value.trim(),
        }
      : {
          condition_grade: "",
          condition_desc: "",
        };
    const valuationPayload = showValuationFields.value
      ? {
          valuation_min: formatMoneyInput(valuationMin.value),
          valuation_max: formatMoneyInput(valuationMax.value),
          valuation_desc: valuationDesc.value.trim(),
        }
      : {
          valuation_min: 0,
          valuation_max: 0,
          valuation_desc: "",
        };

    await withLoading(action === "submit" ? "正在提交鉴定" : "正在保存鉴定", () =>
      adminApi.saveAppraisalTaskResult({
        id: detail.value!.task_info.id,
        action,
        product_info: {
          category_id: detail.value!.product_info.category_id,
          product_name: detail.value!.product_info.product_name,
          category_name: detail.value!.product_info.category_name,
          brand_name: detail.value!.product_info.brand_name,
          color: detail.value!.product_info.color,
          size_spec: detail.value!.product_info.size_spec,
          serial_no: detail.value!.product_info.serial_no,
        },
        result_text: resultText.value.trim(),
        result_desc: resultDesc.value.trim(),
        ...conditionPayload,
        ...valuationPayload,
        external_remark: externalRemark.value.trim(),
        internal_remark: internalRemark.value.trim(),
        attachments: evidenceFiles.value,
        key_points: templateKeyPointsPayload(),
        ...(qrInput ? { qr_input: qrInput } : {}),
      }),
    );
    if (action === "submit") {
      returnToWorkOrders("验真吊牌已绑定，报告已发布");
      return;
    }
    showInfoToast("鉴定已保存");
    await fetchDetail();
  } catch (error) {
    showErrorToast(error, action === "submit" ? "鉴定提交失败" : "鉴定保存失败");
  } finally {
    submitting.value = false;
  }
}

async function submitSupplement() {
  if (!detail.value) return;
  if (isTaskReadonly.value) {
    showInfoToast("当前任务已完成，不能再发起补资料");
    return;
  }
  const items = supplementForm.items.filter((item) => item.item_name.trim());
  if (!supplementForm.reason.trim()) {
    showInfoToast("请先填写补资料原因");
    return;
  }
  if (!items.length) {
    showInfoToast("请至少填写一项补资料要求");
    return;
  }

  supplementSubmitting.value = true;
  try {
    await adminApi.requestAppraisalTaskSupplement({
      id: detail.value.task_info.id,
      reason: supplementForm.reason.trim(),
      deadline: supplementForm.deadline.trim(),
      items: items.map((item) => ({
        item_name: item.item_name.trim(),
        guide_text: item.guide_text.trim(),
        is_required: item.is_required,
      })),
    });
    showInfoToast("已发起补资料要求");
    await fetchDetail();
  } catch (error) {
    showErrorToast(error, "发起补资料失败");
  } finally {
    supplementSubmitting.value = false;
  }
}

async function submitZhongjianReport() {
  if (!detail.value) return;
  if (isTaskReadonly.value) {
    showInfoToast("当前任务已完成，不能再提交");
    return;
  }
  if (!zhongjianReportNo.value.trim()) {
    showInfoToast("请填写中检报告编号");
    return;
  }
  if (!resultText.value.trim()) {
    showInfoToast("请填写鉴定结论");
    return;
  }
  if (!productName.value.trim() && !categoryName.value.trim() && !brandName.value.trim()) {
    showInfoToast("请先完善物品信息");
    return;
  }
  if (!zhongjianFiles.value.length) {
    showInfoToast("请至少上传 1 个中检报告文件");
    return;
  }

  const qrInput = await confirmAndScanMaterialTag();
  if (!qrInput) {
    return;
  }

  submitting.value = true;
  try {
    await adminApi.saveZhongjianAppraisalReport({
      id: detail.value.task_info.id,
      zhongjian_report_no: zhongjianReportNo.value.trim(),
      product_info: {
        category_id: detail.value.product_info.category_id,
        product_name: productName.value.trim(),
        category_name: categoryName.value.trim(),
        brand_name: brandName.value.trim(),
        color: color.value.trim(),
        size_spec: sizeSpec.value.trim(),
        serial_no: serialNo.value.trim(),
      },
      result_text: resultText.value.trim(),
      result_desc: resultDesc.value.trim(),
      attachments: evidenceFiles.value,
      key_points: templateKeyPointsPayload(),
      report_files: zhongjianFiles.value,
      qr_input: qrInput,
    });
    returnToWorkOrders("验真吊牌已绑定，报告已发布");
  } catch (error) {
    showErrorToast(error, "中检报告录入失败");
  } finally {
    submitting.value = false;
  }
}

function openReportDetail() {
  const reportId = Number(detail.value?.report_summary?.id || 0);
  if (!reportId) return;
  uni.navigateTo({ url: `/pages/report/detail?id=${reportId}` });
}

onLoad((options) => {
  taskId.value = Number(options?.id || 0);
  if (!taskId.value) {
    loadError.value = "缺少工单编号，无法查看详情。";
  }
});

onShow(() => {
  if (taskId.value && !pageReady.value) {
    void fetchDetail();
  }
});
</script>

<template>
  <view class="page">
    <view v-if="!pageReady && loading" class="empty">正在加载工单详情</view>
    <view v-else-if="!pageReady && loadError" class="empty">{{ loadError }}</view>

    <template v-else-if="detail">
      <view class="hero">
        <view class="eyebrow">鉴定工单</view>
        <view class="title">{{ detail.product_info.product_name || "待完善物品信息" }}</view>
        <view class="subtitle">{{ detail.task_info.order_no }} / {{ detail.task_info.appraisal_no }}</view>
      </view>

      <view class="card">
        <view class="row">
          <view>
            <view class="card-title">{{ detail.task_info.task_stage_text }} · {{ detail.task_info.status_text }}</view>
            <view class="card-desc">{{ detail.task_info.service_provider_text }} / {{ detail.task_info.assignee_name }}</view>
          </view>
          <text class="tag">{{ resultSummary }}</text>
        </view>
        <view class="meta-grid">
          <view class="meta-item">
            <view class="meta-label">SLA 截止</view>
            <view class="meta-value">{{ detail.task_info.sla_deadline || "-" }}</view>
          </view>
          <view class="meta-item">
            <view class="meta-label">开始时间</view>
            <view class="meta-value">{{ detail.task_info.started_at || "-" }}</view>
          </view>
          <view class="meta-item">
            <view class="meta-label">提交时间</view>
            <view class="meta-value">{{ detail.task_info.submitted_at || "-" }}</view>
          </view>
          <view class="meta-item">
            <view class="meta-label">报告摘要</view>
            <view class="meta-value">{{ reportSummary || "-" }}</view>
          </view>
          <view v-if="internalTagNo" class="meta-item meta-item--wide">
            <view class="meta-label">流转码编号</view>
            <view class="meta-value transfer-code-value">{{ internalTagNo }}</view>
          </view>
        </view>
      </view>

      <view v-if="isTaskReadonly" class="readonly-notice">
        当前工单已完成，鉴定内容和附件仅可查看。
      </view>

      <view class="card">
        <view class="segmented">
          <view :class="['segment', activeSection === 'result' ? 'segment--active' : '']" @click="activeSection = 'result'">鉴定结论</view>
          <view :class="['segment', activeSection === 'supplement' ? 'segment--active' : '']" @click="activeSection = 'supplement'">补资料</view>
          <view :class="['segment', activeSection === 'zhongjian' ? 'segment--active' : '']" @click="activeSection = 'zhongjian'">中检报告</view>
        </view>
      </view>

      <view v-if="activeSection === 'result' && !isZhongjian" class="card">
        <view class="card-title">鉴定结论</view>
        <view class="stack" style="margin-top: 18rpx">
          <input v-model="resultText" class="field" :disabled="isTaskReadonly" placeholder="结论，例如：正品 / 存疑" />
          <textarea v-model="resultDesc" class="textarea" :disabled="isTaskReadonly" placeholder="结论说明" />
          <template v-if="showConditionFields">
            <input v-model="conditionGrade" class="field" :disabled="isTaskReadonly" placeholder="成色评级" />
            <textarea v-model="conditionDesc" class="textarea" :disabled="isTaskReadonly" placeholder="成色说明" />
          </template>
          <template v-if="showValuationFields">
            <view class="meta-grid">
              <input v-model="valuationMin" class="field" :disabled="isTaskReadonly" placeholder="最低估值" />
              <input v-model="valuationMax" class="field" :disabled="isTaskReadonly" placeholder="最高估值" />
            </view>
            <textarea v-model="valuationDesc" class="textarea" :disabled="isTaskReadonly" placeholder="估值说明" />
          </template>
          <textarea v-model="externalRemark" class="textarea" :disabled="isTaskReadonly" placeholder="对外备注" />
          <textarea v-model="internalRemark" class="textarea" :disabled="isTaskReadonly" placeholder="内部备注" />
        </view>

        <view v-if="detail.appraisal_template?.key_points?.length" class="stack" style="margin-top: 20rpx">
          <view class="card-desc">模板项</view>
          <view v-for="(item, index) in detail.appraisal_template.key_points" :key="item.point_code" class="stack">
            <view class="meta-item">
              <view class="meta-label">{{ item.point_name }}</view>
              <view class="meta-value">{{ item.point_type }}{{ item.is_required ? " · 必填" : "" }}</view>
            </view>
            <input
              :value="item.point_value"
              class="field"
              :disabled="isTaskReadonly"
              :placeholder="`${item.point_name} 值`"
              @input="updateTemplatePointFromInput(index, 'point_value', $event)"
            />
            <textarea
              :value="item.point_remark"
              class="textarea"
              :disabled="isTaskReadonly"
              :placeholder="`${item.point_name} 说明`"
              @input="updateTemplatePointFromInput(index, 'point_remark', $event)"
            />
          </view>
        </view>

        <view class="card-desc evidence-title">证据附件</view>
        <view v-if="evidenceFiles.length" class="attachment-grid">
          <view v-for="item in evidenceFiles" :key="item.file_url" class="attachment-tile">
            <view class="attachment-preview" @click="previewAttachment(evidenceFiles, item)">
              <image v-if="isImageAsset(item)" class="attachment-thumb" :src="item.thumbnail_url || item.file_url" mode="aspectFill" />
              <template v-else-if="isVideoAsset(item)">
                <image v-if="item.thumbnail_url" class="attachment-thumb" :src="item.thumbnail_url" mode="aspectFill" />
                <view v-else class="attachment-video-thumb">
                  <text class="attachment-video-label">视频</text>
                </view>
              </template>
              <view v-else class="attachment-file-thumb">附件</view>
              <view v-if="isVideoAsset(item)" class="attachment-play" @click.stop="previewAttachment(evidenceFiles, item)">▶</view>
            </view>
            <view class="attachment-meta">
              <view class="attachment-name">{{ item.name || item.file_id }}</view>
              <view class="attachment-actions">
                <text class="attachment-type">{{ attachmentTypeLabel(item) }}</text>
                <text v-if="!isTaskReadonly" class="attachment-remove" @click.stop="removeEvidenceFile(item.file_url)">删除</text>
              </view>
            </view>
          </view>
        </view>
        <view v-if="!isTaskReadonly" class="upload-actions">
          <button class="action-button action-button--secondary" :disabled="uploading" @click="chooseEvidenceImage">
            <text class="action-symbol">+</text>
            <text>{{ uploading ? "上传中" : "添加图片" }}</text>
          </button>
          <button class="action-button action-button--secondary" :disabled="uploading" @click="chooseEvidenceVideo">
            <text class="action-symbol">+</text>
            <text>{{ uploading ? "上传中" : "添加视频" }}</text>
          </button>
        </view>

        <view v-if="!isTaskReadonly" class="form-actions">
          <button class="form-action form-action--secondary" :disabled="submitting" @click="submitResult('save')">保存</button>
          <button class="form-action form-action--primary" :disabled="submitting" @click="submitResult('submit')">提交</button>
        </view>
      </view>

      <view v-else-if="activeSection === 'supplement'" class="card">
        <view class="card-title">补资料</view>
        <view class="stack" style="margin-top: 18rpx">
          <textarea v-model="supplementForm.reason" class="textarea" :disabled="isTaskReadonly" placeholder="补资料原因" />
          <input v-model="supplementForm.deadline" class="field" :disabled="isTaskReadonly" placeholder="截止时间（可选）" />
          <view v-for="(item, index) in supplementForm.items" :key="index" class="stack">
            <input v-model="item.item_name" class="field" :disabled="isTaskReadonly" placeholder="补资料项名称" />
            <textarea v-model="item.guide_text" class="textarea" :disabled="isTaskReadonly" placeholder="补资料说明" />
            <view v-if="!isTaskReadonly" class="row">
              <text class="tag" :class="item.is_required ? 'tag--warning' : ''" @click="item.is_required = !item.is_required">
                {{ item.is_required ? "必传" : "选传" }}
              </text>
              <text class="tag tag--danger" @click="removeSupplementItem(index)">删除</text>
            </view>
          </view>
          <view v-if="!isTaskReadonly" class="form-actions">
            <button class="form-action form-action--secondary" @click="addSupplementItem">添加一项</button>
            <button class="form-action form-action--primary" :disabled="supplementSubmitting" @click="submitSupplement">发起补资料</button>
          </view>
        </view>
      </view>

      <view v-else class="card">
        <view class="card-title">中检报告</view>
        <view class="stack" style="margin-top: 18rpx">
          <view class="card-desc">报告展示信息</view>
          <input v-model="productName" class="field" :disabled="isTaskReadonly" placeholder="产品名称" />
          <input v-model="categoryName" class="field" :disabled="isTaskReadonly" placeholder="品类" />
          <input v-model="brandName" class="field" :disabled="isTaskReadonly" placeholder="品牌" />
          <view class="meta-grid">
            <input v-model="color" class="field" :disabled="isTaskReadonly" placeholder="颜色" />
            <input v-model="sizeSpec" class="field" :disabled="isTaskReadonly" placeholder="规格 / 尺寸" />
          </view>
          <input v-model="serialNo" class="field" :disabled="isTaskReadonly" placeholder="序列号 / 编码" />
          <textarea v-model="resultText" class="textarea" :disabled="isTaskReadonly" placeholder="鉴定结论" />
          <textarea v-model="resultDesc" class="textarea" :disabled="isTaskReadonly" placeholder="结论说明" />

          <view v-if="detail.appraisal_template?.key_points?.length" class="stack">
            <view class="card-desc">模板项</view>
            <view v-for="(item, index) in detail.appraisal_template.key_points" :key="`zhongjian-${item.point_code}`" class="stack">
              <view class="meta-item">
                <view class="meta-label">{{ item.point_name }}</view>
                <view class="meta-value">{{ item.point_type }}{{ item.is_required ? " · 必填" : "" }}</view>
              </view>
              <input
                :value="item.point_value"
                class="field"
                :disabled="isTaskReadonly"
                :placeholder="`${item.point_name} 值`"
                @input="updateTemplatePointFromInput(index, 'point_value', $event)"
              />
              <textarea
                :value="item.point_remark"
                class="textarea"
                :disabled="isTaskReadonly"
                :placeholder="`${item.point_name} 说明`"
                @input="updateTemplatePointFromInput(index, 'point_remark', $event)"
              />
            </view>
          </view>

          <view class="card-desc evidence-title">鉴定图片 / 视频</view>
          <view v-if="evidenceFiles.length" class="attachment-grid">
            <view v-for="item in evidenceFiles" :key="`zj-evidence-${item.file_url}`" class="attachment-tile">
              <view class="attachment-preview" @click="previewAttachment(evidenceFiles, item)">
                <image v-if="isImageAsset(item)" class="attachment-thumb" :src="item.thumbnail_url || item.file_url" mode="aspectFill" />
                <template v-else-if="isVideoAsset(item)">
                  <image v-if="item.thumbnail_url" class="attachment-thumb" :src="item.thumbnail_url" mode="aspectFill" />
                  <view v-else class="attachment-video-thumb">
                    <text class="attachment-video-label">视频</text>
                  </view>
                </template>
                <view v-else class="attachment-file-thumb">附件</view>
                <view v-if="isVideoAsset(item)" class="attachment-play" @click.stop="previewAttachment(evidenceFiles, item)">▶</view>
              </view>
              <view class="attachment-meta">
                <view class="attachment-name">{{ item.name || item.file_id }}</view>
                <view class="attachment-actions">
                  <text class="attachment-type">{{ attachmentTypeLabel(item) }}</text>
                  <text v-if="!isTaskReadonly" class="attachment-remove" @click.stop="removeEvidenceFile(item.file_url)">删除</text>
                </view>
              </view>
            </view>
          </view>
          <view v-if="!isTaskReadonly" class="upload-actions">
            <button class="action-button action-button--secondary" :disabled="uploading" @click="chooseEvidenceImage">
              <text class="action-symbol">+</text>
              <text>{{ uploading ? "上传中" : "添加鉴定图片" }}</text>
            </button>
            <button class="action-button action-button--secondary" :disabled="uploading" @click="chooseEvidenceVideo">
              <text class="action-symbol">+</text>
              <text>{{ uploading ? "上传中" : "添加鉴定视频" }}</text>
            </button>
          </view>

          <view class="card-desc">中检报告文件</view>
          <input v-model="zhongjianReportNo" class="field" :disabled="isTaskReadonly" placeholder="中检报告编号" />
          <view v-if="zhongjianFiles.length" class="attachment-grid">
            <view v-for="item in zhongjianFiles" :key="item.file_url" class="attachment-tile">
              <view class="attachment-preview" @click="previewAttachment(zhongjianFiles, item)">
                <image v-if="isImageAsset(item)" class="attachment-thumb" :src="item.thumbnail_url || item.file_url" mode="aspectFill" />
                <template v-else-if="isVideoAsset(item)">
                  <image v-if="item.thumbnail_url" class="attachment-thumb" :src="item.thumbnail_url" mode="aspectFill" />
                  <view v-else class="attachment-video-thumb">
                    <text class="attachment-video-label">视频</text>
                  </view>
                </template>
                <view v-else class="attachment-file-thumb">附件</view>
                <view v-if="isVideoAsset(item)" class="attachment-play" @click.stop="previewAttachment(zhongjianFiles, item)">▶</view>
              </view>
              <view class="attachment-meta">
                <view class="attachment-name">{{ item.name || item.file_id }}</view>
                <view class="attachment-actions">
                  <text class="attachment-type">{{ attachmentTypeLabel(item) }}</text>
                  <text v-if="!isTaskReadonly" class="attachment-remove" @click.stop="removeZhongjianFile(item.file_url)">删除</text>
                </view>
              </view>
            </view>
          </view>
          <view v-if="!isTaskReadonly" class="upload-actions">
            <button class="action-button action-button--secondary" :disabled="uploading" @click="chooseZhongjianImage">
              <text class="action-symbol">+</text>
              <text>{{ uploading ? "上传中" : "添加图片" }}</text>
            </button>
            <button class="action-button action-button--secondary" :disabled="uploading" @click="chooseZhongjianVideo">
              <text class="action-symbol">+</text>
              <text>{{ uploading ? "上传中" : "添加视频" }}</text>
            </button>
          </view>
          <view v-if="!isTaskReadonly || detail.report_summary?.id" class="form-actions" :class="detail.report_summary?.id && !isTaskReadonly ? '' : 'form-actions--single'">
            <button v-if="!isTaskReadonly" class="form-action form-action--primary" :disabled="submitting" @click="submitZhongjianReport">提交并发布</button>
            <button v-if="detail.report_summary?.id" class="form-action form-action--secondary" @click="openReportDetail">查看报告</button>
          </view>
        </view>
      </view>

      <view v-if="activePreviewVideo" class="video-preview-mask" @click="closePreviewVideo">
        <view class="video-preview-panel" @click.stop>
          <view class="video-preview-head">
            <text class="video-preview-title">{{ activePreviewVideo.name || "附件视频" }}</text>
            <text class="video-preview-close" @click="closePreviewVideo">关闭</text>
          </view>
          <video class="video-preview-player" :src="activePreviewVideo.file_url" :poster="activePreviewVideo.thumbnail_url || ''" controls autoplay />
        </view>
      </view>

      <view class="card">
        <view class="card-title">任务信息</view>
        <view class="meta-grid">
          <view class="meta-item">
            <view class="meta-label">订单号</view>
            <view class="meta-value">{{ detail.task_info.order_no }}</view>
          </view>
          <view class="meta-item">
            <view class="meta-label">鉴定单号</view>
            <view class="meta-value">{{ detail.task_info.appraisal_no }}</view>
          </view>
          <view class="meta-item">
            <view class="meta-label">服务类型</view>
            <view class="meta-value">{{ detail.task_info.service_provider_text }}</view>
          </view>
          <view class="meta-item">
            <view class="meta-label">处理人</view>
            <view class="meta-value">{{ detail.task_info.assignee_name }}</view>
          </view>
          <view v-if="internalTagNo" class="meta-item meta-item--wide">
            <view class="meta-label">流转码编号</view>
            <view class="meta-value transfer-code-value">{{ internalTagNo }}</view>
          </view>
        </view>
      </view>
    </template>
  </view>
</template>

<style scoped lang="scss">
.list {
  display: grid;
  gap: 14rpx;
}

.readonly-notice {
  margin: -6rpx 0 18rpx;
  padding: 18rpx 22rpx;
  border: 1px solid var(--work-border);
  border-radius: var(--work-radius-sm);
  background: var(--work-card-muted);
  color: var(--work-text-soft);
  font-size: 24rpx;
  font-weight: 700;
  line-height: 1.5;
}

.meta-item--wide {
  grid-column: 1 / -1;
}

.transfer-code-value {
  color: var(--work-warning);
  font-weight: 900;
  word-break: break-all;
}

.evidence-title {
  margin-top: 24rpx;
  color: var(--work-text);
  font-weight: 800;
}

.attachment-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14rpx;
  margin-top: 14rpx;
}

.attachment-tile {
  min-width: 0;
}

.attachment-preview {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  overflow: hidden;
  border: 1px solid var(--work-border);
  border-radius: var(--work-radius-sm);
  background: var(--work-card-muted);
}

.attachment-thumb {
  display: block;
  width: 100%;
  height: 100%;
}

.attachment-video-thumb,
.attachment-file-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

.attachment-video-thumb {
  background: linear-gradient(135deg, #f8fafc 0%, #e8edf3 100%);
  color: var(--work-text);
}

.attachment-video-label {
  font-size: 24rpx;
  font-weight: 900;
}

.attachment-file-thumb {
  color: var(--work-text-soft);
  font-size: 24rpx;
  font-weight: 800;
}

.attachment-play {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 54rpx;
  height: 54rpx;
  margin-left: -27rpx;
  margin-top: -27rpx;
  border-radius: 50%;
  background: rgba(32, 33, 36, 0.72);
  color: #ffffff;
  font-size: 28rpx;
  line-height: 54rpx;
  text-align: center;
}

.attachment-meta {
  min-width: 0;
  margin-top: 8rpx;
}

.attachment-name {
  min-width: 0;
  overflow: hidden;
  color: var(--work-text);
  font-size: 22rpx;
  font-weight: 700;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attachment-actions {
  display: flex;
  align-items: center;
  gap: 8rpx;
  margin-top: 6rpx;
}

.attachment-type,
.attachment-remove {
  flex: 0 0 auto;
  min-height: 34rpx;
  padding: 0 10rpx;
  border-radius: var(--work-radius-pill);
  font-size: 20rpx;
  font-weight: 700;
  line-height: 34rpx;
  white-space: nowrap;
}

.attachment-type {
  background: var(--work-info-soft);
  color: var(--work-info);
}

.attachment-remove {
  background: var(--work-danger-soft);
  color: var(--work-danger);
}

.upload-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16rpx;
  margin-top: 16rpx;
}

.action-button,
.form-action {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 88rpx;
  padding: 0 22rpx;
  border: 1px solid transparent;
  border-radius: var(--work-radius-sm);
  font-size: 28rpx;
  font-weight: 800;
  line-height: 1;
}

.action-button::after,
.form-action::after {
  border: 0;
}

.action-button[disabled],
.form-action[disabled] {
  opacity: 0.56;
}

.action-button--secondary {
  justify-content: flex-start;
  gap: 12rpx;
  border-color: var(--work-border);
  background: var(--work-card-muted);
  color: var(--work-text);
}

.action-symbol {
  width: 36rpx;
  height: 36rpx;
  border-radius: 50%;
  background: #ffffff;
  color: var(--work-accent-deep);
  font-size: 30rpx;
  font-weight: 800;
  line-height: 34rpx;
  text-align: center;
}

.form-actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
  gap: 16rpx;
  margin-top: 24rpx;
}

.form-actions--single {
  grid-template-columns: 1fr;
}

.form-action--secondary {
  border-color: var(--work-border);
  background: #ffffff;
  color: var(--work-text);
}

.form-action--primary {
  border-color: var(--work-accent);
  background: var(--work-accent);
  color: #ffffff;
}

.video-preview-mask {
  position: fixed;
  z-index: 20;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32rpx;
  background: rgba(0, 0, 0, 0.58);
}

.video-preview-panel {
  width: 100%;
  overflow: hidden;
  border-radius: var(--work-radius);
  background: #ffffff;
}

.video-preview-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18rpx;
  padding: 22rpx 24rpx;
}

.video-preview-title {
  min-width: 0;
  overflow: hidden;
  color: var(--work-text);
  font-size: 28rpx;
  font-weight: 800;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.video-preview-close {
  flex: 0 0 auto;
  color: var(--work-info);
  font-size: 26rpx;
  font-weight: 800;
}

.video-preview-player {
  display: block;
  width: 100%;
  height: 58vh;
  background: #000000;
}
</style>
