import React, { useState, useRef, useCallback, useEffect } from "react";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { toast } from "sonner";
import { uploadFiles, downloadFile, deleteFile, getComponentFiles, getFileInfoByObjid, getFilePreviewUrl } from "@/lib/api/file";
import { GlobalFileManager } from "@/lib/api/globalFile";
import { formatFileSize } from "@/lib/utils";
import { apiClient } from "@/lib/api/client";
import { FileViewerModal } from "./FileViewerModal";
import { FileManagerModal } from "./FileManagerModal";
import { FileUploadConfig, FileInfo, FileUploadStatus, FileUploadResponse } from "./types";
import { useAuth } from "@/hooks/useAuth";
import {
  Upload,
  File,
  FileText,
  Image,
  Video,
  Music,
  Archive,
  Download,
  Eye,
  Trash2,
  AlertCircle,
  FileImage,
  FileVideo,
  FileAudio,
  Presentation,
} from "lucide-react";

// 파일 아이콘 매핑
const getFileIcon = (extension: string) => {
  const ext = extension.toLowerCase().replace(".", "");

  if (["jpg", "jpeg", "png", "gif", "bmp", "webp", "svg"].includes(ext)) {
    return <FileImage className="h-6 w-6 text-blue-500" />;
  }
  if (["mp4", "avi", "mov", "wmv", "flv", "webm"].includes(ext)) {
    return <FileVideo className="h-6 w-6 text-purple-500" />;
  }
  if (["mp3", "wav", "flac", "aac", "ogg"].includes(ext)) {
    return <FileAudio className="h-6 w-6 text-green-500" />;
  }
  if (["pdf"].includes(ext)) {
    return <FileText className="h-6 w-6 text-red-500" />;
  }
  if (["doc", "docx", "hwp", "hwpx", "pages"].includes(ext)) {
    return <FileText className="h-6 w-6 text-blue-600" />;
  }
  if (["xls", "xlsx", "hcell", "numbers"].includes(ext)) {
    return <FileText className="h-6 w-6 text-green-600" />;
  }
  if (["ppt", "pptx", "hanshow", "keynote"].includes(ext)) {
    return <Presentation className="h-6 w-6 text-orange-500" />;
  }
  if (["zip", "rar", "7z", "tar", "gz"].includes(ext)) {
    return <Archive className="h-6 w-6 text-gray-500" />;
  }

  return <File className="h-6 w-6 text-gray-400" />;
};

export interface FileUploadComponentProps {
  component: any;
  componentConfig: FileUploadConfig;
  componentStyle: React.CSSProperties;
  className: string;
  isInteractive: boolean;
  isDesignMode: boolean;
  formData: any;
  onFormDataChange: (fieldName: string, value: any) => void;
  onClick?: () => void;
  onDragStart?: (e: React.DragEvent) => void;
  onDragEnd?: (e: React.DragEvent) => void;
  onUpdate?: (updates: Partial<any>) => void;
  autoGeneration?: any;
  hidden?: boolean;
  onConfigChange?: (config: any) => void;
}

const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
  component,
  componentConfig,
  componentStyle,
  className,
  isInteractive,
  isDesignMode = false, // 기본값 설정
  formData,
  onFormDataChange,
  onClick,
  onDragStart,
  onDragEnd,
  onUpdate,
}) => {
  // 🔑 인증 정보 가져오기
  const { user } = useAuth();
  
  const [uploadedFiles, setUploadedFiles] = useState<FileInfo[]>([]);
  const [uploadStatus, setUploadStatus] = useState<FileUploadStatus>("idle");
  const [dragOver, setDragOver] = useState(false);
  const [viewerFile, setViewerFile] = useState<FileInfo | null>(null);
  const [isViewerOpen, setIsViewerOpen] = useState(false);
  const [isFileManagerOpen, setIsFileManagerOpen] = useState(false);
  const [forceUpdate, setForceUpdate] = useState(0);
  const [representativeImageUrl, setRepresentativeImageUrl] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  // 🔑 레코드 모드 판단: formData에 id가 있으면 특정 행에 연결된 파일 관리
  const isRecordMode = !!(formData?.id && !String(formData.id).startsWith('temp_'));
  const recordTableName = formData?.tableName || component.tableName;
  const recordId = formData?.id;
  // 🔑 컬럼명 결정: component.columnName을 우선 사용 (실제 DB 컬럼명)
  // image, file 등의 웹타입 컬럼에 URL이 저장되어야 함
  const columnName = component.columnName || component.id || 'attachments';
  
  // 🔑 레코드 모드용 targetObjid 생성
  const getRecordTargetObjid = useCallback(() => {
    if (isRecordMode && recordTableName && recordId) {
      return `${recordTableName}:${recordId}:${columnName}`;
    }
    return null;
  }, [isRecordMode, recordTableName, recordId, columnName]);

  // 🔑 레코드별 고유 키 생성 (localStorage, 전역 상태용)
  // 🆕 columnName을 포함하여 같은 화면의 여러 파일 업로드 컴포넌트 구분
  const getUniqueKey = useCallback(() => {
    if (isRecordMode && recordTableName && recordId) {
      // 레코드 모드: 테이블명:레코드ID:컴포넌트ID:컬럼명 형태로 고유 키 생성
      return `fileUpload_${recordTableName}_${recordId}_${component.id}_${columnName}`;
    }
    // 기본 모드: 컴포넌트 ID + 컬럼명 사용
    return `fileUpload_${component.id}_${columnName}`;
  }, [isRecordMode, recordTableName, recordId, component.id, columnName]);


  // 🆕 레코드 ID 변경 시 파일 목록 초기화 및 새로 로드
  const prevRecordIdRef = useRef<any>(null);
  const prevIsRecordModeRef = useRef<boolean | null>(null);
  useEffect(() => {
    const recordIdChanged = prevRecordIdRef.current !== recordId;
    const modeChanged = prevIsRecordModeRef.current !== null && prevIsRecordModeRef.current !== isRecordMode;
    
    if (recordIdChanged || modeChanged) {
      prevRecordIdRef.current = recordId;
      prevIsRecordModeRef.current = isRecordMode;
      
      // 레코드 ID가 변경되거나 등록 모드(isRecordMode=false)로 전환되면 파일 목록 초기화
      // 등록 모드에서는 항상 빈 상태로 시작해야 함
      if (isRecordMode || !recordId) {
        setUploadedFiles([]);
        setRepresentativeImageUrl(null);
      }
    } else if (prevIsRecordModeRef.current === null) {
      // 초기 마운트 시 모드 저장
      prevIsRecordModeRef.current = isRecordMode;
    }
  }, [recordId, isRecordMode]);

  // 컴포넌트 마운트 시 즉시 localStorage에서 파일 복원
  // 🔑 등록 모드(recordId가 없는 경우)에서는 파일을 복원하지 않음 - 항상 빈 상태로 시작
  useEffect(() => {
    if (!component?.id) return;
    
    // 등록 모드(새 레코드)인 경우 파일 복원 스킵 - 빈 상태 유지
    if (!isRecordMode || !recordId) {
      return;
    }

    try {
      // 🔑 레코드별 고유 키 사용 (수정 모드에서만)
      const backupKey = getUniqueKey();
      const backupFiles = localStorage.getItem(backupKey);
      if (backupFiles) {
        const parsedFiles = JSON.parse(backupFiles);
        if (parsedFiles.length > 0) {
          setUploadedFiles(parsedFiles);

          // 전역 상태에도 복원 (레코드별 고유 키 사용)
          if (typeof window !== "undefined") {
            (window as any).globalFileState = {
              ...(window as any).globalFileState,
              [backupKey]: parsedFiles,
            };
          }
        }
      }
    } catch (e) {
      console.warn("컴포넌트 마운트 시 파일 복원 실패:", e);
    }
  }, [component.id, getUniqueKey, recordId, isRecordMode]); // 레코드별 고유 키 변경 시 재실행

  // 🔑 수정 모드: formData[columnName]에 저장된 objid로 이미지 로드
  // 🆕 formData 전체가 아닌 특정 컬럼 값만 의존하도록 수정 (다른 컴포넌트 영향 방지)
  const imageObjidFromFormData = formData?.[columnName];
  
  useEffect(() => {
    // 이미지 objid가 있고, 숫자 문자열인 경우에만 처리
    if (imageObjidFromFormData && /^\d+$/.test(String(imageObjidFromFormData))) {
      const objidStr = String(imageObjidFromFormData);
      
      // 이미 같은 objid의 파일이 로드되어 있으면 스킵
      const alreadyLoaded = uploadedFiles.some(f => String(f.objid) === objidStr);
      if (alreadyLoaded) {
        return;
      }
      
      // 🔑 실제 파일 정보 조회 (previewUrl 제거 - apiClient blob 다운로드 방식으로 통일)
      (async () => {
        try {
          const fileInfoResponse = await getFileInfoByObjid(objidStr);
          
          if (fileInfoResponse.success && fileInfoResponse.data) {
            const { realFileName, fileSize, fileExt, regdate, isRepresentative } = fileInfoResponse.data;
            
            const fileInfo = {
              objid: objidStr,
              realFileName: realFileName,
              fileExt: fileExt,
              fileSize: fileSize,
              filePath: getFilePreviewUrl(objidStr),
              regdate: regdate,
              isImage: true,
              isRepresentative: isRepresentative,
            };
            
            setUploadedFiles([fileInfo]);
            // representativeImageUrl은 loadRepresentativeImage에서 blob으로 로드됨
          } else {
            // 파일 정보 조회 실패 시 최소 정보로 추가
            console.warn("🖼️ [FileUploadComponent] 파일 정보 조회 실패, 최소 정보 사용");
            const minimalFileInfo = {
              objid: objidStr,
              realFileName: `image_${objidStr}.jpg`,
              fileExt: '.jpg',
              fileSize: 0,
              filePath: getFilePreviewUrl(objidStr),
              regdate: new Date().toISOString(),
              isImage: true,
            };
            
            setUploadedFiles([minimalFileInfo]);
            // representativeImageUrl은 loadRepresentativeImage에서 blob으로 로드됨
          }
        } catch (error) {
          console.error("🖼️ [FileUploadComponent] 파일 정보 조회 오류:", error);
        }
      })();
    }
  }, [imageObjidFromFormData, columnName, component.id]); // 🆕 formData 대신 특정 컬럼 값만 의존

  // 🎯 화면설계 모드에서 실제 화면으로의 실시간 동기화 이벤트 리스너
  // 🆕 columnName도 체크하여 같은 화면의 다른 파일 업로드 컴포넌트와 구분
  useEffect(() => {
    const handleDesignModeFileChange = (event: CustomEvent) => {
      const eventColumnName = event.detail.eventColumnName || event.detail.columnName;
      
      // 🆕 고유 키 또는 (컴포넌트ID + 컬럼명) 조합으로 체크
      const isForThisComponent = 
        (event.detail.uniqueKey && event.detail.uniqueKey === currentUniqueKey) ||
        (event.detail.componentId === component.id && eventColumnName === columnName) ||
        (event.detail.componentId === component.id && !eventColumnName); // 이전 호환성

      // 🆕 현재 컴포넌트와 일치하고 화면설계 모드에서 온 이벤트인 경우
      if (isForThisComponent && event.detail.source === "designMode") {
        // 파일 상태 업데이트
        const newFiles = event.detail.files || [];
        setUploadedFiles(newFiles);

        // localStorage 백업 업데이트 (레코드별 고유 키 사용)
        try {
          const backupKey = currentUniqueKey;
          localStorage.setItem(backupKey, JSON.stringify(newFiles));
        } catch (e) {
          console.warn("localStorage 백업 업데이트 실패:", e);
        }

        // 전역 상태 업데이트 (🆕 고유 키 사용)
        if (typeof window !== "undefined") {
          (window as any).globalFileState = {
            ...(window as any).globalFileState,
            [currentUniqueKey]: newFiles,
          };
        }

        // onUpdate 콜백 호출 (부모 컴포넌트에 알림)
        if (onUpdate) {
          onUpdate({
            uploadedFiles: newFiles,
            lastFileUpdate: event.detail.timestamp,
          });
        }
      }
    };

    if (typeof window !== "undefined") {
      window.addEventListener("globalFileStateChanged", handleDesignModeFileChange as EventListener);

      return () => {
        window.removeEventListener("globalFileStateChanged", handleDesignModeFileChange as EventListener);
      };
    }
  }, [component.id, onUpdate]);

  // 템플릿 파일과 데이터 파일을 조회하는 함수
  const loadComponentFiles = useCallback(async () => {
    if (!component?.id) return false;

    // 🔑 등록 모드(새 레코드)인 경우 파일 조회 스킵 - 빈 상태 유지
    if (!isRecordMode || !recordId) {
      return false;
    }

    try {
      // 1. formData에서 screenId 가져오기
      let screenId = formData?.screenId;
      
      // 2. URL에서 screenId 추출 (/screens/:id 패턴)
      if (!screenId && typeof window !== "undefined") {
        const pathname = window.location.pathname;
        const screenMatch = pathname.match(/\/screens\/(\d+)/);
        if (screenMatch) {
          screenId = parseInt(screenMatch[1]);
        }
      }

      // 3. 디자인 모드인 경우 임시 화면 ID 사용
      if (!screenId && isDesignMode) {
        screenId = 999999; // 디자인 모드 임시 ID
      }

      // 4. 화면 ID가 없으면 컴포넌트 ID만으로 조회 시도
      if (!screenId) {
        console.warn("⚠️ 화면 ID 없음, 컴포넌트 ID만으로 파일 조회:", {
          componentId: component.id,
          pathname: window.location.pathname,
          formData: formData,
        });
        // screenId를 0으로 설정하여 컴포넌트 ID로만 조회
        screenId = 0;
      }

      const params = {
        screenId,
        componentId: component.id,
        tableName: recordTableName || formData?.tableName || component.tableName,
        recordId: recordId || formData?.id,
        columnName: columnName, // 🔑 레코드 모드에서 사용하는 columnName
      };

      const response = await getComponentFiles(params);

      if (response.success) {

        // 파일 데이터 형식 통일
        const formattedFiles = response.totalFiles.map((file: any) => ({
          objid: file.objid || file.id,
          savedFileName: file.savedFileName || file.saved_file_name,
          realFileName: file.realFileName || file.real_file_name,
          fileSize: file.fileSize || file.file_size,
          fileExt: file.fileExt || file.file_ext,
          regdate: file.regdate,
          status: file.status || "ACTIVE",
          uploadedAt: file.uploadedAt || new Date().toISOString(),
          ...file,
        }));


        // 🔄 localStorage의 기존 파일과 서버 파일 병합 (레코드별 고유 키 사용)
        let finalFiles = formattedFiles;
        const uniqueKey = getUniqueKey();
        try {
          const backupFiles = localStorage.getItem(uniqueKey);
          if (backupFiles) {
            const parsedBackupFiles = JSON.parse(backupFiles);

            // 서버에 없는 localStorage 파일들을 추가 (objid 기준으로 중복 제거)
            const serverObjIds = new Set(formattedFiles.map((f: any) => f.objid));
            const additionalFiles = parsedBackupFiles.filter((f: any) => !serverObjIds.has(f.objid));

            finalFiles = [...formattedFiles, ...additionalFiles];
          }
        } catch (e) {
          console.warn("파일 병합 중 오류:", e);
        }

        setUploadedFiles(finalFiles);

        // 전역 상태에도 저장 (레코드별 고유 키 사용)
        if (typeof window !== "undefined") {
          (window as any).globalFileState = {
            ...(window as any).globalFileState,
            [uniqueKey]: finalFiles,
          };

          // 🌐 전역 파일 저장소에 등록 (페이지 간 공유용)
          GlobalFileManager.registerFiles(finalFiles, {
            uploadPage: window.location.pathname,
            componentId: component.id,
            screenId: formData?.screenId,
            recordId: recordId,
          });

          // localStorage 백업도 병합된 파일로 업데이트 (레코드별 고유 키 사용)
          try {
            localStorage.setItem(uniqueKey, JSON.stringify(finalFiles));
          } catch (e) {
            console.warn("localStorage 백업 업데이트 실패:", e);
          }
        }
        return true; // 새로운 로직 사용됨
      }
    } catch (error) {
      console.error("파일 조회 오류:", error);
    }
    return false; // 기존 로직 사용
  }, [component.id, component.tableName, component.columnName, formData?.screenId, formData?.tableName, formData?.id, getUniqueKey, recordId, isRecordMode, recordTableName, columnName]);

  // 컴포넌트 파일 동기화 (DB 우선, localStorage는 보조)
  useEffect(() => {
    const componentFiles = (component as any)?.uploadedFiles || [];
    const lastUpdate = (component as any)?.lastFileUpdate;

    // 🔒 항상 DB에서 최신 파일 목록을 조회 (멀티테넌시 격리)
    loadComponentFiles().then((dbLoadSuccess) => {
      if (dbLoadSuccess) {
        return; // DB 로드 성공 시 localStorage 무시
      }

      // 🆕 등록 모드(새 레코드)인 경우 fallback 로드도 스킵 - 항상 빈 상태 유지
      if (!isRecordMode || !recordId) {
        return;
      }

      // DB 로드 실패 시에만 기존 로직 사용 (하위 호환성)

      // 전역 상태에서 최신 파일 정보 가져오기 (🆕 고유 키 사용)
      const globalFileState = typeof window !== "undefined" ? (window as any).globalFileState || {} : {};
      const uniqueKeyForFallback = getUniqueKey();
      const globalFiles = globalFileState[uniqueKeyForFallback] || globalFileState[component.id] || [];

      // 최신 파일 정보 사용 (전역 상태 > 컴포넌트 속성)
      const currentFiles = globalFiles.length > 0 ? globalFiles : componentFiles;


      // 최신 파일과 현재 파일 비교
      if (JSON.stringify(currentFiles) !== JSON.stringify(uploadedFiles)) {
        setUploadedFiles(currentFiles);
        setForceUpdate((prev) => prev + 1);
      }
    });
  }, [loadComponentFiles, component.id, (component as any)?.uploadedFiles, (component as any)?.lastFileUpdate]);

  // 전역 상태 변경 감지 (모든 파일 컴포넌트 동기화 + 화면 복원)
  // 🆕 columnName을 포함한 고유 키로 구분하여 다른 파일 업로드 컴포넌트에 영향 방지
  const currentUniqueKey = getUniqueKey();
  
  useEffect(() => {
    const handleGlobalFileStateChange = (event: CustomEvent) => {
      const { componentId, files, fileCount, timestamp, isRestore, uniqueKey: eventUniqueKey, eventColumnName } = event.detail;

      // 🆕 고유 키 또는 (컴포넌트ID + 컬럼명) 조합으로 체크
      const isForThisComponent = 
        (eventUniqueKey && eventUniqueKey === currentUniqueKey) ||
        (componentId === component.id && eventColumnName === columnName);

      // 🆕 같은 고유 키인 경우에만 업데이트 (componentId + columnName 조합)
      if (isForThisComponent) {

        setUploadedFiles(files);
        setForceUpdate((prev) => prev + 1);

        // localStorage 백업도 업데이트 (레코드별 고유 키 사용)
        try {
          const backupKey = currentUniqueKey;
          localStorage.setItem(backupKey, JSON.stringify(files));
        } catch (e) {
          console.warn("localStorage 백업 실패:", e);
        }
      }
    };

    if (typeof window !== "undefined") {
      window.addEventListener("globalFileStateChanged", handleGlobalFileStateChange as EventListener);

      return () => {
        window.removeEventListener("globalFileStateChanged", handleGlobalFileStateChange as EventListener);
      };
    }
  }, [component.id, columnName, currentUniqueKey, uploadedFiles.length]);

  // 파일 업로드 설정 - componentConfig가 undefined일 수 있으므로 안전하게 처리
  const safeComponentConfig = componentConfig || {};
  const fileConfig = {
    ...safeComponentConfig,
    accept: safeComponentConfig.accept || "*/*",
    multiple: safeComponentConfig.multiple || false,
    maxSize: safeComponentConfig.maxSize || 10 * 1024 * 1024, // 10MB
    maxFiles: safeComponentConfig.maxFiles || 5,
  } as FileUploadConfig;

  // 파일 선택 핸들러
  const handleFileSelect = useCallback(() => {
    if (fileInputRef.current) {
      fileInputRef.current.click();
    }
  }, []);

  const handleInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(e.target.files || []);
    if (files.length > 0) {
      handleFileUpload(files);
    }
  }, []);

  // 파일 업로드 처리
  const handleFileUpload = useCallback(
    async (files: File[]) => {
      if (!files.length) return;

      // 중복 파일 체크
      const existingFileNames = uploadedFiles.map((f) => f.realFileName.toLowerCase());
      const duplicates: string[] = [];
      const uniqueFiles: File[] = [];

      files.forEach((file) => {
        const fileName = file.name.toLowerCase();
        if (existingFileNames.includes(fileName)) {
          duplicates.push(file.name);
        } else {
          uniqueFiles.push(file);
        }
      });

      if (duplicates.length > 0) {
        toast.error(`중복된 파일이 있습니다: ${duplicates.join(", ")}`, {
          description: "같은 이름의 파일이 이미 업로드되어 있습니다.",
          duration: 4000,
        });

        if (uniqueFiles.length === 0) {
          return; // 모든 파일이 중복이면 업로드 중단
        }

        // 일부만 중복인 경우 고유한 파일만 업로드
        toast.info(`${uniqueFiles.length}개의 새로운 파일만 업로드합니다.`);
      }

      const filesToUpload = uniqueFiles.length > 0 ? uniqueFiles : files;
      setUploadStatus("uploading");
      toast.loading("파일을 업로드하는 중...", { id: "file-upload" });

      try {
        // 🔑 레코드 모드 우선 사용
        const effectiveTableName = recordTableName || formData?.tableName || component.tableName || "default_table";
        const effectiveRecordId = recordId || formData?.id;
        const effectiveColumnName = columnName;
        
        // screenId 추출 (우선순위: formData > URL)
        let screenId = formData?.screenId;
        if (!screenId && typeof window !== "undefined") {
          const pathname = window.location.pathname;
          const screenMatch = pathname.match(/\/screens\/(\d+)/);
          if (screenMatch) {
            screenId = parseInt(screenMatch[1]);
          }
        }

        let targetObjid;
        // 🔑 레코드 모드 판단 개선
        const effectiveIsRecordMode = isRecordMode || (effectiveRecordId && !String(effectiveRecordId).startsWith('temp_'));
        
        if (effectiveIsRecordMode && effectiveTableName && effectiveRecordId) {
          // 🎯 레코드 모드: 특정 행에 파일 연결
          targetObjid = `${effectiveTableName}:${effectiveRecordId}:${effectiveColumnName}`;
        } else if (screenId) {
          // 🔑 템플릿 파일 (백엔드 조회 형식과 동일하게)
          targetObjid = `screen_files:${screenId}:${component.id}:${effectiveColumnName}`;
        } else {
          // 기본값 (화면관리에서 사용)
          targetObjid = `temp_${component.id}`;
        }

        // 🔒 현재 사용자의 회사 코드 가져오기 (멀티테넌시 격리)
        const userCompanyCode = user?.companyCode || (window as any).__user__?.companyCode;
        
        // 🔑 레코드 모드일 때는 effectiveTableName을 우선 사용
        // formData.linkedTable이 'screen_files' 같은 기본값일 수 있으므로 레코드 모드에서는 무시
        const finalLinkedTable = effectiveIsRecordMode 
          ? effectiveTableName 
          : (formData?.linkedTable || effectiveTableName);
        
        const uploadData = {
          // 🎯 formData에서 백엔드 API 설정 가져오기
          autoLink: formData?.autoLink || true,
          linkedTable: finalLinkedTable,
          recordId: effectiveRecordId || `temp_${component.id}`,
          columnName: effectiveColumnName,
          isVirtualFileColumn: formData?.isVirtualFileColumn || true,
          docType: component.fileConfig?.docType || "DOCUMENT",
          docTypeName: component.fileConfig?.docTypeName || "일반 문서",
          companyCode: userCompanyCode, // 🔒 멀티테넌시: 회사 코드 명시적 전달
          // 호환성을 위한 기존 필드들
          tableName: effectiveTableName,
          fieldName: effectiveColumnName,
          targetObjid: targetObjid, // InteractiveDataTable 호환을 위한 targetObjid 추가
          // 🆕 레코드 모드 플래그
          isRecordMode: effectiveIsRecordMode,
        };
        
        const response = await uploadFiles({
          files: filesToUpload,
          ...uploadData,
        });

        if (response.success) {
          // FileUploadResponse 타입에 맞게 files 배열 사용
          const fileData = response.files || (response as any).data || [];

          if (fileData.length === 0) {
            throw new Error("업로드된 파일 데이터를 받지 못했습니다.");
          }

          const newFiles = fileData.map((file: any) => ({
            objid: file.objid || file.id,
            savedFileName: file.saved_file_name || file.savedFileName,
            realFileName: file.real_file_name || file.realFileName || file.name,
            fileSize: file.file_size || file.fileSize || file.size,
            fileExt: file.file_ext || file.fileExt || file.extension,
            filePath: file.file_path || file.filePath || file.path,
            docType: file.doc_type || file.docType,
            docTypeName: file.doc_type_name || file.docTypeName,
            targetObjid: file.target_objid || file.targetObjid,
            parentTargetObjid: file.parent_target_objid || file.parentTargetObjid,
            companyCode: file.company_code || file.companyCode,
            writer: file.writer,
            regdate: file.regdate,
            status: file.status || "ACTIVE",
            uploadedAt: new Date().toISOString(),
            ...file,
          }));


          const updatedFiles = [...uploadedFiles, ...newFiles];

          setUploadedFiles(updatedFiles);
          setUploadStatus("success");

          // localStorage 백업 (레코드별 고유 키 사용)
          try {
            const backupKey = getUniqueKey();
            localStorage.setItem(backupKey, JSON.stringify(updatedFiles));
          } catch (e) {
            console.warn("localStorage 백업 실패:", e);
          }

          // 전역 상태 업데이트 (모든 파일 컴포넌트 동기화)
          if (typeof window !== "undefined") {
            // 전역 파일 상태 업데이트 (레코드별 고유 키 사용)
            const globalFileState = (window as any).globalFileState || {};
            const uniqueKey = getUniqueKey();
            globalFileState[uniqueKey] = updatedFiles;
            (window as any).globalFileState = globalFileState;

            // 🌐 전역 파일 저장소에 새 파일 등록 (페이지 간 공유용)
            GlobalFileManager.registerFiles(newFiles, {
              uploadPage: window.location.pathname,
              componentId: component.id,
              screenId: formData?.screenId,
              recordId: recordId, // 🆕 레코드 ID 추가
            });

            // 모든 파일 컴포넌트에 동기화 이벤트 발생
            // 🆕 columnName 추가하여 같은 화면의 다른 파일 업로드 컴포넌트와 구분
            const syncEvent = new CustomEvent("globalFileStateChanged", {
              detail: {
                componentId: component.id,
                eventColumnName: columnName, // 🆕 컬럼명 추가
                uniqueKey: uniqueKey, // 🆕 고유 키 추가
                recordId: recordId, // 🆕 레코드 ID 추가
                files: updatedFiles,
                fileCount: updatedFiles.length,
                timestamp: Date.now(),
              },
            });
            window.dispatchEvent(syncEvent);
          }

          // 컴포넌트 업데이트
          if (onUpdate) {
            const timestamp = Date.now();
            onUpdate({
              uploadedFiles: updatedFiles,
              lastFileUpdate: timestamp,
            });
          } else {
            console.warn("⚠️ onUpdate 콜백이 없습니다!");
          }

          // 🆕 이미지/파일 컬럼에 objid 저장 (formData 업데이트)
          if (onFormDataChange && effectiveColumnName) {
            // 🎯 이미지/파일 타입 컬럼: 첫 번째 파일의 objid를 저장 (그리드에서 표시용)
            // 단일 파일인 경우 단일 값, 복수 파일인 경우 콤마 구분 문자열
            const fileObjids = updatedFiles.map(file => file.objid);
            const columnValue = fileConfig.multiple 
              ? fileObjids.join(',')  // 복수 파일: 콤마 구분
              : (fileObjids[0] || ''); // 단일 파일: 첫 번째 파일 ID
            
            // onFormDataChange를 (fieldName, value) 형태로 호출 (SaveModal 호환)
            onFormDataChange(effectiveColumnName, columnValue);
          }

          // 그리드 파일 상태 새로고침 이벤트 발생
          if (typeof window !== "undefined") {
            const refreshEvent = new CustomEvent("refreshFileStatus", {
              detail: {
                tableName: effectiveTableName,
                recordId: effectiveRecordId,
                columnName: effectiveColumnName,
                targetObjid: targetObjid,
                fileCount: updatedFiles.length,
              },
            });
            window.dispatchEvent(refreshEvent);
          }

          // 컴포넌트 설정 콜백
          if (safeComponentConfig.onFileUpload) {
            safeComponentConfig.onFileUpload(newFiles);
          }

          // 성공 시 토스트 처리
          setUploadStatus("idle");
          toast.dismiss("file-upload");
          toast.success(`${newFiles.length}개 파일 업로드 완료`);
        } else {
          console.error("❌ 파일 업로드 실패:", response);
          throw new Error(response.message || (response as any).error || "파일 업로드에 실패했습니다.");
        }
      } catch (error) {
        console.error("파일 업로드 오류:", error);
        setUploadStatus("error");
        toast.dismiss("file-upload");
        toast.error(`파일 업로드 오류: ${error instanceof Error ? error.message : "알 수 없는 오류"}`);
      }
    },
    [safeComponentConfig, uploadedFiles, onFormDataChange, component.columnName, component.id, formData],
  );

  // 파일 뷰어 열기
  const handleFileView = useCallback((file: FileInfo) => {
    setViewerFile(file);
    setIsViewerOpen(true);
  }, []);

  // 파일 뷰어 닫기
  const handleViewerClose = useCallback(() => {
    setIsViewerOpen(false);
    setViewerFile(null);
  }, []);

  // 파일 다운로드
  const handleFileDownload = useCallback(async (file: FileInfo) => {
    try {
      await downloadFile({
        fileId: file.objid,
        serverFilename: file.savedFileName,
        originalName: file.realFileName,
      });
      toast.success(`${file.realFileName} 다운로드 완료`);
    } catch (error) {
      console.error("파일 다운로드 오류:", error);
      toast.error("파일 다운로드에 실패했습니다.");
    }
  }, []);

  // 파일 삭제
  const handleFileDelete = useCallback(
    async (file: FileInfo | string) => {
      try {
        const fileId = typeof file === "string" ? file : file.objid;
        const fileName = typeof file === "string" ? "파일" : file.realFileName;

        const serverFilename = typeof file === "string" ? "temp_file" : file.savedFileName;
        await deleteFile(fileId, serverFilename);

        const updatedFiles = uploadedFiles.filter((f) => f.objid !== fileId);
        setUploadedFiles(updatedFiles);

        // localStorage 백업 업데이트 (레코드별 고유 키 사용)
        try {
          const backupKey = getUniqueKey();
          localStorage.setItem(backupKey, JSON.stringify(updatedFiles));
        } catch (e) {
          console.warn("localStorage 백업 업데이트 실패:", e);
        }

        // 전역 상태 업데이트 (모든 파일 컴포넌트 동기화)
        if (typeof window !== "undefined") {
          // 전역 파일 상태 업데이트 (레코드별 고유 키 사용)
          const globalFileState = (window as any).globalFileState || {};
          const uniqueKey = getUniqueKey();
          globalFileState[uniqueKey] = updatedFiles;
          (window as any).globalFileState = globalFileState;

          // 모든 파일 컴포넌트에 동기화 이벤트 발생
          // 🆕 columnName 추가하여 같은 화면의 다른 파일 업로드 컴포넌트와 구분
          const syncEvent = new CustomEvent("globalFileStateChanged", {
            detail: {
              componentId: component.id,
              eventColumnName: columnName, // 🆕 컬럼명 추가
              uniqueKey: uniqueKey, // 🆕 고유 키 추가
              recordId: recordId, // 🆕 레코드 ID 추가
              files: updatedFiles,
              fileCount: updatedFiles.length,
              timestamp: Date.now(),
              source: "realScreen", // 🎯 실제 화면에서 온 이벤트임을 표시
              action: "delete",
            },
          });
          window.dispatchEvent(syncEvent);
        }

        // 컴포넌트 업데이트
        if (onUpdate) {
          const timestamp = Date.now();
          onUpdate({
            uploadedFiles: updatedFiles,
            lastFileUpdate: timestamp,
          });
        }

        // 🆕 파일 삭제 후 컬럼 데이터 동기화
        if (onFormDataChange && columnName) {
          // 🎯 삭제 후 남은 파일들의 objid로 컬럼 값 업데이트
          const fileObjids = updatedFiles.map(f => f.objid);
          const columnValue = fileConfig.multiple 
            ? fileObjids.join(',')
            : (fileObjids[0] || '');
          
          // onFormDataChange를 (fieldName, value) 형태로 호출 (SaveModal 호환)
          onFormDataChange(columnName, columnValue);
        }

        toast.success(`${fileName} 삭제 완료`);
      } catch (error) {
        console.error("파일 삭제 오류:", error);
        toast.error("파일 삭제에 실패했습니다.");
      }
    },
    [uploadedFiles, onUpdate, component.id, isRecordMode, onFormDataChange, recordTableName, recordId, columnName, getUniqueKey],
  );

  // 대표 이미지 Blob URL 로드
  const loadRepresentativeImage = useCallback(
    async (file: FileInfo) => {
      try {
        const isImage = ["jpg", "jpeg", "png", "gif", "bmp", "webp", "svg"].includes(
          file.fileExt.toLowerCase().replace(".", "")
        );

        if (!isImage) {
          setRepresentativeImageUrl(null);
          return;
        }

        // objid가 없거나 유효하지 않으면 로드 중단
        if (!file.objid || file.objid === "0" || file.objid === "") {
          console.warn("⚠️ 대표 이미지 로드 실패: objid가 없음", file);
          setRepresentativeImageUrl(null);
          return;
        }

        // API 클라이언트를 통해 Blob으로 다운로드 (인증 토큰 포함)
        // 🔑 previewUrl 상대 경로 대신 apiClient를 사용하여 Docker 환경에서도 정상 동작
        const response = await apiClient.get(`/files/preview/${file.objid}`, {
          params: {
            serverFilename: file.savedFileName,
          },
          responseType: "blob",
        });

        // Blob URL 생성
        const blob = new Blob([response.data]);
        const url = window.URL.createObjectURL(blob);
        
        // 이전 URL 정리
        if (representativeImageUrl) {
          window.URL.revokeObjectURL(representativeImageUrl);
        }

        setRepresentativeImageUrl(url);
      } catch (error: any) {
        console.error("❌ 대표 이미지 로드 실패:", {
          file: file.realFileName,
          objid: file.objid,
          error: error?.response?.status || error?.message,
        });
        setRepresentativeImageUrl(null);
      }
    },
    [representativeImageUrl],
  );

  // 대표 이미지 설정 핸들러
  const handleSetRepresentative = useCallback(
    async (file: FileInfo) => {
      try {
        // API 호출하여 DB에 대표 파일 설정
        const { setRepresentativeFile } = await import("@/lib/api/file");
        await setRepresentativeFile(file.objid);

        // 상태 업데이트
        const updatedFiles = uploadedFiles.map((f) => ({
          ...f,
          isRepresentative: f.objid === file.objid,
        }));

        setUploadedFiles(updatedFiles);

        // 대표 이미지 로드
        loadRepresentativeImage(file);
      } catch (e) {
        console.error("❌ 대표 파일 설정 실패:", e);
      }
    },
    [uploadedFiles, component.id, loadRepresentativeImage]
  );

  // uploadedFiles 변경 시 대표 이미지 로드
  useEffect(() => {
    const representativeFile = uploadedFiles.find(f => f.isRepresentative) || uploadedFiles[0];
    if (representativeFile) {
      loadRepresentativeImage(representativeFile);
    } else {
      setRepresentativeImageUrl(null);
    }

    // 컴포넌트 언마운트 시 Blob URL 정리
    return () => {
      if (representativeImageUrl) {
        window.URL.revokeObjectURL(representativeImageUrl);
      }
    };
  }, [uploadedFiles]);

  // 드래그 앤 드롭 핸들러
  const handleDragOver = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      e.stopPropagation();
      if (!safeComponentConfig.readonly && !safeComponentConfig.disabled) {
        setDragOver(true);
      }
    },
    [safeComponentConfig.readonly, safeComponentConfig.disabled],
  );

  const handleDragLeave = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setDragOver(false);
  }, []);

  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      e.stopPropagation();
      setDragOver(false);

      if (!safeComponentConfig.readonly && !safeComponentConfig.disabled) {
        const files = Array.from(e.dataTransfer.files);
        if (files.length > 0) {
          handleFileUpload(files);
        }
      }
    },
    [safeComponentConfig.readonly, safeComponentConfig.disabled, handleFileUpload],
  );

  // 클릭 핸들러
  const handleClick = useCallback(
    (e: React.MouseEvent) => {
      e.preventDefault();
      e.stopPropagation();
      if (!safeComponentConfig.readonly && !safeComponentConfig.disabled) {
        handleFileSelect();
      }
      onClick?.();
    },
    [safeComponentConfig.readonly, safeComponentConfig.disabled, handleFileSelect, onClick],
  );

  return (
    <div
      style={{
        ...componentStyle,
        width: "100%", // 🆕 부모 컨테이너 너비에 맞춤
        height: "100%", // 🆕 부모 컨테이너 높이에 맞춤
        border: "none !important",
        boxShadow: "none !important",
        outline: "none !important",
        backgroundColor: "transparent !important",
        padding: "0px !important",
        borderRadius: "0px !important",
        marginBottom: "8px !important",
      }}
      className={`${className} file-upload-container`}
    >
      {/* 라벨 렌더링 */}
      {component.label && component.style?.labelDisplay !== false && (
        <label
          style={{
            position: "absolute",
            top: "-20px",
            left: "0px",
            fontSize: "12px",
            color: "rgb(107, 114, 128)",
            fontWeight: "400",
            background: "transparent !important",
            border: "none !important",
            boxShadow: "none !important",
            outline: "none !important",
            padding: "0px !important",
            margin: "0px !important"
          }}
        >
          {component.label}
          {component.required && (
            <span style={{ color: "#ef4444" }}>*</span>
          )}
        </label>
      )}

      <div
        className="border-border bg-card relative flex h-full w-full flex-col rounded-lg border overflow-hidden"
      >
        {/* 대표 이미지 전체 화면 표시 */}
        {uploadedFiles.length > 0 ? (() => {
          const representativeFile = uploadedFiles.find(f => f.isRepresentative) || uploadedFiles[0];
          const isImage = representativeFile && ["jpg", "jpeg", "png", "gif", "bmp", "webp", "svg"].includes(
            representativeFile.fileExt.toLowerCase().replace(".", "")
          );

          return (
            <>
              {isImage && representativeImageUrl ? (
                <div className="relative h-full w-full flex items-center justify-center bg-muted/10">
                  <img
                    src={representativeImageUrl}
                    alt={representativeFile.realFileName}
                    className="h-full w-full object-contain"
                  />
                </div>
              ) : isImage && !representativeImageUrl ? (
                <div className="flex h-full w-full flex-col items-center justify-center">
                  <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary mb-2"></div>
                  <p className="text-sm text-muted-foreground">이미지 로딩 중...</p>
                </div>
              ) : (
                <div className="flex h-full w-full flex-col items-center justify-center">
                  {getFileIcon(representativeFile.fileExt)}
                  <p className="mt-3 text-sm font-medium text-center px-4">
                    {representativeFile.realFileName}
                  </p>
                  <Badge variant="secondary" className="mt-2">
                    대표 파일
                  </Badge>
                </div>
              )}
              
              {/* 우측 하단 자세히보기 버튼 */}
              <div className="absolute bottom-3 right-3">
                <Button
                  variant="secondary"
                  size="sm"
                  className="h-8 px-3 text-xs shadow-md"
                  onClick={() => setIsFileManagerOpen(true)}
                >
                  자세히보기 ({uploadedFiles.length})
                </Button>
              </div>
            </>
          );
        })() : (
          <div className="flex h-full w-full flex-col items-center justify-center text-muted-foreground">
            <File className="mb-3 h-12 w-12" />
            <p className="text-sm font-medium">업로드된 파일이 없습니다</p>
            <Button
              variant="outline"
              size="sm"
              className="mt-4 h-8 px-3 text-xs"
              onClick={() => setIsFileManagerOpen(true)}
            >
              파일 업로드
            </Button>
          </div>
        )}
      </div>

      {/* 파일뷰어 모달 */}
      <FileViewerModal
        file={viewerFile}
        isOpen={isViewerOpen}
        onClose={handleViewerClose}
        onDownload={handleFileDownload}
        onDelete={!isDesignMode ? handleFileDelete : undefined}
      />

      {/* 파일 관리 모달 */}
      <FileManagerModal
        isOpen={isFileManagerOpen}
        onClose={() => setIsFileManagerOpen(false)}
        uploadedFiles={uploadedFiles}
        onFileUpload={handleFileUpload}
        onFileDownload={handleFileDownload}
        onFileDelete={handleFileDelete}
        onFileView={handleFileView}
        onSetRepresentative={handleSetRepresentative}
        config={fileConfig}
        isDesignMode={isDesignMode}
      />
    </div>
  );
};

export { FileUploadComponent };
export default FileUploadComponent;
