"use client";

import React, {
  useState,
  useEffect,
  useRef,
  SetStateAction,
  Dispatch,
} from "react";
import { WebViewerInstance } from "@pdftron/webviewer";
import { Loader2, FileText, ClipboardList, AlertTriangle, FileSignature, Target, CheckCircle2, BookOpen } from "lucide-react";
import { toast } from "sonner";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import { getActiveSurveyTemplate, getVendorSignatureFile, type SurveyTemplateWithQuestions } from '../service';
import { useConditionalSurvey } from '../vendor-table/survey-conditional';
import { SurveyComponent } from './SurveyComponent';
import { GtcClausesComponent } from './GtcClausesComponent';

interface FileInfo {
  path: string;
  name: string;
  type: 'main' | 'attachment' | 'survey' | 'clauses';
}

interface BasicContractSignViewerProps {
  contractId?: number;
  filePath?: string;
  additionalFiles?: FileInfo[];
  templateName?: string;
  isOpen?: boolean;
  onClose?: () => void;
  onSign?: (documentData: ArrayBuffer, surveyData?: any) => Promise<void>;
  instance: WebViewerInstance | null;
  setInstance: Dispatch<SetStateAction<WebViewerInstance | null>>;
  onSurveyComplete?: () => void;
  onSignatureComplete?: () => void;
  onGtcCommentStatusChange?: (
    hasComments: boolean,
    commentCount: number,
    reviewStatus?: string,
    isComplete?: boolean
  ) => void;
  mode?: 'vendor' | 'buyer'; // 추가된 mode prop
  t?: (key: string) => string;
}

// 자동 서명 필드 생성을 위한 타입 정의
interface SignaturePattern {
  regex: RegExp;
  name: string;
  priority: number;
  offsetX?: number;
  offsetY?: number;
  width?: number;
  height?: number;
}

// 초간단 안전한 서명 필드 감지 클래스
class AutoSignatureFieldDetector {
  private instance: WebViewerInstance;
  private mode: 'vendor' | 'buyer';

  constructor(instance: WebViewerInstance, mode: 'vendor' | 'buyer' = 'vendor') {
    this.instance = instance;
    this.mode = mode;
  }

  async detectAndCreateSignatureFields(): Promise<string[]> {
    console.log(`🔍 텍스트 기반 서명 필드 감지 시작... (모드: ${this.mode})`);

    try {
      if (!this.instance?.Core?.documentViewer) {
        throw new Error("WebViewer 인스턴스가 유효하지 않습니다.");
      }

      const { Core } = this.instance;
      const { documentViewer } = Core;

      const document = documentViewer.getDocument();
      if (!document) {
        throw new Error("PDF 문서가 로드되지 않았습니다.");
      }

      // 모드에 따라 검색할 텍스트 결정
      const searchText = this.mode === 'buyer'
        ? '삼성중공업_서명란'
        : '협력업체_서명란';

      console.log(`📄 "${searchText}" 텍스트 검색 중...`);

      // 텍스트 검색 및 서명 필드 생성
      const fieldName = await this.createSignatureFieldAtText(searchText);

      if (fieldName) {
        console.log(`✅ 텍스트 위치에 서명 필드 생성 완료: ${searchText}`);
        return [fieldName];
      } else {
        // 텍스트를 찾지 못한 경우 기본 위치에 생성
        console.log(`⚠️ "${searchText}" 텍스트를 찾지 못해 기본 위치에 생성`);
        const defaultField = await this.createSimpleSignatureField();
        return [defaultField];
      }

    } catch (error) {
      console.error("📛 서명 필드 생성 실패:", error);

      // 오류 발생 시 기본 위치에 생성
      try {
        const defaultField = await this.createSimpleSignatureField();
        return [defaultField];
      } catch (fallbackError) {
        throw new Error("서명 필드 생성에 실패했습니다.");
      }
    }
  }

  private async createSignatureFieldAtText(searchText: string): Promise<string | null> {
    const { Core } = this.instance;
    const { documentViewer, annotationManager } = Core;
    const document = documentViewer.getDocument();

    if (!document) return null;

    try {
      // 모든 페이지에서 텍스트 검색
      const searchMode = Core.Search.Mode.PAGE_STOP | Core.Search.Mode.HIGHLIGHT;
      const searchOptions = {
        fullSearch: true,
        onResult: null,
      };

      // 텍스트 검색 시작
      const textSearchIterator = await document.getTextSearchIterator();
      textSearchIterator.begin(searchText, searchMode);

      let searchResult = await textSearchIterator.next();

      // 검색 결과가 있는 경우
      if (searchResult && searchResult.resultCode === Core.Search.ResultCode.FOUND) {
        const pageNumber = searchResult.pageNum;
        const quads = searchResult.quads;

        if (quads && quads.length > 0) {
          // 첫 번째 검색 결과의 위치 가져오기
          const quad = quads[0];

          // 쿼드의 좌표를 기반으로 서명 필드 위치 계산
          const x = Math.min(quad.x1, quad.x2, quad.x3, quad.x4);
          const y = Math.min(quad.y1, quad.y2, quad.y3, quad.y4);
          const textWidth = Math.abs(quad.x2 - quad.x1);
          const textHeight = Math.abs(quad.y3 - quad.y1);

          // 서명 필드 생성
          const fieldName = `signature_at_text_${Date.now()}`;
          const flags = new Core.Annotations.WidgetFlags();
          flags.set('Required', true);

          const field = new Core.Annotations.Forms.Field(fieldName, {
            type: 'Sig',
            flags
          });

          const widget = new Core.Annotations.SignatureWidgetAnnotation(field, {
            Width: 150,
            Height: 50
          });

          widget.setPageNumber(pageNumber);

          // 텍스트 바로 아래 또는 오른쪽에 서명 필드 배치
          // 옵션 1: 텍스트 바로 아래
          widget.setX(x);
          widget.setY(y + textHeight + 5); // 텍스트 아래 5픽셀 간격

          // 옵션 2: 텍스트 오른쪽 (필요시 아래 주석 해제)
          // widget.setX(x + textWidth + 10); // 텍스트 오른쪽 10픽셀 간격
          // widget.setY(y);

          widget.setWidth(150);
          widget.setHeight(50);

          // 필드 매니저에 추가
          const fm = annotationManager.getFieldManager();
          fm.addField(field);
          annotationManager.addAnnotation(widget);
          annotationManager.drawAnnotationsFromList([widget]);

          console.log(`📌 서명 필드를 페이지 ${pageNumber}의 "${searchText}" 위치에 생성`);

          return fieldName;
        }
      }

      console.log(`⚠️ "${searchText}" 텍스트를 찾을 수 없음`);
      return null;

    } catch (error) {
      console.error(`📛 텍스트 검색 중 오류: ${error}`);
      return null;
    }
  }

  private async createSimpleSignatureField(): Promise<string> {
    const { Core } = this.instance;
    const { documentViewer, annotationManager, Annotations } = Core;

    const page = documentViewer.getPageCount();
    const w = documentViewer.getPageWidth(page) || 612;
    const h = documentViewer.getPageHeight(page) || 792;

    const fieldName = `simple_signature_${Date.now()}`;
    const flags = new Annotations.WidgetFlags();
    flags.set('Required', true);

    const field = new Core.Annotations.Forms.Field(fieldName, {
      type: 'Sig',
      flags
    });

    const widget = new Annotations.SignatureWidgetAnnotation(field, {
      Width: 150,
      Height: 50
    });

    widget.setPageNumber(page);

    // 구매자 모드일 때는 왼쪽 하단으로 위치 설정
    if (this.mode === 'buyer') {
      widget.setX(w * 0.1); // 왼쪽 (10%)
      widget.setY(h * 0.85); // 하단 (85%)
    } else {
      // 협력업체 모드일 때는 기존처럼 오른쪽
      widget.setX(w * 0.7); // 오른쪽 (70%)
      widget.setY(h * 0.85); // 하단 (85%)
    }

    widget.setWidth(150);
    widget.setHeight(50);

    const fm = annotationManager.getFieldManager();
    fm.addField(field);
    annotationManager.addAnnotation(widget);
    annotationManager.drawAnnotationsFromList([widget]);

    return fieldName;
  }
}


function useAutoSignatureFields(instance: WebViewerInstance | null, mode: 'vendor' | 'buyer' = 'vendor') {
  const [signatureFields, setSignatureFields] = useState<string[]>([]);
  const [isProcessing, setIsProcessing] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // 한 번만 실행되도록 보장하는 플래그들
  const processingRef = useRef(false);
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);
  const processedDocumentRef = useRef<string | null>(null); // 처리된 문서 추적
  const handlerRef = useRef<(() => void) | null>(null); // 핸들러 참조 저장

  useEffect(() => {
    if (!instance) return;

    const { documentViewer } = instance.Core;

    // 새로운 핸들러 생성 (참조가 변하지 않도록)
    const handleDocumentLoaded = () => {
      // 현재 문서의 고유 식별자 생성
      const currentDoc = documentViewer.getDocument();
      const documentId = currentDoc ? `${currentDoc.getFilename()}_${Date.now()}` : null;

      // 같은 문서를 이미 처리했다면 스킵
      if (documentId && processedDocumentRef.current === documentId) {
        console.log("📛 이미 처리된 문서이므로 스킵:", documentId);
        return;
      }

      if (processingRef.current) {
        console.log("📛 이미 처리 중이므로 스킵");
        return;
      }

      // 이전 타이머 클리어
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
        timeoutRef.current = null;
      }

      timeoutRef.current = setTimeout(async () => {
        // 다시 한번 중복 체크
        if (processingRef.current) return;
        if (documentId && processedDocumentRef.current === documentId) return;

        processingRef.current = true;
        setIsProcessing(true);
        setError(null);

        try {
          console.log("📄 문서 로드 완료, 서명 필드 처리 시작...");

          if (!instance?.Core?.documentViewer?.getDocument()) {
            throw new Error("문서가 준비되지 않았습니다.");
          }

          // 기존 서명 필드 확인
          const { annotationManager } = instance.Core;
          const existingAnnotations = annotationManager.getAnnotationsList();
          const existingSignatureFields = existingAnnotations.filter(
            annot => annot instanceof instance.Core.Annotations.SignatureWidgetAnnotation
          );

          // 이미 서명 필드가 있으면 생성하지 않음
          if (existingSignatureFields.length > 0) {
            console.log("📋 기존 서명 필드 발견:", existingSignatureFields.length);
            const fieldNames = existingSignatureFields.map((field, idx) =>
              field.getField()?.name || `existing_signature_${idx}`
            );
            setSignatureFields(fieldNames);

            // 처리 완료 표시
            if (documentId) {
              processedDocumentRef.current = documentId;
            }

            toast.success(`📋 ${fieldNames.length}개의 기존 서명 필드를 확인했습니다.`);
            return;
          }

          const detector = new AutoSignatureFieldDetector(instance, mode); // mode 전달
          const fields = await detector.detectAndCreateSignatureFields();

          setSignatureFields(fields);

          // 처리 완료 표시
          if (documentId) {
            processedDocumentRef.current = documentId;
          }

          if (fields.length > 0) {
            const hasTextBasedField = fields.some(field => field.startsWith('signature_at_text_'));
            const hasSimpleField = fields.some(field => field.startsWith('simple_signature_'));

            if (hasTextBasedField) {
              const searchText = mode === 'buyer' ? '삼성중공업_서명란' : '협력업체_서명란';
              toast.success(`📝 "${searchText}" 위치에 서명 필드가 생성되었습니다.`, {
                description: "해당 텍스트 근처의 파란색 영역에서 서명해주세요.",
                icon: <FileSignature className="h-4 w-4 text-blue-500" />,
                duration: 5000
              });
            } else if (hasSimpleField) {
              const positionMessage = mode === 'buyer'
                ? "마지막 페이지 왼쪽 하단의 파란색 영역에서 서명해주세요."
                : "마지막 페이지 하단의 파란색 영역에서 서명해주세요.";

              toast.info("📝 기본 위치에 서명 필드가 생성되었습니다.", {
                description: `검색 텍스트를 찾을 수 없어 ${positionMessage}`,
                icon: <FileSignature className="h-4 w-4 text-blue-500" />,
                duration: 5000
              });
            }
          }

        } catch (error) {
          console.error("📛 서명 필드 처리 실패:", error);
          const errorMessage = error instanceof Error ? error.message : "서명 필드 처리에 실패했습니다.";
          setError(errorMessage);

          toast.info("수동 서명 모드", {
            description: "문서에서 서명할 위치를 직접 클릭해주세요.",
            icon: <FileSignature className="h-4 w-4 text-blue-500" />
          });
        } finally {
          setIsProcessing(false);
          processingRef.current = false;
        }
      }, 3000);
    };

    // 핸들러 참조 저장
    handlerRef.current = handleDocumentLoaded;

    // 이전 리스너 제거 (저장된 참조 사용)
    if (handlerRef.current) {
      documentViewer.removeEventListener('documentLoaded', handlerRef.current);
    }

    // 새 리스너 등록
    documentViewer.addEventListener('documentLoaded', handleDocumentLoaded);

    // 이미 문서가 로드되어 있다면 즉시 실행
    if (documentViewer.getDocument()) {
      // 짧은 지연 후 실행 (WebViewer 초기화 완료 보장)
      setTimeout(() => {
        if (!processingRef.current) {
          handleDocumentLoaded();
        }
      }, 1000);
    }

    return () => {
      // 클리어 시 저장된 참조 사용
      if (handlerRef.current) {
        documentViewer.removeEventListener('documentLoaded', handlerRef.current);
      }

      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
        timeoutRef.current = null;
      }

      // 상태 리셋
      processingRef.current = false;
      processedDocumentRef.current = null;
      handlerRef.current = null;
    };
  }, [instance, mode]); // mode 의존성 추가

  // 컴포넌트 언마운트 시 정리
  useEffect(() => {
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
      processingRef.current = false;
      processedDocumentRef.current = null;
    };
  }, []);

  return {
    signatureFields,
    isProcessing,
    hasSignatureFields: signatureFields.length > 0,
    error
  };
}
// XFDF 기반 서명 감지
function useSignatureDetection(instance: WebViewerInstance | null, onSignatureComplete?: () => void) {
  const [hasValidSignature, setHasValidSignature] = useState(false);
  const onCompleteRef = useRef(onSignatureComplete);

  useEffect(() => {
    onCompleteRef.current = onSignatureComplete
  }, [onSignatureComplete]);

  useEffect(() => {
    if (!instance?.Core) return;

    const { annotationManager, documentViewer } = instance.Core;
    const checkSignedByAppearance = () => {
      try {
        const annotations = annotationManager.getAnnotationsList();
        const signatureWidgets = annotations.filter(
          annot => annot instanceof instance.Core.Annotations.SignatureWidgetAnnotation
        );

        if (signatureWidgets.length === 0) {
          return false;
        }

        for (const widget of signatureWidgets) {
          const isSignedByAppearance = widget.isSignedByAppearance();

          if (isSignedByAppearance) {
            return true;
          }
        }
        return false;

      } catch (error) {
        console.error('서명 위젯 확인 중 오류:', error);
        return false;
      }
    };

    const checkSigned = async () => {
      try {
        const hasSignature = await checkSignedByAppearance();

        if (hasSignature !== hasValidSignature) {
          setHasValidSignature(hasSignature);

          if (hasSignature && onCompleteRef.current) {
            onCompleteRef.current();
          }
        }

      } catch (error) {
        console.error('서명 확인 중 오류:', error);
      }
    };

    const onAnnotationChanged = (annotations: any[], action: string) => {
      console.log("서명 변경")
      // if (action === 'delete') return;

      setTimeout(checkSigned, 800);
    };



    const onDocumentLoaded = () => {
      setTimeout(checkSigned, 2000);
    };

    const onPageUpdated = () => {
      setTimeout(checkSigned, 1000);
    };

    const onAnnotationSelected = () => {
      setTimeout(checkSigned, 500);
    };

    const onAnnotationUnselected = () => {
      setTimeout(checkSigned, 1000);
    };

    try {
      annotationManager.addEventListener('annotationChanged', onAnnotationChanged);
      annotationManager.addEventListener('annotationSelected', onAnnotationSelected);
      annotationManager.addEventListener('annotationUnselected', onAnnotationUnselected);
      documentViewer.addEventListener('documentLoaded', onDocumentLoaded);
      documentViewer.addEventListener('pageNumberUpdated', onPageUpdated);

    } catch (error) {
      console.error('이벤트 리스너 등록 실패:', error);
    }

    if (documentViewer.getDocument()) {
      setTimeout(checkSigned, 1000);
    }

    const pollInterval = setInterval(() => {
      checkSigned();
    }, 5000);

    return () => {
      try {
        annotationManager.removeEventListener('annotationChanged', onAnnotationChanged);
        annotationManager.removeEventListener('annotationSelected', onAnnotationSelected);
        annotationManager.removeEventListener('annotationUnselected', onAnnotationUnselected);
        documentViewer.removeEventListener('documentLoaded', onDocumentLoaded);
        documentViewer.removeEventListener('pageNumberUpdated', onPageUpdated);
        clearInterval(pollInterval);
      } catch (error) {
        console.error('클린업 중 오류:', error);
      }
    };
  }, [instance, hasValidSignature]);

  return { hasValidSignature };
}

export function BasicContractSignViewer({
  contractId,
  filePath,
  additionalFiles = [],
  templateName = "",
  isOpen = false,
  onClose,
  onSign,
  instance,
  setInstance,
  onSurveyComplete,
  onSignatureComplete,
  onGtcCommentStatusChange,
  mode = 'vendor', // 기본값 vendor
  t = (key: string) => key,
}: BasicContractSignViewerProps) {

  const [fileLoading, setFileLoading] = useState<boolean>(true);
  const [activeTab, setActiveTab] = useState<string>("main");
  const [surveyData, setSurveyData] = useState<any>({});
  const [isInitialLoaded, setIsInitialLoaded] = useState<boolean>(false);
  const [surveyTemplate, setSurveyTemplate] = useState<SurveyTemplateWithQuestions | null>(null);
  const [surveyLoading, setSurveyLoading] = useState<boolean>(false);
  const [gtcCommentStatus, setGtcCommentStatus] = useState<{
    hasComments: boolean;
    commentCount: number;
    reviewStatus?: string;
    isComplete?: boolean;
  }>({
    hasComments: false,
    commentCount: 0,
    isComplete: false
  });

  console.log(filePath, "filePath")
  console.log(surveyTemplate, "surveyTemplate")

  const conditionalHandler = useConditionalSurvey(surveyTemplate);

  const viewer = useRef<HTMLDivElement>(null);
  const initialized = useRef(false);
  const isCancelled = useRef(false);
  const currentDocumentPath = useRef<string>("");
  const [showDialog, setShowDialog] = useState(isOpen);
  const webViewerInstance = useRef<WebViewerInstance | null>(null);

  // mode 전달
  const { signatureFields, isProcessing: isAutoSignProcessing, hasSignatureFields, error: autoSignError } = useAutoSignatureFields(webViewerInstance.current || instance, mode);

  const { hasValidSignature } = useSignatureDetection(webViewerInstance.current || instance, onSignatureComplete);

  // 구매자 모드일 때는 템플릿 관련 로직 비활성화
  const isComplianceTemplate = mode === 'buyer' ? false : templateName.includes('준법');
  const isNDATemplate = mode === 'buyer' ? false : (templateName.includes('비밀유지') || templateName.includes('NDA'));
  const isGTCTemplate = mode === 'buyer' ? false : templateName.includes('GTC');

  const allFiles: FileInfo[] = React.useMemo(() => {
    const files: FileInfo[] = [];

    if (filePath) {
      files.push({
        path: filePath,
        name: templateName || "기본 계약서",
        type: "main",
      });
    }

    // 구매자 모드일 때는 추가 파일, 설문조사, 조항 검토 탭 제외
    if (mode === 'buyer') {
      return files; // 메인 계약서 파일만 반환
    }

    const normalizedAttachments: FileInfo[] = (additionalFiles || [])
      .map((f: any, idx: number) => ({
        path: f.path ?? f.filePath ?? "",
        name: `첨부파일 ${idx + 1}`,
        type: "attachment" as const,
      }))
      .filter(f => !!f.path);

    files.push(...normalizedAttachments);

    if (isComplianceTemplate) {
      files.push({
        path: "",
        name: "준법 설문조사",
        type: "survey",
      });
    }

    if (isGTCTemplate) {
      files.push({
        path: "",
        name: "조항 검토",
        type: "clauses",
      });
    }

    return files;
  }, [filePath, additionalFiles, templateName, isComplianceTemplate, isGTCTemplate, mode]);

  const cleanupHtmlStyle = () => {
    const elements = document.querySelectorAll('.Document_container');
    elements.forEach((elem) => {
      elem.remove();
    });
  };

  const cleanupWebViewer = () => {
    console.log("🧹 WebViewer 정리 시작");

    if (webViewerInstance.current) {
      try {
        const { documentViewer } = webViewerInstance.current.Core;
        if (documentViewer && documentViewer.getDocument()) {
          documentViewer.closeDocument();
        }

        if (webViewerInstance.current.UI && typeof webViewerInstance.current.UI.dispose === 'function') {
          webViewerInstance.current.UI.dispose();
        }
      } catch (error) {
        console.warn("WebViewer 정리 중 에러 (무시됨):", error);
      }

      webViewerInstance.current = null;
    }

    if (instance && setInstance) {
      setInstance(null);
    }

    setTimeout(() => cleanupHtmlStyle(), 100);
  };

  useEffect(() => {
    setShowDialog(isOpen);

    // 구매자 모드가 아닐 때만 설문조사 템플릿 로드
    if (isOpen && isComplianceTemplate && !surveyTemplate && mode !== 'buyer') {
      loadSurveyTemplate();
    }

    if (isOpen) {
      setIsInitialLoaded(false);
      currentDocumentPath.current = "";
    }
  }, [isOpen, isComplianceTemplate, mode]);

  useEffect(() => {
    if (!filePath) return;

    setIsInitialLoaded(false);
    currentDocumentPath.current = "";
    setActiveTab("main");

    const currentInstance = webViewerInstance.current || instance;

    if (currentInstance) {
      const normalizedPath = filePath.startsWith('/') ? filePath.substring(1) : filePath;
      const encodedPath = normalizedPath.split('/').map(part => encodeURIComponent(part)).join('/');
      const apiFilePath = `/api/files/${encodedPath}`;

      loadDocument(currentInstance, apiFilePath, true).then(() => {
        setIsInitialLoaded(true);
      }).catch((error) => {
        console.error("📛 문서 로드 실패:", error);
      });
    }
  }, [filePath, instance]);

  const loadSurveyTemplate = async () => {
    setSurveyLoading(true);

    try {
      const template = await getActiveSurveyTemplate();
      setSurveyTemplate(template);
    } catch (error) {
      console.error('📛 설문조사 템플릿 로드 실패:', error);
      setSurveyTemplate(null);
    } finally {
      setSurveyLoading(false);
    }
  };

  useEffect(() => {
    if (!initialized.current && viewer.current) {
      initialized.current = true;
      isCancelled.current = false;

      const initializeWebViewer = () => {
        if (!viewer.current || isCancelled.current) {
          return;
        }

        const viewerElement = viewer.current;

        if (!viewerElement.isConnected) {
          setTimeout(initializeWebViewer, 100);
          return;
        }

        cleanupWebViewer();

        import("@pdftron/webviewer").then(({ default: WebViewer }) => {
          if (isCancelled.current || !viewer.current) {
            return;
          }

          WebViewer(
            {
              path: "/pdftronWeb",
              licenseKey: process.env.NEXT_PUBLIC_PDFTRON_WEBVIEW_KEY,
              fullAPI: true,
            },
            viewerElement
          ).then((newInstance) => {
            if (isCancelled.current) {
              return;
            }

            webViewerInstance.current = newInstance;
            setInstance(newInstance);
            setFileLoading(false);

            const { documentViewer, annotationManager, Annotations } = newInstance.Core;

            const { WidgetFlags } = Annotations;
            const FitMode = newInstance.UI.FitMode;

            const handleDocumentLoaded = () => {
              setFileLoading(false);
              newInstance.UI.setFitMode(FitMode.FitWidth);

              requestAnimationFrame(() => {
                try {
                  documentViewer.refreshAll();
                  documentViewer.updateView();
                  window.dispatchEvent(new Event("resize"));
                  setTimeout(() => window.dispatchEvent(new Event("resize")), 100);
                } catch (e) {
                  console.warn("layout refresh skipped", e);
                }
              });
            };

            documentViewer.addEventListener('documentLoaded', handleDocumentLoaded);

            // 구매자 모드가 아닐 때만 자동 서명 적용
            if (mode !== 'buyer') {
              annotationManager.addEventListener('annotationChanged', async (annotList, type) => {
                for (const annot of annotList) {
                  const { fieldName, X, Y, Width, Height, PageNumber } = annot;

                  if (type === "add" && annot.Subject === "Widget") {
                    const signatureImage = await getVendorSignatureFile()

                    const stamp = new Annotations.StampAnnotation();
                    stamp.PageNumber = PageNumber;
                    stamp.X = X;
                    stamp.Y = Y;
                    stamp.Width = Width;
                    stamp.Height = Height;

                    if (signatureImage) {
                      await stamp.setImageData(signatureImage.data.dataUrl);
                      annot.sign(stamp);
                      annot.setFieldFlag(WidgetFlags.READ_ONLY, true);
                    }

                  }
                }
              });
            }

            newInstance.UI.setMinZoomLevel('25%');
            newInstance.UI.setMaxZoomLevel('400%');

            newInstance.UI.disableElements([
              "toolbarGroup-Annotate",
              "toolbarGroup-Shapes",
              "toolbarGroup-Insert",
              "toolbarGroup-Edit",
              "toolbarGroup-FillAndSign",
              "toolbarGroup-Forms",
              "saveAsButton",
              "downloadButton",
            ]);

            documentViewer.addEventListener('documentLoadingError', (error) => {
              console.error("📛 문서 로딩 에러:", error);

              let showToast = true;
              let errorMessage = "문서를 불러오는데 실패했습니다.";

              if (error && typeof error === 'object') {
                const errorStr = JSON.stringify(error).toLowerCase();

                if (errorStr.includes('linearized') || errorStr.includes('getreference')) {
                  showToast = false;
                } else if (errorStr.includes('network')) {
                  errorMessage = "네트워크 연결을 확인해주세요.";
                } else if (errorStr.includes('permission')) {
                  errorMessage = "문서에 접근할 권한이 없습니다.";
                }
              }

              if (showToast) {
                setFileLoading(false);
                toast.error(errorMessage);
              }
            });

          }).catch((error) => {
            console.error("📛 WebViewer 초기화 실패:", error);
            setFileLoading(false);
            toast.error("뷰어 초기화에 실패했습니다.");
          });
        }).catch((error) => {
          console.error("📛 WebViewer 모듈 로드 실패:", error);
          setFileLoading(false);
          toast.error("뷰어 모듈을 불러오는데 실패했습니다.");
        });
      };

      requestAnimationFrame(() => {
        setTimeout(initializeWebViewer, 50);
      });
    }

    return () => {
      isCancelled.current = true;
      cleanupWebViewer();
    };
  }, [setInstance, mode]);

  const getExtFromPath = (p: string) => {
    const m = p.toLowerCase().match(/\.([a-z0-9]+)(?:\?.*)?$/);
    return m ? m[1] : undefined;
  };

  const loadDocument = async (
    instance: WebViewerInstance,
    documentPath: string,
    forceReload = false
  ) => {
    if (!forceReload && currentDocumentPath.current === documentPath) {
      return;
    }

    setFileLoading(true);
    try {
      if (!instance || !instance.UI || !instance.Core) {
        throw new Error("WebViewer 인스턴스가 유효하지 않습니다.");
      }

      const ext = getExtFromPath(documentPath);
      await instance.UI.loadDocument(documentPath, {
        ...(ext ? { extension: ext } : {}),
        filename: documentPath.split("/").pop(),
      });

      currentDocumentPath.current = documentPath;

      const { documentViewer } = instance.Core;
      requestAnimationFrame(() => {
        try {
          documentViewer.refreshAll();
          documentViewer.updateView();
          window.dispatchEvent(new Event("resize"));
          setTimeout(() => window.dispatchEvent(new Event("resize")), 100);
        } catch (e) {
          console.warn("레이아웃 새로고침 스킵:", e);
        }
      });
    } catch (error) {
      console.error("📛 문서 로딩 실패:", error);
      currentDocumentPath.current = "";

      let msg = "문서를 불러오는데 실패했습니다.";
      if (error instanceof Error) {
        const s = error.message.toLowerCase();
        if (s.includes("network") || s.includes("fetch")) {
          msg = "네트워크 연결을 확인해주세요.";
        } else if (s.includes("permission") || s.includes("access")) {
          msg = "문서에 접근할 권한이 없습니다.";
        } else if (s.includes("corrupt") || s.includes("invalid")) {
          msg = "파일이 손상되었거나 형식이 올바르지 않습니다.";
        } else if (s.includes("linearized") || s.includes("getreference")) {
          msg = "";
        }
      }
      if (msg) toast.error(msg);
    } finally {
      setFileLoading(false);
    }
  };

  const collectFormData = async (instance: WebViewerInstance) => {
    try {
      const { annotationManager } = instance.Core;
      const fieldManager = annotationManager.getFieldManager();
      const fields = fieldManager.getFields();

      const formData: any = {};
      fields.forEach((field: any) => {
        formData[field.name] = field.value;
      });

      return formData;
    } catch (error) {
      console.error('📛 폼 데이터 수집 실패:', error);
      return {};
    }
  };

  const handleTabChange = async (newTab: string) => {
    setActiveTab(newTab);
    if (newTab === "survey" || newTab === "clauses") return;

    const currentInstance = webViewerInstance.current || instance;
    if (!currentInstance || fileLoading) return;

    if (newTab === 'survey' && !surveyTemplate && !surveyLoading && mode !== 'buyer') {
      loadSurveyTemplate();
    }

    let targetFile: FileInfo | undefined;
    if (newTab === "main") {
      targetFile = allFiles.find(f => f.type === "main");
    } else if (newTab.startsWith("file-")) {
      const fileIndex = parseInt(newTab.replace("file-", ""), 10);
      targetFile = allFiles.filter(f => f.type !== 'survey' && f.type !== 'clauses')[fileIndex];
    }

    if (!targetFile?.path) {
      console.warn("📛 대상 파일을 찾을 수 없음:", newTab, allFiles);
      return;
    }

    const normalizedPath = targetFile.path.startsWith("/")
      ? targetFile.path.substring(1)
      : targetFile.path;
    const encodedPath = normalizedPath.split("/").map(encodeURIComponent).join("/");
    const apiFilePath = `/api/files/${encodedPath}`;

    try {
      currentDocumentPath.current = "";
      await loadDocument(currentInstance, apiFilePath, true);
      setIsInitialLoaded(true);

      const { documentViewer } = currentInstance.Core;
      requestAnimationFrame(() => {
        try {
          documentViewer.refreshAll();
          documentViewer.updateView();
          window.dispatchEvent(new Event("resize"));
        } catch (e) {
          console.warn("탭 변경 후 레이아웃 새고침 스킵:", e);
        }
      });
    } catch (e) {
      console.error("📛 탭 변경 실패:", e);
    }
  };

  useEffect(() => {
    const currentInstance = webViewerInstance.current || instance;

    if (!currentInstance || !filePath || isInitialLoaded) {
      return;
    }

    const isMainTab = activeTab === 'main';
    const shouldLoadInitial = allFiles.length === 1 || isMainTab;

    if (!shouldLoadInitial || currentDocumentPath.current !== "") {
      return;
    }

    const normalizedPath = filePath.startsWith('/') ? filePath.substring(1) : filePath;
    const encodedPath = normalizedPath.split('/').map(part => encodeURIComponent(part)).join('/');
    const apiFilePath = `/api/files/${encodedPath}`;

    currentDocumentPath.current = "";

    loadDocument(currentInstance, apiFilePath, true).then(() => {
      setIsInitialLoaded(true);
    }).catch((error) => {
      console.error("📛 초기 마운트 로드 실패:", error);
    });
  }, [webViewerInstance.current, instance, filePath, activeTab, isInitialLoaded, allFiles.length]);

  const handleSave = async () => {
    const currentInstance = webViewerInstance.current || instance;
    if (!currentInstance) return;

    try {
      const { documentViewer, annotationManager } = currentInstance.Core;
      const doc = documentViewer.getDocument();

      if (!doc) {
        toast.error("문서가 로드되지 않았습니다.");
        return;
      }

      const formData = await collectFormData(currentInstance);

      const xfdfString = await annotationManager.exportAnnotations();
      const documentData = await doc.getFileData({
        xfdfString,
        downloadType: "pdf",
      });

      // 구매자 모드일 때는 설문조사와 GTC 검증 건너뛰기
      if (mode !== 'buyer') {
        if (isComplianceTemplate && !surveyData.completed) {
          toast.error("준법 설문조사를 먼저 완료해주세요.");
          setActiveTab('survey');
          return;
        }

        if (isGTCTemplate && gtcCommentStatus.hasComments && !gtcCommentStatus.isComplete) {
          toast.error("GTC 조항에 미해결 코멘트가 있어 서명할 수 없습니다.");
          toast.info("모든 코멘트를 삭제하거나 협의를 완료한 후 서명해주세요.");
          setActiveTab('clauses');
          return;
        }
      }

      if (onSign) {
        await onSign(documentData, { formData, surveyData, signatureFields });
      } else {
        const actionText = mode === 'buyer' ? "최종승인" : "서명";
        toast.success(`계약서가 성공적으로 ${actionText}되었습니다.`);
      }

      handleClose();
    } catch (error) {
      console.error(`📛 ${mode === 'buyer' ? '최종승인' : '서명'} 저장 실패:`, error);
      const actionText = mode === 'buyer' ? "최종승인" : "서명";
      toast.error(`${actionText}을 저장하는데 실패했습니다.`);
    }
  };

  const handleClose = () => {
    if (onClose) {
      onClose();
    } else {
      setShowDialog(false);
    }
  };

  // 서명 상태 표시 컴포넌트
  const SignatureFieldsStatus = () => {
    if (!hasSignatureFields && !isAutoSignProcessing && !autoSignError && !hasValidSignature) return null;

    return (
      <div className="mb-2 flex items-center space-x-2">
        {isAutoSignProcessing ? (
          <Badge variant="secondary" className="text-xs">
            <Loader2 className="h-3 w-3 mr-1 animate-spin" />
            서명 필드 생성 중...
          </Badge>
        ) : autoSignError ? (
          <Badge variant="destructive" className="text-xs bg-red-50 text-red-700 border-red-200">
            <AlertTriangle className="h-3 w-3 mr-1" />
            자동 생성 실패
          </Badge>
        ) : hasSignatureFields ? (
          <Badge variant="outline" className="text-xs bg-blue-50 text-blue-700 border-blue-200">
            <Target className="h-3 w-3 mr-1" />
            {signatureFields.length}개 서명 필드 자동 생성됨 {mode === 'buyer' ? '(왼쪽 하단)' : ''}
          </Badge>
        ) : null}

        {hasValidSignature && (
          <Badge variant="outline" className="text-xs bg-green-50 text-green-700 border-green-200">
            <CheckCircle2 className="h-3 w-3 mr-1" />
            서명 완료됨
          </Badge>
        )}
      </div>
    );
  };

  // 인라인 뷰어 렌더링
  if (!isOpen && !onClose) {
    return (
      <div className="h-full w-full flex flex-col overflow-hidden">
        {/* 구매자 모드에서는 탭 없이 단일 뷰어만 표시 */}
        {allFiles.length > 1 && mode !== 'buyer' ? (
          <Tabs value={activeTab} onValueChange={handleTabChange} className="h-full flex flex-col">
            <div className="border-b bg-gray-50 px-3 py-2 flex-shrink-0">
              <SignatureFieldsStatus />
              <TabsList className="grid w-full h-8" style={{ gridTemplateColumns: `repeat(${allFiles.length}, 1fr)` }}>
                {allFiles.map((file, index) => {
                  let tabId: string;
                  if (index === 0) {
                    tabId = 'main';
                  } else if (file.type === 'survey') {
                    tabId = 'survey';
                  } else if (file.type === 'clauses') {
                    tabId = 'clauses';
                  } else {
                    const fileOnlyIndex = allFiles.slice(0, index).filter(f => f.type !== 'survey' && f.type !== 'clauses').length;
                    tabId = `file-${fileOnlyIndex}`;
                  }

                  return (
                    <TabsTrigger key={tabId} value={tabId} className="text-xs">
                      <div className="flex items-center space-x-1">
                        {file.type === 'survey' ? (
                          <ClipboardList className="h-3 w-3" />
                        ) : file.type === 'clauses' ? (
                          <BookOpen className="h-3 w-3" />
                        ) : (
                          <FileText className="h-3 w-3" />
                        )}
                        <span className="truncate">{file.name}</span>
                        {file.type === 'survey' && surveyData.completed && (
                          <Badge variant="secondary" className="ml-1 h-4 px-1 text-xs">완료</Badge>
                        )}
                        {file.type === 'clauses' && gtcCommentStatus.hasComments && (
                          <Badge variant="destructive" className="ml-1 h-4 px-1 text-xs">
                            코멘트 {gtcCommentStatus.commentCount}
                          </Badge>
                        )}
                      </div>
                    </TabsTrigger>
                  );
                })}
              </TabsList>
            </div>

            <div className="flex-1 min-h-0 overflow-hidden relative">
              <div
                className={`absolute inset-0 p-3 ${activeTab === 'survey' ? 'block' : 'hidden'}`}
              >
                {/* 분리된 SurveyComponent 사용 */}
                <SurveyComponent
                  contractId={contractId}
                  surveyTemplate={surveyTemplate}
                  surveyLoading={surveyLoading}
                  conditionalHandler={conditionalHandler}
                  onSurveyComplete={onSurveyComplete}
                  onSurveyDataUpdate={setSurveyData}
                  onLoadSurveyTemplate={loadSurveyTemplate}
                  setActiveTab={setActiveTab}
                />
              </div>

              <div
                className={`absolute inset-0 p-3 ${activeTab === 'clauses' ? 'block' : 'hidden'}`}
              >
                {/* GTC 조항 컴포넌트 */}
                <GtcClausesComponent
                  contractId={contractId}
                  onCommentStatusChange={(hasComments, commentCount, reviewStatus, isComplete) => {
                    setGtcCommentStatus({ hasComments, commentCount, reviewStatus, isComplete });
                    onGtcCommentStatusChange?.(hasComments, commentCount, reviewStatus, isComplete);
                  }}
                  t={t}
                />
              </div>

              <div
                className={`absolute inset-0 ${activeTab !== 'survey' && activeTab !== 'clauses' ? 'block' : 'hidden'}`}
              >
                <div className="w-full h-full overflow-auto">
                  <div
                    ref={viewer}
                    className="w-full h-full min-h-[400px]"
                    style={{
                      position: 'relative',
                      overflow: 'visible'
                    }}
                  >
                    {fileLoading && (
                      <div className="absolute inset-0 flex flex-col items-center justify-center bg-white z-10">
                        <Loader2 className="h-8 w-8 text-blue-500 animate-spin mb-4" />
                        <p className="text-sm text-muted-foreground">문서 로딩 중...</p>
                      </div>
                    )}
                  </div>
                </div>
              </div>
            </div>
          </Tabs>
        ) : (
          <div className="h-full w-full flex flex-col">
            <div className="flex-shrink-0 p-2">
              <SignatureFieldsStatus />
            </div>
            <div className="flex-1 min-h-0 overflow-hidden relative">
              <div className="absolute inset-0">
                <div className="w-full h-full overflow-auto">
                  <div
                    ref={viewer}
                    className="w-full h-full min-h-[400px]"
                    style={{
                      position: 'relative',
                      overflow: 'visible'
                    }}
                  >
                    {fileLoading && (
                      <div className="absolute inset-0 flex flex-col items-center justify-center bg-white z-10">
                        <Loader2 className="h-8 w-8 text-blue-500 animate-spin mb-4" />
                        <p className="text-sm text-muted-foreground">문서 로딩 중...</p>
                      </div>
                    )}
                  </div>
                </div>
              </div>
            </div>
          </div>
        )}
      </div>
    );
  }

  const handleGtcCommentStatusChange = React.useCallback((
    hasComments: boolean,
    commentCount: number,
    reviewStatus?: string,
    isComplete?: boolean
  ) => {
    setGtcCommentStatus({ hasComments, commentCount, reviewStatus, isComplete });
    onGtcCommentStatusChange?.(hasComments, commentCount, reviewStatus, isComplete);
  }, [onGtcCommentStatusChange]);

  // 다이얼로그 뷰어 렌더링
  return (
    <Dialog open={showDialog} onOpenChange={handleClose}>
      <DialogContent className="w-[90vw] max-w-6xl h-[90vh] flex flex-col p-0">
        <DialogHeader className="px-6 py-4 border-b flex-shrink-0">
          <DialogTitle className="flex items-center justify-between">
            <span>{mode === 'buyer' ? '구매자 최종승인' : '기본계약서 서명'}</span>
            <SignatureFieldsStatus />
          </DialogTitle>
          <DialogDescription>
            계약서를 확인하고 {mode === 'buyer' ? '최종승인을' : '서명을'} 진행해주세요.
            {mode !== 'buyer' && isComplianceTemplate && (
              <span className="block mt-1 text-amber-600">📋 준법 설문조사를 먼저 완료해주세요.</span>
            )}
            {mode !== 'buyer' && isGTCTemplate && (
              <span className="block mt-1 text-blue-600">📋 GTC 조항을 검토하고 코멘트가 없는지 확인해주세요.</span>
            )}
            {hasSignatureFields && (
              <span className="block mt-1 text-green-600">
                🎯 서명 위치가 자동으로 감지되었습니다{mode === 'buyer' ? ' (왼쪽 하단)' : ''}.
              </span>
            )}
            {hasValidSignature && (
              <span className="block mt-1 text-green-600">
                ✅ {mode === 'buyer' ? '승인이' : '서명이'} 완료되었습니다.
              </span>
            )}
            {mode !== 'buyer' && isGTCTemplate && gtcCommentStatus.hasComments && (
              <span className="block mt-1 text-red-600">
                ⚠️ GTC 조항에 {gtcCommentStatus.commentCount}개의 코멘트가 있어 서명할 수 없습니다.
              </span>
            )}
            {mode !== 'buyer' && isGTCTemplate && gtcCommentStatus.hasComments && !gtcCommentStatus.isComplete && (
              <span className="block mt-1 text-red-600">
                ⚠️ GTC 조항에 {gtcCommentStatus.commentCount}개의 미해결 코멘트가 있어 서명할 수 없습니다.
              </span>
            )}
            {mode !== 'buyer' && isGTCTemplate && gtcCommentStatus.hasComments && gtcCommentStatus.isComplete && (
              <span className="block mt-1 text-green-600">
                ✅ GTC 조항 협의가 완료되어 서명 가능합니다.
              </span>
            )}
          </DialogDescription>
        </DialogHeader>

        <div className="flex-1 min-h-0 overflow-hidden">
          {/* 구매자 모드에서는 탭 없이 단일 뷰어만 표시 */}
          {allFiles.length > 1 && mode !== 'buyer' ? (
            <Tabs value={activeTab} onValueChange={handleTabChange} className="h-full flex flex-col">
              <div className="border-b bg-gray-50 px-3 py-2 flex-shrink-0">
                <TabsList className="grid w-full h-8" style={{ gridTemplateColumns: `repeat(${allFiles.length}, 1fr)` }}>
                  {allFiles.map((file, index) => {
                    let tabId: string;
                    if (index === 0) {
                      tabId = 'main';
                    } else if (file.type === 'survey') {
                      tabId = 'survey';
                    } else if (file.type === 'clauses') {
                      tabId = 'clauses';
                    } else {
                      const fileOnlyIndex = allFiles.slice(0, index).filter(f => f.type !== 'survey' && f.type !== 'clauses').length;
                      tabId = `file-${fileOnlyIndex}`;
                    }

                    return (
                      <TabsTrigger key={tabId} value={tabId} className="text-xs">
                        <div className="flex items-center space-x-1">
                          {file.type === 'survey' ? (
                            <ClipboardList className="h-3 w-3" />
                          ) : file.type === 'clauses' ? (
                            <BookOpen className="h-3 w-3" />
                          ) : (
                            <FileText className="h-3 w-3" />
                          )}
                          <span className="truncate">{file.name}</span>
                          {file.type === 'survey' && surveyData.completed && (
                            <Badge variant="secondary" className="ml-1 h-4 px-1 text-xs">완료</Badge>
                          )}
                          {file.type === 'clauses' && gtcCommentStatus.hasComments && (
                            <Badge variant="destructive" className="ml-1 h-4 px-1 text-xs">
                              코멘트 {gtcCommentStatus.commentCount}
                            </Badge>
                          )}
                        </div>
                      </TabsTrigger>
                    );
                  })}
                </TabsList>
              </div>

              <div className="flex-1 min-h-0 overflow-hidden relative">
                <div className={`absolute inset-0 p-3 ${activeTab === 'survey' ? 'block' : 'hidden'}`}>
                  {/* 분리된 SurveyComponent 사용 */}
                  <SurveyComponent
                    contractId={contractId}
                    surveyTemplate={surveyTemplate}
                    surveyLoading={surveyLoading}
                    conditionalHandler={conditionalHandler}
                    onSurveyComplete={onSurveyComplete}
                    onSurveyDataUpdate={setSurveyData}
                    onLoadSurveyTemplate={loadSurveyTemplate}
                    setActiveTab={setActiveTab}
                  />
                </div>

                <div className={`absolute inset-0 p-3 ${activeTab === 'clauses' ? 'block' : 'hidden'}`}>
                  {/* GTC 조항 컴포넌트 */}
                  <GtcClausesComponent
                    contractId={contractId}
                    onCommentStatusChange={handleGtcCommentStatusChange}  // 메모이제이션된 콜백 사용
                    t={t}
                  />
                </div>

                <div className={`absolute inset-0 ${activeTab !== 'survey' && activeTab !== 'clauses' ? 'block' : 'hidden'}`}>
                  <div className="w-full h-full overflow-auto">
                    <div
                      ref={viewer}
                      className="w-full h-full min-h-[400px]"
                      style={{
                        position: 'relative',
                        overflow: 'visible'
                      }}
                    >
                      {fileLoading && (
                        <div className="absolute inset-0 flex flex-col items-center justify-center bg-white z-10">
                          <Loader2 className="h-8 w-8 text-blue-500 animate-spin mb-4" />
                          <p className="text-sm text-muted-foreground">문서 로딩 중...</p>
                        </div>
                      )}
                    </div>
                  </div>
                </div>
              </div>
            </Tabs>
          ) : (
            <div className="h-full flex flex-col">
              <div className="flex-1 min-h-0 overflow-hidden relative">
                <div className="absolute inset-0">
                  <div className="w-full h-full overflow-auto">
                    <div
                      ref={viewer}
                      className="w-full h-full min-h-[400px]"
                      style={{
                        position: 'relative',
                        overflow: 'visible'
                      }}
                    >
                      {fileLoading && (
                        <div className="absolute inset-0 flex flex-col items-center justify-center bg-white z-10">
                          <Loader2 className="h-8 w-8 text-blue-500 animate-spin mb-4" />
                          <p className="text-sm text-muted-foreground">문서 로딩 중...</p>
                        </div>
                      )}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          )}
        </div>

        <DialogFooter className="px-6 py-4 border-t bg-white flex-shrink-0">
          <Button variant="outline" onClick={handleClose} disabled={fileLoading}>취소</Button>
          <Button onClick={handleSave} disabled={fileLoading || isAutoSignProcessing}>
            <FileSignature className="h-4 w-4 mr-2" />
            {mode === 'buyer' ? '최종승인 완료' : '서명 완료'}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}