import { useEffect, useRef, useState } from 'react';
import * as pdfjsLib from 'pdfjs-dist';
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.min.mjs?url';

import type { OutputTongyishuFileInfo, OutputTijianPdfFileInfo, OutputPhysicalExamItemInfo } from '../../api';
import {
  signInMedicalExamCenter,
  submitTongyishuSign,
  submitDaojiandanSign,
  editDaojiandanPrintStatus,
  submitAddItemBillSign,
  getTijianPdfFile,
  getTongyishuPdf,
  getDaojiandanPdf,
  getExamOptionalItemList,
  removeOptionalPackage,
  getExamOptionRecordList,
} from '../../api';
import type { SignaturePadHandle } from '../ui';
import { Button, SignaturePad } from '../ui';

// Polyfill for Promise.withResolvers
if (typeof (Promise as any).withResolvers === 'undefined') {
  (Promise as any).withResolvers = function <T>() {
    let resolve!: (value: T | PromiseLike<T>) => void;
    let reject!: (reason?: any) => void;
    const promise = new Promise<T>((res, rej) => {
      resolve = res;
      reject = rej;
    });
    return { promise, resolve, reject };
  };
}

// 配置 PDF.js worker
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;

interface ExamSignPanelProps {
  examId?: number;
  onBusyChange?: (busy: boolean) => void;
}

export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
  const [idCardFile, setIdCardFile] = useState<File | null>(null);
  const [previewImage, setPreviewImage] = useState<string | null>(null);
  const [showImagePreview, setShowImagePreview] = useState(false);
  const [signLoading, setSignLoading] = useState(false);
  const [message, setMessage] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement | null>(null);
  const [consentList, setConsentList] = useState<OutputTongyishuFileInfo[]>([]);
  const [consentLoading, setConsentLoading] = useState(false);
  const [previewPdf, setPreviewPdf] = useState<OutputTongyishuFileInfo | null>(null);
  const [showSignature, setShowSignature] = useState(false);
  const signaturePadRef = useRef<SignaturePadHandle | null>(null);
  const [submitLoading, setSubmitLoading] = useState(false);
  const [submitMessage, setSubmitMessage] = useState<string | null>(null);
  const [signedCombinationCodes, setSignedCombinationCodes] = useState<number[]>([]);
  const [pdfData, setPdfData] = useState<ArrayBuffer | null>(null);
  const [pdfReady, setPdfReady] = useState(false);
  const [pdfLoading, setPdfLoading] = useState(false);
  const [pdfBlobUrl, setPdfBlobUrl] = useState<string | null>(null);
  const canvasContainerRef = useRef<HTMLDivElement>(null);

  // 导检单相关状态
  const [daojiandanUrl, setDaojiandanUrl] = useState<string | null>(null);
  const [isDaojiandanSigned, setIsDaojiandanSigned] = useState(false); // 导检单是否已签名
  const [showDaojiandanSignature, setShowDaojiandanSignature] = useState(false);
  const daojiandanSignaturePadRef = useRef<SignaturePadHandle | null>(null);
  const [daojiandanSubmitLoading, setDaojiandanSubmitLoading] = useState(false);
  const [daojiandanSubmitMessage, setDaojiandanSubmitMessage] = useState<string | null>(null);
  const [showDaojiandanPreview, setShowDaojiandanPreview] = useState(false);
  const [daojiandanPdfData, setDaojiandanPdfData] = useState<ArrayBuffer | null>(null);
  const [daojiandanPdfLoading, setDaojiandanPdfLoading] = useState(false);
  const daojiandanCanvasContainerRef = useRef<HTMLDivElement>(null);
  const [showAddItemBillPreview, setShowAddItemBillPreview] = useState(false);
  const [showAddItemBillSignature, setShowAddItemBillSignature] = useState(false);
  const addItemBillSignaturePadRef = useRef<SignaturePadHandle | null>(null);
  const [addItemBillSubmitLoading, setAddItemBillSubmitLoading] = useState(false);
  const [addItemBillSubmitMessage, setAddItemBillSubmitMessage] = useState<string | null>(null);
  type AddItemBillItem = {
    pdf_sort: number;
    combinationCode: string;
    payment_status?: string | null;
    payment_status_name?: string | null;
    pdf_name: string;
    pdf_url: string;
    is_signed: boolean;
  };
  const [addItemBillList, setAddItemBillList] = useState<AddItemBillItem[]>([]);
  const [currentAddItemBill, setCurrentAddItemBill] = useState<AddItemBillItem | null>(null);
  const [addItemBillPdfData, setAddItemBillPdfData] = useState<ArrayBuffer | null>(null);
  const [addItemBillPdfLoading, setAddItemBillPdfLoading] = useState(false);
  const [batchPrintLoading, setBatchPrintLoading] = useState(false);
  const addItemBillCanvasContainerRef = useRef<HTMLDivElement>(null);

  // 可选项目列表相关状态
  const [optionalItemList, setOptionalItemList] = useState<OutputPhysicalExamItemInfo[]>([]);
  const [optionalItemLoading, setOptionalItemLoading] = useState(false);
  const [selectedOptionalItem, setSelectedOptionalItem] = useState<number | null>(null);
  // 是否已经确认过可选项目（如果后端已有记录，视为已确认）
  const [optionalConfirmed, setOptionalConfirmed] = useState(false);
  // 是否显示"请先确认体检项目，确认后不可修改"的提示
  const [showOptionalConfirmTip, setShowOptionalConfirmTip] = useState(false);
  // 跟踪当前 examId 是否已加载过导检单和知情同意书
  const pdfsLoadedForExamIdRef = useRef<number | null>(null);
  // 使用 ref 存储最新的可选项目状态，确保 refreshTijianPdfs 能读取到最新值
  const optionalItemListRef = useRef<OutputPhysicalExamItemInfo[]>([]);
  const optionalConfirmedRef = useRef<boolean>(false);

  const busy =
    signLoading ||
    submitLoading ||
    consentLoading ||
    pdfLoading ||
    daojiandanSubmitLoading ||
    addItemBillSubmitLoading ||
    batchPrintLoading ||
    optionalItemLoading;

  useEffect(() => {
    onBusyChange?.(busy);
    return () => onBusyChange?.(false);
  }, [busy, onBusyChange]);

  const refreshTijianPdfs = async (examIdValue: number, checkOptional: boolean = true) => {
    // 如果还有可选项目未确认，不执行接口请求（使用 ref 确保读取最新值）
    if (checkOptional && optionalItemListRef.current.length > 0 && !optionalConfirmedRef.current) {
      console.log('跳过 pdf-file-get 请求：可选项目未确认', { optionalItemListLength: optionalItemListRef.current.length, optionalConfirmed: optionalConfirmedRef.current });
      return;
    }

    setConsentLoading(true);

    try {
      const res = await getTijianPdfFile({ exam_id: examIdValue });
      const list: OutputTijianPdfFileInfo[] = res.Data || [];

      // 知情同意书列表（pdf_type = 2）
      const consentItems = list.filter((item) => item.pdf_type === 2);
      const mappedConsent: OutputTongyishuFileInfo[] = consentItems.map((item) => ({
        pdf_name: item.pdf_name || '',
        pdf_url: item.sign_pdf_url || item.pdf_url || '',
        combination_code: item.combination_code ?? null,
        is_signed: item.is_sign === 1,
      }));
      setConsentList(mappedConsent);

      // 已签名的组合码，用于一键打印等逻辑
      const signedCodes =
        consentItems
          .filter((item) => item.is_sign === 1 && item.combination_code !== null && item.combination_code !== undefined)
          .map((item) => Number(item.combination_code))
          .filter((n) => Number.isFinite(n)) || [];
      setSignedCombinationCodes(signedCodes);

      // 导检单（pdf_type = 1，取第一条）
      const daojiandan = list.find((item) => item.pdf_type === 1);
      if (daojiandan) {
        const url = daojiandan.sign_pdf_url || daojiandan.pdf_url || null;
        setDaojiandanUrl(url);
        setIsDaojiandanSigned(daojiandan.is_sign === 1);
      } else {
        // 如果 getTijianPdfFile 没有返回导检单，保留之前通过 getDaojiandanPdf 获取的URL（如果存在）
        // 不设置为 null，这样未签名的导检单也能显示"查看"按钮
        setDaojiandanUrl((prev) => (prev !== null ? prev : null));
        setIsDaojiandanSigned(false);
      }

      // 加项单（pdf_type = 3）：完全由新接口提供列表和签名状态（直接使用接口返回的字段）
      const addItemFromApi = list.filter((item) => item.pdf_type === 3);
      if (addItemFromApi.length > 0) {
        const addItemList: AddItemBillItem[] = addItemFromApi.map((item) => ({
          // 这里直接使用接口返回的 pdf_sort / combination_code / is_pay / is_pay_name
          pdf_sort: item.pdf_sort ?? 0,
          combinationCode: item.combination_code != null ? String(item.combination_code) : '',
          payment_status: item.is_pay != null ? String(item.is_pay) : null,
          payment_status_name: item.is_pay_name ?? null,
          pdf_name: item.pdf_name || '加项单',
          pdf_url: item.sign_pdf_url || item.pdf_url || '',
          is_signed: item.is_sign === 1,
        }));
        setAddItemBillList(addItemList);
        const unsigned = addItemList.find((bill) => bill.is_signed !== true);
        setCurrentAddItemBill(unsigned || addItemList[0] || null);
      } else {
        setAddItemBillList([]);
        setCurrentAddItemBill(null);
      }
    } catch (err) {
      console.error('获取体检PDF列表失败', err);
    } finally {
      setConsentLoading(false);
    }
  };

  // 加载可选项目列表 & 操作记录（优先使用记录，无记录时才调用可选项目接口）
  const loadOptionalItems = async () => {
    if (!examId) return;
    setOptionalItemLoading(true);
    try {
      // 先获取操作记录
      const recordRes = await getExamOptionRecordList({ exam_id: examId });


      console.log("操作记录请求", recordRes);
      // 若任意记录 is_abandon=1，则视为"已确定"（已做过弃选/确认动作），不可再确认
      let hasConfirmedRecord = false;
      let selectedFromRecord: number | null = null;
      let itemsFromRecord: OutputPhysicalExamItemInfo[] = [];

      if (recordRes.Status === 200 && recordRes.Data && recordRes.Data.length > 0) {
        hasConfirmedRecord = recordRes.Data.some((r) => r.is_abandon === 1);

        // 从记录中构建可选项目列表（只显示 is_abandon=0 的记录）
        itemsFromRecord = recordRes.Data
          .filter((r) => r.is_abandon === 0 && r.combination_code)
          .map((r) => {
            const codeNum = Number(r.combination_code);
            const packageNum = r.package_code ? Number(r.package_code) : null;
            if (!Number.isFinite(codeNum)) return null;
            return {
              combination_code: codeNum,
              combination_name: r.combination_name || '',
              package_code: Number.isFinite(packageNum) ? packageNum : null,
            } as OutputPhysicalExamItemInfo;
          })
          .filter((item): item is OutputPhysicalExamItemInfo => item !== null);

        // 预选：优先取 is_abandon=0 的组合码（若有）
        const selectedRecord = recordRes.Data.find(
          (r) => r.is_abandon === 0 && r.combination_code
        );
        if (selectedRecord?.combination_code) {
          const codeNum = Number(selectedRecord.combination_code);
          if (Number.isFinite(codeNum)) {
            selectedFromRecord = codeNum;
          }
        }
      }

      // 如果有记录，使用记录构建的列表；否则调用可选项目接口
      if (itemsFromRecord.length > 0) {
        // 根据 combination_code 去重，保留第一个出现的项目
        const uniqueItems = itemsFromRecord.filter((item, index, self) =>
          index === self.findIndex((t) => t.combination_code === item.combination_code)
        );
        setOptionalItemList(uniqueItems);
        optionalItemListRef.current = uniqueItems;

        if (selectedFromRecord != null && uniqueItems.some((i) => i.combination_code === selectedFromRecord)) {
          setSelectedOptionalItem(selectedFromRecord);
        } else {
          setSelectedOptionalItem(null);
        }
        // 只要存在可选项目：默认未确认；但若出现 is_abandon=1 记录，则视为已确定
        setOptionalConfirmed(hasConfirmedRecord);
        optionalConfirmedRef.current = hasConfirmedRecord;
        setShowOptionalConfirmTip(false);
      } else {
        // 没有记录，调用可选项目接口
        const listRes = await getExamOptionalItemList({ physical_exam_id: examId });

        if (listRes.Status === 200 && listRes.Data?.listOptionalItem) {
          const items = listRes.Data.listOptionalItem;
          // 根据 combination_code 去重，保留第一个出现的项目
          const uniqueItems = items.filter((item, index, self) =>
            index === self.findIndex((t) => t.combination_code === item.combination_code)
          );
          setOptionalItemList(uniqueItems);
          optionalItemListRef.current = uniqueItems;

          // 无历史记录，默认不选
          setSelectedOptionalItem(null);
          // 只要存在可选项目：默认未确认
          setOptionalConfirmed(false);
          optionalConfirmedRef.current = false;
          setShowOptionalConfirmTip(false);
        } else {
          setOptionalItemList([]);
          optionalItemListRef.current = [];
          setSelectedOptionalItem(null);
          setOptionalConfirmed(true);
          optionalConfirmedRef.current = true;
          setShowOptionalConfirmTip(false);
        }
      }
    } catch (err) {
      console.error('获取可选项目/记录失败', err);
      setOptionalItemList([]);
      optionalItemListRef.current = [];
      setSelectedOptionalItem(null);
      setOptionalConfirmed(true);
      optionalConfirmedRef.current = true;
      setShowOptionalConfirmTip(false);
    } finally {
      setOptionalItemLoading(false);
    }
  };

  // 加载 PDF 的逻辑（知情同意书、导检单）
  const loadPdfs = async (currentExamId: number) => {
    // 如果已经为当前 examId 加载过，不再重复加载
    if (pdfsLoadedForExamIdRef.current === currentExamId) {
      return;
    }

    // 使用 ref 确保读取最新值：如果没有可选项目，或者有可选项目但已确认，才加载导检单和知情同意书
    console.log('检查是否应该加载 PDF，ref 值：', {
      optionalItemListLength: optionalItemListRef.current.length,
      optionalConfirmed: optionalConfirmedRef.current
    });
    const shouldLoadPdfs = optionalItemListRef.current.length === 0 || optionalConfirmedRef.current;

    if (!shouldLoadPdfs) {
      console.log('跳过所有 PDF 接口请求：可选项目未确认', {
        optionalItemListLength: optionalItemListRef.current.length,
        optionalConfirmed: optionalConfirmedRef.current
      });
      return;
    }

    pdfsLoadedForExamIdRef.current = currentExamId;

    // 初始化时加载知情同意书
    const loadTongyishu = async () => {
      try {
        const res = await getTongyishuPdf({ exam_id: currentExamId });
        if (res.Status === 200 && res.Data?.list_pdf_url) {
          const list = res.Data.list_pdf_url;
          const mappedConsent: OutputTongyishuFileInfo[] = list.map((item) => ({
            pdf_name: item.pdf_name || '',
            pdf_url: item.pdf_url || '',
            combination_code: item.combination_code ?? null,
          }));
          setConsentList(mappedConsent);
        }
      } catch (err) {
        console.error('获取知情同意书失败', err);
      }
    };

    // 初始化时加载导检单（未签名版本也可以查看）
    const loadDaojiandan = async () => {
      try {
        console.log("未签名导检单请求");
        const res = await getDaojiandanPdf({ exam_id: currentExamId });
        if (res.Status === 200 && res.Data?.pdf_url) {
          setDaojiandanUrl((prev) => prev || res.Data?.pdf_url || null);
        }
      } catch (err) {
        console.error('获取导检单失败', err);
      }
    };

    // 加载 PDF
    loadTongyishu().then(() => {
      // 调用 refreshTijianPdfs 前再次检查可选项目状态（使用 ref 确保读取最新值）
      if (optionalItemListRef.current.length === 0 || optionalConfirmedRef.current) {
        refreshTijianPdfs(currentExamId, true);
      }
    });
    loadDaojiandan();
  };

  // 初始化：先检查可选项
  useEffect(() => {
    if (!examId) {
      setConsentList([]);
      setDaojiandanUrl(null);
      setIsDaojiandanSigned(false);
      optionalItemListRef.current = [];
      optionalConfirmedRef.current = true;
      pdfsLoadedForExamIdRef.current = null;
      setOptionalItemLoading(false);
      return;
    }

    // 先设置 loading 为 true
    setOptionalItemLoading(true);
    optionalItemListRef.current = [];
    optionalConfirmedRef.current = false;
    pdfsLoadedForExamIdRef.current = null;

    // 先检查可选项，选择完毕后才请求导检单接口
    loadOptionalItems().then(() => {
      // loadOptionalItems 完成后，ref 已经更新，直接调用加载 PDF 的逻辑
      console.log('loadOptionalItems 完成，ref 已更新', {
        optionalItemListLength: optionalItemListRef.current.length,
        optionalConfirmed: optionalConfirmedRef.current
      });
      // 直接调用加载 PDF 的逻辑，不依赖第二个 useEffect
      loadPdfs(examId);
    });
  }, [examId]);

  // 监听可选项目确认状态变化，确认后才加载导检单和知情同意书
  useEffect(() => {
    if (!examId) return;

    // 仅在可选项目状态从"未确认"变为"已确认"时，加载 PDF
    if (optionalConfirmed && optionalItemList.length > 0 && pdfsLoadedForExamIdRef.current !== examId) {
      console.log('可选项目已确认，开始加载 PDF');
      loadPdfs(examId);
    }
  }, [examId, optionalConfirmed]);

  const handlePickFile = () => {
    // 有可选项目但尚未确认时，禁止拍照并提示先确认项目
    if (optionalItemList.length > 0 && !optionalConfirmed) {
      setMessage('请先确认体检项目');
      setShowOptionalConfirmTip(true);
      return;
    }
    fileInputRef.current?.click();
  };

  const convertToJpg = async (file: File): Promise<File> => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (event) => {
        const img = new Image();
        img.onload = () => {
          const canvas = document.createElement('canvas');
          canvas.width = img.width;
          canvas.height = img.height;
          const ctx = canvas.getContext('2d');
          if (!ctx) {
            reject(new Error('无法创建画布上下文'));
            return;
          }
          ctx.drawImage(img, 0, 0);
          canvas.toBlob(
            (blob) => {
              if (!blob) {
                reject(new Error('图片转换失败'));
                return;
              }
              const jpgFile = new File([blob], 'id_card.jpg', { type: 'image/jpeg' });
              resolve(jpgFile);
            },
            'image/jpeg',
            0.92
          );
        };
        img.onerror = () => reject(new Error('图片加载失败'));
        img.src = event.target?.result as string;
      };
      reader.onerror = () => reject(new Error('文件读取失败'));
      reader.readAsDataURL(file);
    });
  };

  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    setMessage(null);

    try {
      const jpgFile = await convertToJpg(file);
      setIdCardFile(jpgFile);

      const reader = new FileReader();
      reader.onload = (event) => {
        setPreviewImage(event.target?.result as string);
      };
      reader.readAsDataURL(jpgFile);
    } catch (err) {
      console.error('图片转换失败', err);
      setMessage('图片处理失败，请重试');
    }

    e.target.value = '';
  };

  const handleSign = async () => {
    if (!idCardFile) {
      setMessage('请先上传身份证照片');
      return;
    }
    if (!examId) {
      setMessage('缺少体检ID');
      return;
    }

    // 如果存在可选项目但尚未确认，则不允许直接签到
    if (optionalItemList.length > 0 && !optionalConfirmed) {
      setMessage('请先确认体检项目');
      setShowOptionalConfirmTip(true);
      return;
    }

    setSignLoading(true);
    setMessage(null);
    try {
      const res = await signInMedicalExamCenter({ id_no_pic: idCardFile });
      const ok = res.Status === 200 && res.Data?.is_success === 0;
      if (ok) {
        setMessage('签到成功');
      } else {
        setMessage(res.Message || '签到失败');
      }
    } catch (err) {
      console.error(err);
      // setMessage('签到请求失败，请稍后重试');
    } finally {
      setSignLoading(false);
    }
  };

  // 确认当前选择的可选项目：移除未选择的项目
  const handleConfirmOptionalSelection = async () => {
    if (!examId) {
      setMessage('缺少体检ID');
      return;
    }
    if (optionalItemList.length === 0) {
      setOptionalConfirmed(true);
      optionalConfirmedRef.current = true;
      setShowOptionalConfirmTip(false);
      return;
    }
    if (selectedOptionalItem == null) {
      setMessage('请选择一个可选项目');
      setShowOptionalConfirmTip(true);
      return;
    }

    const unselectedCodes = optionalItemList
      .map((item) => item.combination_code)
      .filter((code): code is number => code != null && code !== selectedOptionalItem);

    // 没有未选项目需要移除，直接标记为已确认
    if (unselectedCodes.length === 0) {
      setOptionalConfirmed(true);
      optionalConfirmedRef.current = true;
      setShowOptionalConfirmTip(false);
      setMessage('可选项目已确定');
      setTimeout(() => setMessage(null), 3000);
      return;
    }

    setOptionalItemLoading(true);
    try {
      const combinationCodeIds = unselectedCodes.join(',');
      const res = await removeOptionalPackage({
        physical_exam_id: examId,
        combination_code_ids: combinationCodeIds,
      });
      if (res.Status === 200 && res.Data?.is_success === 1) {
        setOptionalConfirmed(true);
        optionalConfirmedRef.current = true;
        setShowOptionalConfirmTip(false);
        // 刷新操作记录列表（不再调用 optional-item-list 接口，避免恢复已移除的项目）
        await loadOptionalItems();
        setMessage('可选项目已确定');
        setTimeout(() => setMessage(null), 3000);
      } else {
        setMessage('可选项目确定失败：' + (res.Message || '未知错误'));
        setTimeout(() => setMessage(null), 3000);
      }
    } catch (err) {
      console.error('可选项目确定失败', err);
      setMessage('可选项目确定失败，请稍后重试');
      setTimeout(() => setMessage(null), 3000);
    } finally {
      setOptionalItemLoading(false);
    }
  };

  const handleSubmitSign = async () => {
    // 有可选项目但尚未确认时，禁止签名并提示先确认项目
    if (optionalItemList.length > 0 && !optionalConfirmed) {
      setSubmitMessage('请先确认体检项目');
      setShowOptionalConfirmTip(true);
      return;
    }

    if (!examId || !previewPdf?.combination_code) {
      setSubmitMessage('缺少必要信息，无法提交签名');
      return;
    }

    const dataUrl = signaturePadRef.current?.toDataURL('image/png');
    if (!dataUrl) {
      setSubmitMessage('请先完成签名');
      return;
    }

    setSubmitLoading(true);
    setSubmitMessage(null);
    try {
      const blob = await fetch(dataUrl).then((r) => r.blob());

      const res = await submitTongyishuSign({
        exam_id: examId,
        combination_code: previewPdf.combination_code,
        sign_file: blob,
      });

      if (res.Status === 200) {
        setSubmitMessage('签名提交成功');
        // 更新本地已签名组合码（立刻刷新按钮状态）
        setSignedCombinationCodes((prev) => {
          const code = Number(previewPdf.combination_code);
          if (!Number.isFinite(code)) return prev || [];
          return Array.from(new Set([...(prev || []), code]));
        });
        setTimeout(() => {
          setShowSignature(false);
          setPreviewPdf(null);
          setSubmitMessage(null);
          signaturePadRef.current?.clear();

          // 更新签名状态（刷新统一 PDF 列表）
          // 如果还有可选项目未确认，不执行接口请求（使用 ref 确保读取最新值）
          if (examId && (optionalItemListRef.current.length === 0 || optionalConfirmedRef.current)) {
            refreshTijianPdfs(examId, true);
          } else if (examId) {
            console.log('跳过 pdf-file-get 请求：可选项目未确认（签名成功后）', {
              optionalItemListLength: optionalItemListRef.current.length,
              optionalConfirmed: optionalConfirmedRef.current
            });
          }
        }, 500);
      } else {
        setSubmitMessage(res.Message || '签名提交失败');
      }
    } catch (err) {
      console.error('提交签名失败', err);
      setSubmitMessage('签名提交失败，请稍后重试');
    } finally {
      setSubmitLoading(false);
    }
  };

  // 加载 PDF 数据
  useEffect(() => {
    if (!previewPdf?.pdf_url) {
      setPdfData(null);
      setPdfBlobUrl(null);
      setPdfReady(false);
      return;
    }

    let objectUrl: string | null = null;
    setPdfReady(false);
    setPdfLoading(true);
    setPdfData(null);

    fetch(previewPdf.pdf_url)
      .then((resp) => {
        if (!resp.ok) throw new Error('获取PDF文件失败');
        return resp.blob();
      })
      .then((blob) => {
        objectUrl = URL.createObjectURL(blob);
        setPdfBlobUrl(objectUrl);
        return blob.arrayBuffer();
      })
      .then((arrayBuffer) => {
        setPdfData(arrayBuffer);
        setPdfLoading(false);
      })
      .catch((err) => {
        console.error('PDF 拉取失败', err);
        setPdfLoading(false);
      });

    return () => {
      if (objectUrl) {
        URL.revokeObjectURL(objectUrl);
      }
    };
  }, [previewPdf?.pdf_url]);

  // 渲染 PDF
  useEffect(() => {
    if (!pdfData || !canvasContainerRef.current) return;

    setPdfReady(false);

    const renderAllPages = async () => {
      try {
        const pdf = await pdfjsLib.getDocument({ data: pdfData }).promise;

        if (!canvasContainerRef.current) return;

        // 清空容器
        canvasContainerRef.current.innerHTML = '';

        const scale = 3;

        for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
          const page = await pdf.getPage(pageNum);
          const viewport = page.getViewport({ scale });

          const canvas = document.createElement('canvas');
          const context = canvas.getContext('2d');

          if (!context) continue;

          canvas.height = viewport.height;
          canvas.width = viewport.width;
          canvas.style.display = 'block';
          canvas.style.marginBottom = '10px';
          canvas.style.maxWidth = '100%';
          canvas.style.height = 'auto';
          canvas.className = 'mx-auto border rounded-lg shadow-sm';

          canvasContainerRef.current.appendChild(canvas);

          const renderContext = {
            canvasContext: context,
            viewport: viewport,
          } as any;

          await page.render(renderContext).promise;
        }

        setPdfReady(true);
      } catch (err) {
        console.error('PDF 渲染失败', err);
        setPdfLoading(false);
      }
    };

    renderAllPages();
  }, [pdfData]);

  // 加载导检单 PDF 数据
  useEffect(() => {
    if (!showDaojiandanPreview || !daojiandanUrl) {
      setDaojiandanPdfData(null);
      return;
    }

    let objectUrl: string | null = null;
    setDaojiandanPdfLoading(true);
    setDaojiandanPdfData(null);

    fetch(daojiandanUrl)
      .then((resp) => {
        if (!resp.ok) throw new Error('获取PDF文件失败');
        return resp.blob();
      })
      .then((blob) => {
        objectUrl = URL.createObjectURL(blob);
        return blob.arrayBuffer();
      })
      .then((arrayBuffer) => {
        setDaojiandanPdfData(arrayBuffer);
        setDaojiandanPdfLoading(false);
      })
      .catch((err) => {
        console.error('导检单PDF 拉取失败', err);
      });

    return () => {
      if (objectUrl) {
        URL.revokeObjectURL(objectUrl);
      }
    };
  }, [showDaojiandanPreview, daojiandanUrl]);

  // 渲染导检单 PDF
  useEffect(() => {
    if (!daojiandanPdfData || !daojiandanCanvasContainerRef.current) return;

    const renderAllPages = async () => {
      try {
        const pdf = await pdfjsLib.getDocument({ data: daojiandanPdfData }).promise;

        if (!daojiandanCanvasContainerRef.current) return;

        // 清空容器
        daojiandanCanvasContainerRef.current.innerHTML = '';

        const scale = 3.0;

        for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
          const page = await pdf.getPage(pageNum);
          const viewport = page.getViewport({ scale });

          const canvas = document.createElement('canvas');
          const context = canvas.getContext('2d');

          if (!context) continue;

          canvas.height = viewport.height;
          canvas.width = viewport.width;
          canvas.style.display = 'block';
          canvas.style.marginBottom = '10px';
          canvas.style.maxWidth = '100%';
          canvas.style.height = 'auto';
          canvas.className = 'mx-auto border rounded-lg shadow-sm';

          daojiandanCanvasContainerRef.current.appendChild(canvas);

          const renderContext = {
            canvasContext: context,
            viewport: viewport,
          } as any;

          await page.render(renderContext).promise;
        }

      } catch (err) {
        console.error('导检单PDF 渲染失败', err);
      }
    };

    renderAllPages();
  }, [daojiandanPdfData]);

  // 加载加项单 PDF 数据（当前选中的加项单）
  useEffect(() => {
    if (!showAddItemBillPreview || !currentAddItemBill?.pdf_url) {
      setAddItemBillPdfData(null);
      setAddItemBillPdfLoading(false);
      return;
    }

    let objectUrl: string | null = null;
    setAddItemBillPdfLoading(true);
    setAddItemBillPdfData(null);

    fetch(currentAddItemBill.pdf_url)
      .then((resp) => {
        if (!resp.ok) throw new Error('获取PDF文件失败');
        return resp.blob();
      })
      .then((blob) => {
        objectUrl = URL.createObjectURL(blob);
        return blob.arrayBuffer();
      })
      .then((arrayBuffer) => {
        setAddItemBillPdfData(arrayBuffer);
        setAddItemBillPdfLoading(false);
      })
      .catch((err) => {
        console.error('加项单PDF 拉取失败', err);
        setAddItemBillPdfLoading(false);
      });

    return () => {
      if (objectUrl) {
        URL.revokeObjectURL(objectUrl);
      }
    };
  }, [showAddItemBillPreview, currentAddItemBill?.pdf_url]);

  // 导检单预览：使用 pdfjs 渲染到 canvas
  useEffect(() => {
    if (!showDaojiandanPreview || !daojiandanUrl || !daojiandanCanvasContainerRef.current) return;

    const container = daojiandanCanvasContainerRef.current;
    let cancelled = false;

    const renderDaojiandan = async () => {
      try {
        container.innerHTML = '';

        const resp = await fetch(daojiandanUrl);
        if (!resp.ok) throw new Error('获取PDF文件失败');
        const blob = await resp.blob();
        const arrayBuffer = await blob.arrayBuffer();

        const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
        const scale = 3.0;

        for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
          if (cancelled) return;

          const page = await pdf.getPage(pageNum);
          const viewport = page.getViewport({ scale });

          const canvas = document.createElement('canvas');
          const context = canvas.getContext('2d');
          if (!context) continue;

          canvas.height = viewport.height;
          canvas.width = viewport.width;
          canvas.style.display = 'block';
          canvas.style.marginBottom = '10px';
          canvas.style.maxWidth = '100%';
          canvas.style.height = 'auto';
          canvas.className = 'mx-auto border rounded-lg shadow-sm';

          container.appendChild(canvas);

          const renderContext = {
            canvasContext: context,
            viewport: viewport,
          } as any;

          await page.render(renderContext).promise;
        }
      } catch (err) {
        console.error('导检单PDF 渲染失败', err);
      } finally {
        if (!cancelled) {
        }
      }
    };

    renderDaojiandan();

    return () => {
      cancelled = true;
      container.innerHTML = '';
    };
  }, [showDaojiandanPreview, daojiandanUrl]);

  // 加项单预览：使用 pdfjs 渲染到 canvas（依赖加载好的 addItemBillPdfData）
  useEffect(() => {
    if (!showAddItemBillPreview || !addItemBillPdfData || !addItemBillCanvasContainerRef.current) return;

    const container = addItemBillCanvasContainerRef.current;
    container.innerHTML = '';

    const renderAddItemBill = async () => {
      try {
        const pdf = await pdfjsLib.getDocument({ data: addItemBillPdfData }).promise;
        const scale = 3.0;

        for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
          const page = await pdf.getPage(pageNum);
          const viewport = page.getViewport({ scale });

          const canvas = document.createElement('canvas');
          const context = canvas.getContext('2d');
          if (!context) continue;

          canvas.height = viewport.height;
          canvas.width = viewport.width;
          canvas.style.display = 'block';
          canvas.style.marginBottom = '10px';
          canvas.style.maxWidth = '100%';
          canvas.style.height = 'auto';
          canvas.className = 'mx-auto border rounded-lg shadow-sm';

          container.appendChild(canvas);

          const renderContext = {
            canvasContext: context,
            viewport: viewport,
          } as any;

          await page.render(renderContext).promise;
        }
      } catch (err) {
        console.error('加项单PDF 渲染失败', err);
      }
    };

    renderAddItemBill();

    return () => {
      container.innerHTML = '';
    };
  }, [showAddItemBillPreview, addItemBillPdfData]);

  const handlePrint = () => {
    if (!pdfBlobUrl || !pdfReady || !canvasContainerRef.current || !previewPdf) return;

    // 创建打印窗口
    const printWindow = window.open('', '_blank');
    if (!printWindow) return;

    // 获取所有的 canvas
    const canvases = canvasContainerRef.current.querySelectorAll('canvas');

    // 构建打印页面
    printWindow.document.write(`
      <!DOCTYPE html>
      <html>
        <head>
          <title>${previewPdf.pdf_name || '知情同意书打印'}</title>
          <style>
            @media print {
              body {
                margin: 0;
                padding: 0;
              }
              .print-button, .close-button {
                display: none;
              }
              img {
                max-width: 100%;
                page-break-after: always;
                page-break-inside: avoid;
              }
              img:last-child {
                page-break-after: auto;
              }
            }
            body {
              margin: 0;
              padding: 0;
            }
            .print-button, .close-button {
              padding: 4px 12px;
              border: none;
              border-radius: 4px;
              cursor: pointer;
              font-size: 14px;
              transition: background-color 0.2s;
            }
            .print-button {
              background-color: #2563eb;
              color: white;
            }
            .print-button:hover {
              background-color: #1d4ed8;
            }
            .close-button {
              background-color: transparent;
              color: #374151;
            }
            .close-button:hover {
              background-color: #e5e7eb;
            }
            .button-container {
              position: fixed;
              top: 20px;
              right: 20px;
              display: flex;
              align-items: center;
              gap: 8px;
              z-index: 1000;
            }
            img {
              display: block;
              width: 100%;
              height: auto;
            }
          </style>
        </head>
        <body>
          <div class="button-container">
            <button class="close-button" onclick="window.close()">关闭</button>
            <button class="print-button" onclick="window.print(); setTimeout(() => window.close(), 1000);">打印</button>
          </div>
    `);

    // 将每个 canvas 转换为图片并添加到打印窗口
    canvases.forEach((canvas) => {
      const imgData = (canvas as HTMLCanvasElement).toDataURL('image/png');
      printWindow.document.write(`<img src="${imgData}" />`);
    });

    printWindow.document.write(`
        </body>
      </html>
    `);

    printWindow.document.close();

    // 等待图片加载完成后执行打印
    printWindow.onload = () => {
      printWindow.focus();
      setTimeout(() => {
        printWindow.print();
      }, 1000);
    };
  };

  const handleDirectPrint = async (pdfItem: OutputTongyishuFileInfo) => {
    if (!pdfItem.pdf_url) return;

    try {
      // 加载PDF
      const response = await fetch(pdfItem.pdf_url);
      if (!response.ok) throw new Error('获取PDF文件失败');
      const blob = await response.blob();
      const arrayBuffer = await blob.arrayBuffer();

      // 渲染PDF到临时canvas
      const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
      const scale = 1.0;
      const canvasImages: string[] = [];

      for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
        const page = await pdf.getPage(pageNum);
        const viewport = page.getViewport({ scale });

        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        if (!context) continue;

        canvas.height = viewport.height;
        canvas.width = viewport.width;

        const renderContext = {
          canvasContext: context,
          viewport: viewport,
        } as any;

        await page.render(renderContext).promise;
        canvasImages.push(canvas.toDataURL('image/png'));
      }

      // 创建打印窗口
      const printWindow = window.open('', '_blank');
      if (!printWindow) return;

      printWindow.document.write(`
        <!DOCTYPE html>
        <html>
          <head>
            <title>${pdfItem.pdf_name || '知情同意书打印'}</title>
            <style>
              @media print {
                body {
                  margin: 0;
                  padding: 0;
                }
                .print-button, .close-button {
                  display: none;
                }
                img {
                  max-width: 100%;
                  page-break-after: always;
                  page-break-inside: avoid;
                }
                img:last-child {
                  page-break-after: auto;
                }
              }
              body {
                margin: 0;
                padding: 0;
              }
              .print-button, .close-button {
                padding: 4px 12px;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                transition: background-color 0.2s;
              }
              .print-button {
                background-color: #2563eb;
                color: white;
              }
              .print-button:hover {
                background-color: #1d4ed8;
              }
              .close-button {
                background-color: transparent;
                color: #374151;
              }
              .close-button:hover {
                background-color: #e5e7eb;
              }
              .button-container {
                position: fixed;
                top: 20px;
                right: 20px;
                display: flex;
                align-items: center;
                gap: 8px;
                z-index: 1000;
              }
              img {
                display: block;
                width: 100%;
                height: auto;
              }
            </style>
          </head>
          <body>
            <div class="button-container">
              <button class="close-button" onclick="window.close()">关闭</button>
              <button class="print-button" onclick="window.print(); setTimeout(() => window.close(), 1000);">打印</button>
            </div>
      `);

      canvasImages.forEach((imgData) => {
        printWindow.document.write(`<img src="${imgData}" />`);
      });

      printWindow.document.write(`
          </body>
        </html>
      `);

      printWindow.document.close();

      // 等待图片加载完成后执行打印
      printWindow.onload = () => {
        printWindow.focus();
        setTimeout(() => {
          printWindow.print();
        }, 1000);
      };
    } catch (err) {
      console.error('打印失败', err);
      alert('打印失败，请稍后重试');
    }
  };

  // 导检单签名提交
  const handleSubmitDaojiandanSign = async () => {
    // 有可选项目但尚未确认时，禁止签名并提示先确认项目
    if (optionalItemList.length > 0 && !optionalConfirmed) {
      setDaojiandanSubmitMessage('请先确认体检项目');
      setShowOptionalConfirmTip(true);
      return;
    }

    if (!examId) {
      setDaojiandanSubmitMessage('缺少必要信息，无法提交签名');
      return;
    }

    const dataUrl = daojiandanSignaturePadRef.current?.toDataURL('image/png');
    if (!dataUrl) {
      setDaojiandanSubmitMessage('请先完成签名');
      return;
    }

    setDaojiandanSubmitLoading(true);
    setDaojiandanSubmitMessage(null);
    try {
      const blob = await fetch(dataUrl).then((r) => r.blob());

      const res = await submitDaojiandanSign({
        exam_id: examId,
        sign_file: blob,
      });

      if (res.Status === 200 && res.Data?.pdf_url) {
        setDaojiandanSubmitMessage('签名提交成功');
        const pdfUrlValue = res.Data.pdf_url;
        setDaojiandanUrl(pdfUrlValue);
        setIsDaojiandanSigned(true); // 签名成功后标记为已签名

        // 更新导检单打印状态
        try {
          await editDaojiandanPrintStatus({ exam_id: examId });
        } catch (err) {
          console.error('更新导检单打印状态失败', err);
        }

        setTimeout(() => {
          setShowDaojiandanSignature(false);
          setDaojiandanSubmitMessage(null);
          daojiandanSignaturePadRef.current?.clear();
          setShowDaojiandanPreview(true);
        }, 500);
      } else {
        setDaojiandanSubmitMessage(res.Message || '签名提交失败');
      }
    } catch (err) {
      console.error('提交签名失败', err);
      setDaojiandanSubmitMessage('签名提交失败，请稍后重试');
    } finally {
      setDaojiandanSubmitLoading(false);
    }
  };

  // 加项单签名提交（针对当前选中的加项单）
  const handleSubmitAddItemBillSign = async () => {
    if (!examId) {
      setAddItemBillSubmitMessage('缺少必要信息，无法提交签名');
      return;
    }

    if (!currentAddItemBill) {
      setAddItemBillSubmitMessage('没有可签名的加项单');
      return;
    }

    const dataUrl = addItemBillSignaturePadRef.current?.toDataURL('image/png');
    if (!dataUrl) {
      setAddItemBillSubmitMessage('请先完成签名');
      return;
    }

    // 记录当前正在签名的加项单，用于签名成功后重新选中它
    const justSignedCombinationCode = currentAddItemBill.combinationCode;

    setAddItemBillSubmitLoading(true);
    setAddItemBillSubmitMessage(null);
    try {
      const blob = await fetch(dataUrl).then((r) => r.blob());

      const res = await submitAddItemBillSign({
        exam_id: examId,
        pdf_sort: currentAddItemBill.pdf_sort,
        combinationCode: currentAddItemBill.combinationCode,
        sign_file: blob,
      });

      if (res.Status === 200) {
        setAddItemBillSubmitMessage('签名提交成功');

        // 签名成功后刷新统一 PDF 列表，获取最新的加项单签名状态和地址
        // 如果还有可选项目未确认，不执行接口请求（使用 ref 确保读取最新值）
        if (examId && (optionalItemListRef.current.length === 0 || optionalConfirmedRef.current)) {
          try {
            const refreshRes = await getTijianPdfFile({ exam_id: examId as number });
            const list: OutputTijianPdfFileInfo[] = refreshRes.Data || [];
            const addItemFromApi = list.filter((item) => item.pdf_type === 3);
            if (addItemFromApi.length > 0) {
              const addItemList: AddItemBillItem[] = addItemFromApi.map((item) => ({
                // 同样直接使用接口返回的字段，保持与 refreshTijianPdfs 一致
                pdf_sort: item.pdf_sort ?? 0,
                combinationCode: item.combination_code != null ? String(item.combination_code) : '',
                payment_status: item.is_pay != null ? String(item.is_pay) : null,
                payment_status_name: item.is_pay_name ?? null,
                pdf_name: item.pdf_name || '加项单',
                pdf_url: item.sign_pdf_url || item.pdf_url || '',
                is_signed: item.is_sign === 1,
              }));
              setAddItemBillList(addItemList);

              // 优先选中刚刚签名的那一张，其次选未签名的，其次第一张
              const justSigned = addItemList.find(
                (bill) => bill.combinationCode === justSignedCombinationCode
              );
              const unsigned = addItemList.find((bill) => bill.is_signed !== true);
              setCurrentAddItemBill(justSigned || unsigned || addItemList[0] || null);
            } else {
              setAddItemBillList([]);
              setCurrentAddItemBill(null);
            }
          } catch (e) {
            console.error('刷新加项单列表失败', e);
          }
        }

        setTimeout(() => {
          setShowAddItemBillSignature(false);
          setAddItemBillSubmitMessage(null);
          addItemBillSignaturePadRef.current?.clear();
          setShowAddItemBillPreview(true);
        }, 500);
      } else {
        setAddItemBillSubmitMessage(res.Message || '签名提交失败');
      }
    } catch (err) {
      console.error('提交签名失败', err);
      setAddItemBillSubmitMessage('签名提交失败，请稍后重试');
    } finally {
      setAddItemBillSubmitLoading(false);
    }
  };

  // 加项单直接打印
  const handleAddItemBillDirectPrint = async (target: AddItemBillItem | null) => {
    if (!target?.pdf_url) return;

    try {
      const response = await fetch(target.pdf_url);
      if (!response.ok) throw new Error('获取PDF文件失败');
      const blob = await response.blob();
      const arrayBuffer = await blob.arrayBuffer();

      const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
      const scale = 3.0;
      const canvasImages: string[] = [];

      for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
        const page = await pdf.getPage(pageNum);
        const viewport = page.getViewport({ scale });

        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        if (!context) continue;

        canvas.height = viewport.height;
        canvas.width = viewport.width;

        const renderContext = {
          canvasContext: context,
          viewport: viewport,
        } as any;

        await page.render(renderContext).promise;
        canvasImages.push(canvas.toDataURL('image/png'));
      }

      const printWindow = window.open('', '_blank');
      if (!printWindow) return;

      printWindow.document.write(`
        <!DOCTYPE html>
        <html>
          <head>
            <title>${target.pdf_name || '加项单打印'}</title>
            <style>
              @media print {
                body {
                  margin: 0;
                  padding: 0;
                }
                .print-button, .close-button {
                  display: none;
                }
                img {
                  max-width: 100%;
                  page-break-after: always;
                  page-break-inside: avoid;
                }
                img:last-child {
                  page-break-after: auto;
                }
              }
              body {
                margin: 0;
                padding: 0;
              }
              .print-button, .close-button {
                padding: 4px 12px;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                transition: background-color 0.2s;
              }
              .print-button {
                background-color: #2563eb;
                color: white;
              }
              .print-button:hover {
                background-color: #1d4ed8;
              }
              .close-button {
                background-color: transparent;
                color: #374151;
              }
              .close-button:hover {
                background-color: #e5e7eb;
              }
              .button-container {
                position: fixed;
                top: 20px;
                right: 20px;
                display: flex;
                align-items: center;
                gap: 8px;
                z-index: 1000;
              }
              img {
                display: block;
                width: 100%;
                height: auto;
              }
            </style>
          </head>
          <body>
            <div class="button-container">
              <button class="close-button" onclick="window.close()">关闭</button>
              <button class="print-button" onclick="window.print(); setTimeout(() => window.close(), 1000);">打印</button>
            </div>
      `);

      canvasImages.forEach((imgData) => {
        printWindow.document.write(`<img src="${imgData}" />`);
      });

      printWindow.document.write(`
          </body>
        </html>
      `);

      printWindow.document.close();

      printWindow.onload = () => {
        printWindow.focus();
        setTimeout(() => {
          printWindow.print();
        }, 1000);
      };
    } catch (err) {
      console.error('打印失败', err);
      alert('打印失败，请稍后重试');
    }
  };

  // 导检单直接打印
  const handleDaojiandanDirectPrint = async () => {
    if (!daojiandanUrl) return;

    try {
      const response = await fetch(daojiandanUrl);
      if (!response.ok) throw new Error('获取PDF文件失败');
      const blob = await response.blob();
      const arrayBuffer = await blob.arrayBuffer();

      const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
      const scale = 3.0;
      const canvasImages: string[] = [];

      for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
        const page = await pdf.getPage(pageNum);
        const viewport = page.getViewport({ scale });

        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        if (!context) continue;

        canvas.height = viewport.height;
        canvas.width = viewport.width;

        const renderContext = {
          canvasContext: context,
          viewport: viewport,
        } as any;

        await page.render(renderContext).promise;
        canvasImages.push(canvas.toDataURL('image/png'));
      }

      const printWindow = window.open('', '_blank');
      if (!printWindow) return;

      printWindow.document.write(`
        <!DOCTYPE html>
        <html>
          <head>
            <title>导检单打印</title>
            <style>
              @media print {
                body {
                  margin: 0;
                  padding: 0;
                }
                .print-button, .close-button {
                  display: none;
                }
                img {
                  max-width: 100%;
                  page-break-after: always;
                  page-break-inside: avoid;
                }
                img:last-child {
                  page-break-after: auto;
                }
              }
              body {
                margin: 0;
                padding: 0;
              }
              .print-button, .close-button {
                padding: 4px 12px;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                transition: background-color 0.2s;
              }
              .print-button {
                background-color: #2563eb;
                color: white;
              }
              .print-button:hover {
                background-color: #1d4ed8;
              }
              .close-button {
                background-color: transparent;
                color: #374151;
              }
              .close-button:hover {
                background-color: #e5e7eb;
              }
              .button-container {
                position: fixed;
                top: 20px;
                right: 20px;
                display: flex;
                align-items: center;
                gap: 8px;
                z-index: 1000;
              }
              img {
                display: block;
                width: 100%;
                height: auto;
              }
            </style>
          </head>
          <body>
            <div class="button-container">
              <button class="close-button" onclick="window.close()">关闭</button>
              <button class="print-button" onclick="window.print(); setTimeout(() => window.close(), 1000);">打印</button>
            </div>
      `);

      canvasImages.forEach((imgData) => {
        printWindow.document.write(`<img src="${imgData}" />`);
      });

      printWindow.document.write(`
          </body>
        </html>
      `);

      // 在关闭文档前设置 onload 事件
      printWindow.onload = () => {
        printWindow.focus();
        setTimeout(() => {
          printWindow.print();
        }, 1000);
      };

      printWindow.document.close();

      // 更新导检单打印状态（不阻塞打印流程）
      if (examId) {
        editDaojiandanPrintStatus({ exam_id: examId }).catch((err) => {
          console.error('更新导检单打印状态失败', err);
        });
      }
    } catch (err) {
      console.error('打印失败', err);
      alert('打印失败，请稍后重试');
    }
  };

  // 检查所有文档是否都已签名
  const checkAllSigned = () => {
    // 检查所有知情同意书是否都已签名
    const allConsentsSigned = consentList.every((item) => {
      if (item.combination_code === undefined || item.combination_code === null) return true;
      return signedCombinationCodes.includes(Number(item.combination_code));
    });

    // 检查导检单是否已签名（只有 localStorage 中的或签名后的才是已签名的）
    const daojiandanSigned = isDaojiandanSigned;

    return allConsentsSigned && consentList.length > 0 && daojiandanSigned;
  };

  // 一键打印所有文档
  const handleBatchPrint = async () => {
    if (busy || batchPrintLoading) return;

    setBatchPrintLoading(true);
    try {
      const allImages: string[] = [];
      const scale = 3.0;

      // 处理所有已签名的知情同意书
      for (const item of consentList) {
        if (item.combination_code === undefined || item.combination_code === null) continue;
        if (!signedCombinationCodes.includes(Number(item.combination_code))) continue;
        const targetUrl = item.pdf_url;
        if (!targetUrl) continue;

        try {
          const response = await fetch(targetUrl);
          if (!response.ok) continue;
          const blob = await response.blob();
          const arrayBuffer = await blob.arrayBuffer();

          const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;

          for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
            const page = await pdf.getPage(pageNum);
            const viewport = page.getViewport({ scale });

            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');
            if (!context) continue;

            canvas.height = viewport.height;
            canvas.width = viewport.width;

            const renderContext = {
              canvasContext: context,
              viewport: viewport,
            } as any;

            await page.render(renderContext).promise;
            allImages.push(canvas.toDataURL('image/png'));
          }
        } catch (err) {
          console.error(`处理知情同意书 ${item.pdf_name} 失败`, err);
        }
      }

      // 处理导检单
      if (daojiandanUrl) {
        try {
          const response = await fetch(daojiandanUrl);
          if (response.ok) {
            const blob = await response.blob();
            const arrayBuffer = await blob.arrayBuffer();

            const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;

            for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
              const page = await pdf.getPage(pageNum);
              const viewport = page.getViewport({ scale });

              const canvas = document.createElement('canvas');
              const context = canvas.getContext('2d');
              if (!context) continue;

              canvas.height = viewport.height;
              canvas.width = viewport.width;

              const renderContext = {
                canvasContext: context,
                viewport: viewport,
              } as any;

              await page.render(renderContext).promise;
              allImages.push(canvas.toDataURL('image/png'));
            }
          }
        } catch (err) {
          console.error('处理导检单失败', err);
        }
      }

      // 处理加项单（如果有且已签名）
      if (addItemBillList.length > 0) {
        try {
          for (const bill of addItemBillList) {
            if (!bill.pdf_url || bill.is_signed !== true) continue;
            const response = await fetch(bill.pdf_url);
            if (response.ok) {
              const blob = await response.blob();
              const arrayBuffer = await blob.arrayBuffer();

              const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;

              for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
                const page = await pdf.getPage(pageNum);
                const viewport = page.getViewport({ scale });

                const canvas = document.createElement('canvas');
                const context = canvas.getContext('2d');
                if (!context) continue;

                canvas.height = viewport.height;
                canvas.width = viewport.width;

                const renderContext = {
                  canvasContext: context,
                  viewport: viewport,
                } as any;

                await page.render(renderContext).promise;
                allImages.push(canvas.toDataURL('image/png'));
              }
            }
          }
        } catch (err) {
          console.error('处理加项单失败', err);
        }
      }

      if (allImages.length === 0) {
        alert('没有可打印的内容');
        return;
      }

      // 创建打印窗口
      const printWindow = window.open('', '_blank');
      if (!printWindow) {
        alert('无法打开打印窗口，请检查浏览器弹窗设置');
        return;
      }

      printWindow.document.write(`
        <!DOCTYPE html>
        <html>
          <head>
            <title>一键打印</title>
            <style>
              @media print {
                body {
                  margin: 0;
                  padding: 0;
                }
                .print-button, .close-button {
                  display: none;
                }
                img {
                  max-width: 100%;
                  page-break-after: always;
                  page-break-inside: avoid;
                }
                img:last-child {
                  page-break-after: auto;
                }
              }
              body {
                margin: 0;
                padding: 0;
              }
              .print-button, .close-button {
                padding: 4px 12px;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                transition: background-color 0.2s;
              }
              .print-button {
                background-color: #2563eb;
                color: white;
              }
              .print-button:hover {
                background-color: #1d4ed8;
              }
              .close-button {
                background-color: transparent;
                color: #374151;
              }
              .close-button:hover {
                background-color: #e5e7eb;
              }
              .button-container {
                position: fixed;
                top: 20px;
                right: 20px;
                display: flex;
                align-items: center;
                gap: 8px;
                z-index: 1000;
              }
              img {
                display: block;
                width: 100%;
                height: auto;
              }
            </style>
          </head>
          <body>
            <div class="button-container">
              <button class="close-button" onclick="window.close()">关闭</button>
              <button class="print-button" onclick="window.print(); setTimeout(() => window.close(), 1000);">打印</button>
            </div>
      `);

      allImages.forEach((imgData) => {
        printWindow.document.write(`<img src="${imgData}" />`);
      });

      printWindow.document.write(`
          </body>
        </html>
      `);

      printWindow.document.close();

      // 如果包含导检单，更新导检单打印状态
      if (examId && daojiandanUrl) {
        try {
          await editDaojiandanPrintStatus({ exam_id: examId });
        } catch (err) {
          console.error('更新导检单打印状态失败', err);
          // 不阻塞打印流程，仅记录错误
        }
      }

      // 等待图片加载完成后自动弹出打印窗口
      printWindow.onload = () => {
        printWindow.focus();
        setTimeout(() => {
          printWindow.print();
        }, 1000);
      };
    } catch (err) {
      console.error('一键打印失败', err);
      alert('一键打印失败，请稍后重试');
    } finally {
      setBatchPrintLoading(false);
    }
  };


  return (
    <div className='grid grid-cols-2 gap-4 text-sm'>
      <div className='p-4 rounded-2xl border bg-gray-50/60 flex flex-col gap-3'>
        <div className='font-medium'>身份证拍照与签到</div>
        <div className='text-xs text-gray-500'>拍照身份证后点击签到按钮完成签到。</div>
        <div className='flex items-center gap-3'>
          <Button className='py-1.5 px-3' onClick={handlePickFile} disabled={busy}>
            {idCardFile ? '重新拍照' : '拍照'}
          </Button>
          <input
            ref={fileInputRef}
            type='file'
            accept='image/*'
            capture='environment'
            className='hidden'
            onChange={handleFileChange}
          />
          {previewImage && (
            <div
              className='w-16 h-16 rounded-lg border-2 border-gray-300 overflow-hidden cursor-pointer hover:border-blue-500 transition-colors'
              onClick={() => setShowImagePreview(true)}
            >
              <img src={previewImage} alt='身份证预览' className='w-full h-full object-cover' />
            </div>
          )}
          <Button
            className='py-1.5 px-4 flex-1'
            onClick={handleSign}
            disabled={busy || !idCardFile || (optionalItemList.length > 0 && !optionalConfirmed)}
          >
            {signLoading ? '签到中...' : '签到'}
          </Button>
        </div>
        {message && (
          <div className={`text-xs ${message.includes('成功') ? 'text-green-600' : 'text-amber-600'}`}>{message}</div>
        )}
        {/* 可选项目列表 */}
        {optionalItemLoading ? (
          <div className='text-xs text-gray-500'>加载可选项目...</div>
        ) : optionalItemList.length > 0 ? (
          <div className='mt-2 space-y-2'>
            <div className='text-xs font-medium text-gray-700'>
              可选项目（必选其一）{optionalConfirmed ? '（已确定）' : ''}
            </div>
            <div className='max-h-32 overflow-y-auto custom-scroll space-y-1'>
              {optionalItemList.map((item) => {
                const combinationCode = item.combination_code;
                const isSelected =
                  combinationCode != null && combinationCode === selectedOptionalItem;
                return (
                  <label
                    key={combinationCode ?? `item-${item.package_code}`}
                    className='flex items-center gap-2 cursor-pointer text-xs'
                  >
                    <input
                      type='radio'
                      name='optional-item'
                      checked={isSelected}
                      onChange={() => {
                        if (combinationCode != null && !optionalConfirmed) {
                          setSelectedOptionalItem(combinationCode);
                        }
                      }}
                      disabled={busy || optionalConfirmed}
                      className='w-3 h-3'
                    />
                    <span className={isSelected ? 'text-blue-600 font-medium' : 'text-gray-700'}>
                      {item.combination_name || '未命名项目'}
                    </span>
                  </label>
                );
              })}
            </div>
            {!optionalConfirmed && (
              <div className='flex items-center gap-2'>
                <Button
                  className='py-1 px-3 text-xs bg-blue-600 hover:bg-blue-700 text-white'
                  onClick={handleConfirmOptionalSelection}
                  disabled={busy || selectedOptionalItem == null}
                >
                  确定选择
                </Button>
                {showOptionalConfirmTip && (
                  <span className='text-[11px] text-gray-500'>
                    请先确认体检项目，确认后不可修改
                  </span>
                )}
              </div>
            )}
          </div>
        ) : null}
      </div>
      {showImagePreview && previewImage && (
        <div className='fixed inset-0 z-[80] bg-black/90 flex items-center justify-center p-6' onClick={() => setShowImagePreview(false)}>
          <div className='relative max-w-full max-h-full'>
            <img src={previewImage} alt='身份证预览' className='max-w-full max-h-[90vh] object-contain' />
            <Button className='absolute top-4 right-4 bg-white/90 hover:bg-white' onClick={() => setShowImagePreview(false)}>
              关闭
            </Button>
          </div>
        </div>
      )}
      <div className='p-4 rounded-2xl border bg-gray-50/60 flex flex-col gap-3'>
        <div className='flex items-center justify-between'>
          <div className='font-medium'>体检知情同意书</div>
          {checkAllSigned() && (
            <Button
              className='py-1 px-3 bg-green-600 hover:bg-green-700 text-white text-xs'
              onClick={() => {
                // 有可选项目但尚未确认时，禁止打印并提示先确认项目
                if (optionalItemList.length > 0 && !optionalConfirmed) {
                  setMessage('请先确认体检项目');
                  setShowOptionalConfirmTip(true);
                  return;
                }
                handleBatchPrint();
              }}
              disabled={busy || batchPrintLoading}
            >
              {batchPrintLoading ? '加载中...' : '一键打印'}
            </Button>
          )}
        </div>
        {/* <div className='text-xs text-gray-500'>点击后弹出知情同意书全文及签名区域，签署完成后回到签到页面。</div> */}
        <div className='flex flex-col gap-2 max-h-96 overflow-y-auto custom-scroll'>
          {consentLoading && <div className='text-xs text-gray-500'>加载中...</div>}
          {/* {!consentLoading && consentMessage && <div className='text-xs text-amber-600'>{consentMessage}</div>} */}
          {!consentLoading && (consentList.length > 0 || true) && (
            <div className='space-y-2'>
              {consentList.map((item) => (
                <div
                  key={item.pdf_url || item.pdf_name}
                  className='flex items-center justify-between gap-3 p-2 rounded-xl border bg-white shadow-sm'
                >
                  <div className='text-sm text-gray-800 truncate flex items-center gap-2 relative pr-20'>
                    <span className='truncate'>{item.pdf_name.length > 10 ? item.pdf_name.slice(0, 10) + "..." : item.pdf_name}</span>
                    {item.combination_code !== undefined && signedCombinationCodes.includes(Number(item.combination_code)) && (
                      <img
                        src='/sign.png'
                        alt='已签名'
                        className='w-16 h-16 absolute right-2 top-1/2 -translate-y-1/2 pointer-events-none select-none'
                        loading='lazy'
                      />
                    )}
                  </div>
                  <div className='flex items-center gap-2'>
                    {item.combination_code !== undefined && signedCombinationCodes.includes(Number(item.combination_code)) && (
                      <Button
                        className='py-1.5 px-3 bg-blue-600 hover:bg-blue-700 text-white'
                        onClick={() => {
                          if (busy) return;
                          // 有可选项目但尚未确认时，禁止打印并提示先确认项目
                          if (optionalItemList.length > 0 && !optionalConfirmed) {
                            setMessage('请先确认体检项目');
                            setShowOptionalConfirmTip(true);
                            return;
                          }
                          handleDirectPrint(item);
                        }}
                        disabled={busy}
                      >
                        打印
                      </Button>
                    )}
                    <Button
                      className='py-1.5 px-3'
                      onClick={() => {
                        if (busy) return;
                        // 有可选项目但尚未确认时，禁止查看并提示先确认项目
                        if (optionalItemList.length > 0 && !optionalConfirmed) {
                          setMessage('请先确认体检项目');
                          setShowOptionalConfirmTip(true);
                          return;
                        }
                        setPreviewPdf(item);
                      }}
                      disabled={busy}
                    >
                      查看
                    </Button>
                  </div>
                </div>
              ))}
              {/* 只有在没有可选项目，或者有可选项目但已确认时，才显示导检单 */}
              {(optionalItemList.length === 0 || optionalConfirmed) && (
                <div className='flex items-center justify-between gap-3 p-2 rounded-xl border bg-white shadow-sm'>
                  <div className='text-sm text-gray-800 truncate flex items-center gap-2 relative pr-20'>
                    <span className='truncate'>导检单</span>
                    {isDaojiandanSigned && (
                      <img
                        src='/sign.png'
                        alt='已签名'
                        className='w-16 h-16 absolute right-2 top-1/2 -translate-y-1/2 pointer-events-none select-none'
                        loading='lazy'
                      />
                    )}
                  </div>
                  <div className='flex items-center gap-2'>
                    {isDaojiandanSigned ? (
                      // 已签名：显示打印和查看按钮
                      <>
                        <Button
                          className='py-1.5 px-3 bg-blue-600 hover:bg-blue-700 text-white'
                          onClick={() => {
                            if (busy) return;
                            // 有可选项目但尚未确认时，禁止打印并提示先确认项目
                            if (optionalItemList.length > 0 && !optionalConfirmed) {
                              setMessage('请先确认体检项目');
                              setShowOptionalConfirmTip(true);
                              return;
                            }
                            handleDaojiandanDirectPrint();
                          }}
                          disabled={busy}
                        >
                          打印
                        </Button>
                        <Button
                          className='py-1.5 px-3'
                          onClick={() => {
                            if (busy) return;
                            // 有可选项目但尚未确认时，禁止查看并提示先确认项目
                            if (optionalItemList.length > 0 && !optionalConfirmed) {
                              setMessage('请先确认体检项目');
                              setShowOptionalConfirmTip(true);
                              return;
                            }
                            setShowDaojiandanPreview(true);
                          }}
                          disabled={busy}
                        >
                          查看
                        </Button>
                      </>
                    ) : daojiandanUrl ? (
                      // 未签名但有导检单：显示查看和签名按钮
                      <>
                        <Button
                          className='py-1.5 px-3'
                          onClick={() => {
                            if (busy) return;
                            // 有可选项目但尚未确认时，禁止查看并提示先确认项目
                            if (optionalItemList.length > 0 && !optionalConfirmed) {
                              setMessage('请先确认体检项目');
                              setShowOptionalConfirmTip(true);
                              return;
                            }
                            setShowDaojiandanPreview(true);
                          }}
                          disabled={busy}
                        >
                          查看
                        </Button>
                        <Button
                          className='py-1.5 px-3'
                          onClick={() => {
                            if (busy) return;
                            // 有可选项目但尚未确认时，禁止签名并提示先确认项目
                            if (optionalItemList.length > 0 && !optionalConfirmed) {
                              setMessage('请先确认体检项目');
                              setShowOptionalConfirmTip(true);
                              return;
                            }
                            setShowDaojiandanSignature(true);
                          }}
                          disabled={busy}
                        >
                          签名
                        </Button>
                      </>
                    ) : (
                      // 没有导检单：只显示签名按钮
                      <Button
                        className='py-1.5 px-3'
                        onClick={() => {
                          if (busy) return;
                          // 有可选项目但尚未确认时，禁止签名并提示先确认项目
                          if (optionalItemList.length > 0 && !optionalConfirmed) {
                            setMessage('请先确认体检项目');
                            setShowOptionalConfirmTip(true);
                            return;
                          }
                          setShowDaojiandanSignature(true);
                        }}
                        disabled={busy}
                      >
                        签名
                      </Button>
                    )}
                  </div>
                </div>
              )}
              {/* 加项单列表（可能有多个） */}
              {addItemBillList.length > 0 &&
                addItemBillList.map((bill) => {
                  const isSigned = bill.is_signed === true;
                  const displayName =
                    bill.pdf_name && bill.pdf_name.length > 12 ? bill.pdf_name.slice(0, 12) + '...' : bill.pdf_name || '加项单';
                  return (
                    <div
                      key={bill.pdf_sort}
                      className='flex items-center justify-between gap-3 p-2 rounded-xl border bg-white shadow-sm'
                    >
                      <div className='text-sm text-gray-800 truncate flex items-center gap-2 relative pr-20'>
                        <span className='truncate'>
                          {displayName}
                          {typeof bill.pdf_sort === 'number' ? `` : ''}
                        </span>
                        {bill.payment_status_name && (
                          <span className='text-xs text-gray-500 whitespace-nowrap'>{bill.payment_status_name}</span>
                        )}
                        {isSigned && (
                          <img
                            src='/sign.png'
                            alt='已签名'
                            className='w-16 h-16 absolute right-2 top-1/2 -translate-y-1/2 pointer-events-none select-none'
                            loading='lazy'
                          />
                        )}
                      </div>
                      <div className='flex items-center gap-2'>
                        {isSigned && bill.pdf_url && (
                          <Button
                            className='py-1.5 px-3 bg-blue-600 hover:bg-blue-700 text-white'
                            onClick={() => {
                              if (busy) return;
                              handleAddItemBillDirectPrint(bill);
                            }}
                            disabled={busy}
                          >
                            打印
                          </Button>
                        )}
                        {bill.pdf_url && (
                          <Button
                            className='py-1.5 px-3'
                            onClick={() => {
                              if (busy) return;
                              setCurrentAddItemBill(bill);
                              setShowAddItemBillPreview(true);
                            }}
                            disabled={busy}
                          >
                            查看
                          </Button>
                        )}
                        {!isSigned && (
                          <Button
                            className='py-1.5 px-3'
                            onClick={() => {
                              if (busy) return;
                              setCurrentAddItemBill(bill);
                              setShowAddItemBillSignature(true);
                            }}
                            disabled={busy}
                          >
                            签名
                          </Button>
                        )}
                      </div>
                    </div>
                  );
                })}
            </div>
          )}
        </div>
      </div>
      {
        previewPdf && (
          <div className='fixed inset-0 z-[60] bg-black/75 flex flex-col'>
            <div className='flex items-center justify-between p-4 text-white bg-gray-900/80'>
              <div className='text-sm font-medium truncate pr-3'>{previewPdf.pdf_name}</div>
              <div className='flex items-center gap-2'>
                <Button
                  className='py-1 px-3 bg-blue-600 hover:bg-blue-700 text-white disabled:opacity-50 disabled:cursor-not-allowed'
                  onClick={() => {
                    // 有可选项目但尚未确认时，禁止打印并提示先确认项目
                    if (optionalItemList.length > 0 && !optionalConfirmed) {
                      setMessage('请先确认体检项目');
                      setShowOptionalConfirmTip(true);
                      return;
                    }
                    handlePrint();
                  }}
                  disabled={pdfLoading || !pdfReady || !pdfBlobUrl}
                >
                  打印
                </Button>
                <Button
                  className='py-1 px-3'
                  onClick={() => {
                    if (busy) return;
                    // 有可选项目但尚未确认时，禁止签名并提示先确认项目
                    if (optionalItemList.length > 0 && !optionalConfirmed) {
                      setMessage('请先确认体检项目');
                      setShowOptionalConfirmTip(true);
                      return;
                    }
                    setShowSignature(true);
                  }}
                  disabled={busy}
                >
                  签名
                </Button>
                <Button className='py-1 px-3' onClick={() => !busy && setPreviewPdf(null)} disabled={busy}>
                  关闭
                </Button>
              </div>
            </div>
            <div className='flex-1 bg-gray-100 overflow-auto'>
              {pdfLoading ? (
                <div className='flex items-center justify-center h-full text-white'>
                  <div>正在加载PDF...</div>
                </div>
              ) : pdfData ? (
                <div className='flex justify-center p-4'>
                  <div ref={canvasContainerRef} className='w-full' />
                </div>
              ) : (
                <div className='flex items-center justify-center h-full text-white'>
                  <div>PDF加载失败</div>
                </div>
              )}
            </div>
          </div>
        )
      }
      {
        showSignature && (
          <div className='fixed inset-0 z-[70] bg-black/80 flex items-center justify-center px-6'>
            <div className='bg-white rounded-2xl w-full max-w-3xl shadow-2xl p-4 flex flex-col gap-4'>
              <div className='flex items-center justify-between'>
                <div className='text-base font-semibold text-gray-900'>签署知情同意书</div>
                <div className='flex items-center gap-2'>
                  <Button className='py-1 px-3' onClick={() => setShowSignature(false)} disabled={busy}>
                    关闭
                  </Button>
                </div>
              </div>
              <div className='ui7-signature-wrapper border rounded-xl overflow-hidden bg-gray-50'>
                <SignaturePad
                  ref={signaturePadRef}
                  className='ui7-signature-canvas w-full h-72 bg-white touch-none'
                />
                <div className='flex items-center justify-between px-3 py-2 bg-gray-50 border-t'>
                  <div className='text-xs text-gray-500'>请在上方区域签名完成签到</div>
                  <Button className='ui7-clear-button py-1 px-3' onClick={() => signaturePadRef.current?.clear()} disabled={submitLoading}>
                    清除
                  </Button>
                </div>
              </div>
              {submitMessage && (
                <div className={`text-sm text-center ${submitMessage.includes('成功') ? 'text-green-600' : 'text-amber-600'}`}>{submitMessage}</div>
              )}
              <div className='flex items-center justify-end gap-3'>
                <Button
                  className='py-2 px-6'
                  onClick={() => {
                    setShowSignature(false);
                    setSubmitMessage(null);
                    signaturePadRef.current?.clear();
                  }}
                  disabled={submitLoading}
                >
                  取消
                </Button>
                <Button
                  className='py-2 px-6 bg-blue-600 text-white hover:bg-blue-700'
                  onClick={handleSubmitSign}
                  disabled={submitLoading}
                >
                  {submitLoading ? '提交中...' : '提交签名'}
                </Button>
              </div>
            </div>
          </div>
        )
      }
      {
        showDaojiandanSignature && (
          <div className='fixed inset-0 z-[70] bg-black/80 flex items-center justify-center px-6'>
            <div className='bg-white rounded-2xl w-full max-w-3xl shadow-2xl p-4 flex flex-col gap-4'>
              <div className='flex items-center justify-between'>
                <div className='text-base font-semibold text-gray-900'>签署导检单</div>
                <div className='flex items-center gap-2'>
                  <Button className='py-1 px-3' onClick={() => setShowDaojiandanSignature(false)} disabled={busy}>
                    关闭
                  </Button>
                </div>
              </div>
              <div className='ui7-signature-wrapper border rounded-xl overflow-hidden bg-gray-50'>
                <SignaturePad
                  ref={daojiandanSignaturePadRef}
                  className='ui7-signature-canvas w-full h-72 bg-white touch-none'
                />
                <div className='flex items-center justify-between px-3 py-2 bg-gray-50 border-t'>
                  <div className='text-xs text-gray-500'>请在上方区域签名</div>
                  <Button className='ui7-clear-button py-1 px-3' onClick={() => daojiandanSignaturePadRef.current?.clear()} disabled={daojiandanSubmitLoading}>
                    清除
                  </Button>
                </div>
              </div>
              {daojiandanSubmitMessage && (
                <div className={`text-sm text-center ${daojiandanSubmitMessage.includes('成功') ? 'text-green-600' : 'text-amber-600'}`}>{daojiandanSubmitMessage}</div>
              )}
              <div className='flex items-center justify-end gap-3'>
                <Button
                  className='py-2 px-6'
                  onClick={() => {
                    setShowDaojiandanSignature(false);
                    setDaojiandanSubmitMessage(null);
                    daojiandanSignaturePadRef.current?.clear();
                  }}
                  disabled={daojiandanSubmitLoading}
                >
                  取消
                </Button>
                <Button
                  className='py-2 px-6 bg-blue-600 text-white hover:bg-blue-700'
                  onClick={handleSubmitDaojiandanSign}
                  disabled={daojiandanSubmitLoading}
                >
                  {daojiandanSubmitLoading ? '提交中...' : '提交签名'}
                </Button>
              </div>
            </div>
          </div>
        )
      }
      {
        showDaojiandanPreview && daojiandanUrl && (
          <div className='fixed inset-0 z-[60] bg-black/75 flex flex-col'>
            <div className='flex items-center justify-between p-4 text-white bg-gray-900/80'>
              <div className='text-sm font-medium truncate pr-3'>导检单</div>
              <div className='flex items-center gap-2'>
                <Button
                  className='py-1 px-3 bg-blue-600 hover:bg-blue-700 text-white disabled:opacity-50 disabled:cursor-not-allowed'
                  onClick={() => {
                    // 有可选项目但尚未确认时，禁止打印并提示先确认项目
                    if (optionalItemList.length > 0 && !optionalConfirmed) {
                      setMessage('请先确认体检项目');
                      setShowOptionalConfirmTip(true);
                      return;
                    }
                    handleDaojiandanDirectPrint();
                  }}
                  disabled={busy}
                >
                  打印
                </Button>
                <Button
                  className='py-1 px-3 hover:bg-blue-700 text-white'
                  onClick={() => {
                    if (busy) return;
                    // 有可选项目但尚未确认时，禁止签名并提示先确认项目
                    if (optionalItemList.length > 0 && !optionalConfirmed) {
                      setMessage('请先确认体检项目');
                      setShowOptionalConfirmTip(true);
                      return;
                    }
                    setShowDaojiandanPreview(false);
                    setShowDaojiandanSignature(true);
                  }}
                  disabled={busy}
                >
                  签名
                </Button>
                <Button className='py-1 px-3' onClick={() => !busy && setShowDaojiandanPreview(false)} disabled={busy}>
                  关闭
                </Button>
              </div>
            </div>
            <div className='flex-1 bg-gray-100 overflow-auto'>
              {daojiandanPdfLoading ? (
                <div className='flex items-center justify-center h-full text-white'>
                  <div>正在加载PDF...</div>
                </div>
              ) : daojiandanPdfData ? (
                <div className='flex justify-center p-4'>
                  <div ref={daojiandanCanvasContainerRef} className='w-full' />
                </div>
              ) : (
                <div className='flex items-center justify-center h-full text-white'>
                  <div>PDF加载失败</div>
                </div>
              )}
            </div>
          </div>
        )
      }
      {
        showAddItemBillSignature && (
          <div className='fixed inset-0 z-[70] bg-black/80 flex items-center justify-center px-6'>
            <div className='bg-white rounded-2xl w-full max-w-3xl shadow-2xl p-4 flex flex-col gap-4'>
              <div className='flex items-center justify-between'>
                <div className='text-base font-semibold text-gray-900'>签署加项单</div>
                <div className='flex items-center gap-2'>
                  <Button className='py-1 px-3' onClick={() => setShowAddItemBillSignature(false)} disabled={busy}>
                    关闭
                  </Button>
                </div>
              </div>
              <div className='ui7-signature-wrapper border rounded-xl overflow-hidden bg-gray-50'>
                <SignaturePad
                  ref={addItemBillSignaturePadRef}
                  className='ui7-signature-canvas w-full h-72 bg-white touch-none'
                />
                <div className='flex items-center justify-between px-3 py-2 bg-gray-50 border-t'>
                  <div className='text-xs text-gray-500'>请在上方区域签名</div>
                  <Button className='ui7-clear-button py-1 px-3' onClick={() => addItemBillSignaturePadRef.current?.clear()} disabled={addItemBillSubmitLoading}>
                    清除
                  </Button>
                </div>
              </div>
              {addItemBillSubmitMessage && (
                <div className={`text-sm text-center ${addItemBillSubmitMessage.includes('成功') ? 'text-green-600' : 'text-amber-600'}`}>{addItemBillSubmitMessage}</div>
              )}
              <div className='flex items-center justify-end gap-3'>
                <Button
                  className='py-2 px-6'
                  onClick={() => {
                    setShowAddItemBillSignature(false);
                    setAddItemBillSubmitMessage(null);
                    addItemBillSignaturePadRef.current?.clear();
                  }}
                  disabled={addItemBillSubmitLoading}
                >
                  取消
                </Button>
                <Button
                  className='py-2 px-6 bg-blue-600 text-white hover:bg-blue-700'
                  onClick={handleSubmitAddItemBillSign}
                  disabled={addItemBillSubmitLoading}
                >
                  {addItemBillSubmitLoading ? '提交中...' : '提交签名'}
                </Button>
              </div>
            </div>
          </div>
        )
      }
      {
        showAddItemBillPreview && currentAddItemBill && currentAddItemBill.pdf_url && (
          <div className='fixed inset-0 z-[60] bg-black/75 flex flex-col'>
            <div className='flex items-center justify-between p-4 text-white bg-gray-900/80'>
              <div className='text-sm font-medium truncate pr-3'>{currentAddItemBill.pdf_name || '加项单'}</div>
              <div className='flex items-center gap-2'>
                {currentAddItemBill.is_signed && (
                  <Button
                    className='py-1 px-3 bg-blue-600 hover:bg-blue-700 text-white disabled:opacity-50 disabled:cursor-not-allowed'
                    onClick={() => handleAddItemBillDirectPrint(currentAddItemBill)}
                    disabled={busy}
                  >
                    打印
                  </Button>
                )}
                <Button
                  className='py-1 px-3 hover:bg-blue-700 text-white'
                  onClick={() => {
                    if (busy) return;
                    setShowAddItemBillPreview(false);
                    setShowAddItemBillSignature(true);
                  }}
                  disabled={busy}
                >
                  签名
                </Button>
                <Button className='py-1 px-3' onClick={() => !busy && setShowAddItemBillPreview(false)} disabled={busy}>
                  关闭
                </Button>
              </div>
            </div>
            <div className='flex-1 bg-gray-100 overflow-auto'>
              {addItemBillPdfLoading ? (
                <div className='flex items-center justify-center h-full text-white'>
                  <div>正在加载PDF...</div>
                </div>
              ) : addItemBillPdfData ? (
                <div className='flex justify-center p-4'>
                  <div ref={addItemBillCanvasContainerRef} className='w-full' />
                </div>
              ) : (
                <div className='flex items-center justify-center h-full text-white'>
                  <div>PDF加载失败</div>
                </div>
              )}
            </div>
          </div>
        )
      }
    </div >
  );
};


