"use client";

import React, { useState, useCallback, useEffect } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { useAuth } from "@/hooks/useAuth";
import { uploadFilesAndCreateData } from "@/lib/api/file";
import { toast } from "sonner";
import { ComponentData, WidgetComponent, DataTableComponent, FileComponent, ButtonTypeConfig } from "@/types/screen";
import { FileUploadComponent } from "@/lib/registry/components/file-upload/FileUploadComponent";
import { InteractiveDataTable } from "./InteractiveDataTable";
import { DynamicWebTypeRenderer } from "@/lib/registry";
import { DynamicComponentRenderer } from "@/lib/registry/DynamicComponentRenderer";
import { filterDOMProps } from "@/lib/utils/domPropsFilter";
import { isFileComponent, isDataTableComponent, isButtonComponent } from "@/lib/utils/componentTypeUtils";
import { FlowButtonGroup } from "./widgets/FlowButtonGroup";
import { FlowVisibilityConfig } from "@/types/control-management";
import { findAllButtonGroups } from "@/lib/utils/flowButtonGroupUtils";
import { useScreenPreview } from "@/contexts/ScreenPreviewContext";
import { useSplitPanelContext } from "@/contexts/SplitPanelContext";
import { evaluateConditional } from "@/lib/utils/conditionalEvaluator";

// 컴포넌트 렌더러들을 강제로 로드하여 레지스트리에 등록
import "@/lib/registry/components/ButtonRenderer";
import "@/lib/registry/components/CardRenderer";
import "@/lib/registry/components/DashboardRenderer";
import "@/lib/registry/components/WidgetRenderer";
import { dynamicFormApi, DynamicFormData } from "@/lib/api/dynamicForm";
import { useParams } from "next/navigation";
import { screenApi } from "@/lib/api/screen";

interface InteractiveScreenViewerProps {
  component: ComponentData;
  allComponents: ComponentData[];
  formData?: Record<string, any>;
  onFormDataChange?: (fieldName: string, value: any) => void;
  hideLabel?: boolean;
  screenInfo?: {
    id: number;
    tableName?: string;
  };
  menuObjid?: number; // 메뉴 OBJID (코드 스코프용)
  onSave?: () => Promise<void>;
  onRefresh?: () => void;
  onFlowRefresh?: () => void;
  // 외부에서 전달받는 사용자 정보 (ScreenModal 등에서 사용)
  userId?: string;
  userName?: string;
  companyCode?: string;
  // 그룹 데이터 (EditModal에서 전달)
  groupedData?: Record<string, any>[];
  // 비활성화할 필드 목록 (EditModal에서 전달)
  disabledFields?: string[];
  // EditModal 내부인지 여부 (button-primary가 EditModal의 handleSave 사용하도록)
  isInModal?: boolean;
  // 원본 데이터 (수정 모드에서 UPDATE 판단용)
  originalData?: Record<string, any> | null;
  // 탭 관련 정보 (탭 내부의 컴포넌트에서 사용)
  parentTabId?: string; // 부모 탭 ID
  parentTabsComponentId?: string; // 부모 탭 컴포넌트 ID
}

export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerProps> = ({
  component,
  allComponents,
  formData: externalFormData,
  onFormDataChange,
  hideLabel = false,
  screenInfo,
  menuObjid,
  onSave,
  onRefresh,
  onFlowRefresh,
  userId: externalUserId,
  userName: externalUserName,
  companyCode: externalCompanyCode,
  groupedData,
  disabledFields = [],
  isInModal = false,
  originalData,
  parentTabId,
  parentTabsComponentId,
}) => {
  const { isPreviewMode } = useScreenPreview(); // 프리뷰 모드 확인
  const { userName: authUserName, user: authUser } = useAuth();
  const splitPanelContext = useSplitPanelContext(); // 분할 패널 컨텍스트

  // 외부에서 전달받은 사용자 정보가 있으면 우선 사용 (ScreenModal 등에서)
  const userName = externalUserName || authUserName;
  const user =
    externalUserId && externalUserId !== authUser?.userId
      ? {
          userId: externalUserId,
          userName: externalUserName || authUserName || "",
          companyCode: externalCompanyCode || authUser?.companyCode || "",
          isAdmin: authUser?.isAdmin || false,
        }
      : authUser;
  const [localFormData, setLocalFormData] = useState<Record<string, any>>({});
  const [dateValues, setDateValues] = useState<Record<string, Date | undefined>>({});

  // 테이블에서 선택된 행 데이터 (버튼 액션에 전달)
  const [selectedRowsData, setSelectedRowsData] = useState<any[]>([]);

  // 플로우에서 선택된 데이터 (버튼 액션에 전달)
  const [flowSelectedData, setFlowSelectedData] = useState<any[]>([]);
  const [flowSelectedStepId, setFlowSelectedStepId] = useState<number | null>(null);

  // 팝업 화면 상태
  const [popupScreen, setPopupScreen] = useState<{
    screenId: number;
    title: string;
    size: string;
  } | null>(null);

  // 팝업 화면 레이아웃 상태
  const [popupLayout, setPopupLayout] = useState<ComponentData[]>([]);
  const [popupLoading, setPopupLoading] = useState(false);
  const [popupScreenResolution, setPopupScreenResolution] = useState<{ width: number; height: number } | null>(null);
  const [popupScreenInfo, setPopupScreenInfo] = useState<{ id: number; tableName?: string } | null>(null);

  // 팝업 전용 formData 상태
  const [popupFormData, setPopupFormData] = useState<Record<string, any>>({});

  // 🆕 분할 패널에서 매핑된 부모 데이터 가져오기
  // disableAutoDataTransfer가 true이면 자동 전달 비활성화 (버튼 클릭으로만 전달)
  const splitPanelMappedData = React.useMemo(() => {
    if (splitPanelContext && !splitPanelContext.disableAutoDataTransfer) {
      return splitPanelContext.getMappedParentData();
    }
    return {};
  }, [splitPanelContext, splitPanelContext?.selectedLeftData, splitPanelContext?.disableAutoDataTransfer]);

  // formData 결정 (외부에서 전달받은 것이 있으면 우선 사용, 분할 패널 데이터도 병합)
  const formData = React.useMemo(() => {
    const baseData = externalFormData || localFormData;
    // 분할 패널 매핑 데이터가 있으면 병합 (기존 값이 없는 경우에만)
    // disableAutoDataTransfer가 true이면 자동 병합 안함
    if (Object.keys(splitPanelMappedData).length > 0) {
      const merged = { ...baseData };
      for (const [key, value] of Object.entries(splitPanelMappedData)) {
        // 기존 값이 없거나 빈 값인 경우에만 매핑 데이터 적용
        if (merged[key] === undefined || merged[key] === null || merged[key] === "") {
          merged[key] = value;
        }
      }
      return merged;
    }
    return baseData;
  }, [externalFormData, localFormData, splitPanelMappedData]);

  // formData 업데이트 함수
  const updateFormData = useCallback(
    (fieldName: string, value: any) => {
      if (onFormDataChange) {
        onFormDataChange(fieldName, value);
      } else {
        setLocalFormData((prev) => ({
          ...prev,
          [fieldName]: value,
        }));
      }
    },
    [onFormDataChange],
  );

  // 자동값 생성 함수
  const generateAutoValue = useCallback(
    (autoValueType: string): string => {
      const now = new Date();
      switch (autoValueType) {
        case "current_datetime":
          return now.toISOString().slice(0, 19).replace("T", " ");
        case "current_date":
          return now.toISOString().slice(0, 10);
        case "current_time":
          return now.toTimeString().slice(0, 8);
        case "current_user":
          return userName || "사용자";
        case "uuid":
          return crypto.randomUUID();
        case "sequence":
          return `SEQ_${Date.now()}`;
        default:
          return "";
      }
    },
    [userName],
  );

  // 🆕 Enter 키로 다음 필드 이동
  useEffect(() => {
    const handleEnterKey = (e: KeyboardEvent) => {
      if (e.key === "Enter" && !e.shiftKey) {
        const target = e.target as HTMLElement;

        // 한글 조합 중이면 무시 (한글 입력 문제 방지)
        if ((e as any).isComposing || e.keyCode === 229) {
          return;
        }

        // textarea는 제외 (여러 줄 입력)
        if (target.tagName === "TEXTAREA") {
          return;
        }

        // input, select 등의 폼 요소에서만 작동
        if (target.tagName === "INPUT" || target.tagName === "SELECT" || target.getAttribute("role") === "combobox") {
          e.preventDefault();

          // 모든 포커스 가능한 요소 찾기
          const focusableElements = document.querySelectorAll<HTMLElement>(
            'input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [role="combobox"]:not([disabled])',
          );

          // 화면에 보이는 순서(Y 좌표 → X 좌표)대로 정렬
          const focusableArray = Array.from(focusableElements).sort((a, b) => {
            const rectA = a.getBoundingClientRect();
            const rectB = b.getBoundingClientRect();

            // Y 좌표 차이가 10px 이상이면 Y 좌표로 정렬 (위에서 아래로)
            if (Math.abs(rectA.top - rectB.top) > 10) {
              return rectA.top - rectB.top;
            }

            // 같은 줄이면 X 좌표로 정렬 (왼쪽에서 오른쪽으로)
            return rectA.left - rectB.left;
          });

          const currentIndex = focusableArray.indexOf(target);

          if (currentIndex !== -1 && currentIndex < focusableArray.length - 1) {
            // 다음 요소로 포커스 이동
            const nextElement = focusableArray[currentIndex + 1];
            nextElement.focus();

            // select() 제거: 한글 입력 시 이전 필드의 마지막 글자가 복사되는 버그 방지
          }
        }
      }
    };

    document.addEventListener("keydown", handleEnterKey);

    return () => {
      document.removeEventListener("keydown", handleEnterKey);
    };
  }, []);

  // 🆕 autoFill 자동 입력 초기화
  React.useEffect(() => {
    const initAutoInputFields = async () => {
      for (const comp of allComponents) {
        // type: "component" 또는 type: "widget" 모두 처리
        if (comp.type === "widget" || comp.type === "component") {
          const widget = comp as any;
          const fieldName = widget.columnName || widget.id;

          // autoFill 처리 (테이블 조회 기반 자동 입력)
          if (widget.autoFill?.enabled || (comp as any).autoFill?.enabled) {
            const autoFillConfig = widget.autoFill || (comp as any).autoFill;
            const currentValue = formData[fieldName];

            if (currentValue === undefined || currentValue === "") {
              const { sourceTable, filterColumn, userField, displayColumn } = autoFillConfig;

              // 사용자 정보에서 필터 값 가져오기
              const userValue = user?.[userField];

              if (userValue && sourceTable && filterColumn && displayColumn) {
                try {
                  const { tableTypeApi } = await import("@/lib/api/screen");
                  const result = await tableTypeApi.getTableRecord(sourceTable, filterColumn, userValue, displayColumn);

                  updateFormData(fieldName, result.value);
                } catch (error) {
                  console.error(`autoFill 조회 실패: ${fieldName}`, error);
                }
              }
            }
          }
        }
      }
    };

    initAutoInputFields();
  }, [allComponents, user]);

  // 팝업 화면 레이아웃 로드
  React.useEffect(() => {
    if (popupScreen?.screenId) {
      loadPopupScreen(popupScreen.screenId);
    }
  }, [popupScreen?.screenId]);

  const loadPopupScreen = async (screenId: number) => {
    try {
      setPopupLoading(true);
      const response = await screenApi.getScreenLayout(screenId);

      if (response.success && response.data) {
        const screenData = response.data;
        setPopupLayout(screenData.components || []);
        setPopupScreenResolution({
          width: screenData.screenResolution?.width || 1200,
          height: screenData.screenResolution?.height || 800,
        });
        setPopupScreenInfo({
          id: screenData.id,
          tableName: screenData.tableName,
        });
      } else {
        toast.error("팝업 화면을 불러올 수 없습니다.");
        setPopupScreen(null);
      }
    } catch (error) {
      // console.error("팝업 화면 로드 오류:", error);
      toast.error("팝업 화면 로드 중 오류가 발생했습니다.");
      setPopupScreen(null);
    } finally {
      setPopupLoading(false);
    }
  };

  // 폼 데이터 변경 핸들러
  const handleFormDataChange = (fieldName: string | any, value?: any) => {
    // 일반 필드 변경
    if (onFormDataChange) {
      onFormDataChange(fieldName, value);
    } else {
      setLocalFormData((prev) => ({ ...prev, [fieldName]: value }));
    }
  };

  // 동적 대화형 위젯 렌더링
  const renderInteractiveWidget = (comp: ComponentData) => {
    // 조건부 표시 평가 (기존 conditional 시스템)
    const conditionalResult = evaluateConditional(comp.conditional, formData, allComponents);

    // 조건에 따라 숨김 처리
    if (!conditionalResult.visible) {
      return null;
    }
    
    // 🆕 conditionalConfig 시스템 체크 (V2 레이아웃용)
    const conditionalConfig = (comp as any).componentConfig?.conditionalConfig;
    if (conditionalConfig?.enabled && formData) {
      const { field, operator, value, action } = conditionalConfig;
      const fieldValue = formData[field];
      
      let conditionMet = false;
      switch (operator) {
        case "=":
        case "==":
        case "===":
          conditionMet = fieldValue === value;
          break;
        case "!=":
        case "!==":
          conditionMet = fieldValue !== value;
          break;
        default:
          conditionMet = fieldValue === value;
      }
      
      if (action === "show" && !conditionMet) {
        return null;
      }
      if (action === "hide" && conditionMet) {
        return null;
      }
    }

    // 데이터 테이블 컴포넌트 처리
    if (isDataTableComponent(comp)) {
      return (
        <InteractiveDataTable
          component={comp as DataTableComponent}
          className="h-full w-full"
          style={{
            width: "100%",
            height: "100%",
          }}
          onRefresh={() => {
            // 테이블 자체에서 loadData를 호출하므로 여기서는 빈 함수
            console.log("🔄 InteractiveDataTable 새로고침 트리거됨 (Dynamic)");
          }}
        />
      );
    }

    // 파일 컴포넌트 처리
    if (isFileComponent(comp)) {
      return renderFileComponent(comp as FileComponent);
    }

    // 버튼 컴포넌트 또는 위젯이 아닌 경우 DynamicComponentRenderer 사용
    if (comp.type !== "widget") {
      return (
        <DynamicComponentRenderer
          component={comp}
          isInteractive={true}
          formData={formData}
          originalData={originalData || undefined}
          onFormDataChange={handleFormDataChange}
          screenId={screenInfo?.id}
          tableName={screenInfo?.tableName}
          menuObjid={menuObjid}
          userId={user?.userId}
          userName={user?.userName}
          companyCode={user?.companyCode}
          onSave={onSave}
          allComponents={allComponents}
          selectedRowsData={selectedRowsData}
          onSelectedRowsChange={(selectedRows, selectedData) => {
            console.log("테이블에서 선택된 행 데이터:", selectedData);
            setSelectedRowsData(selectedData);
          }}
          groupedData={groupedData}
          disabledFields={disabledFields}
          flowSelectedData={flowSelectedData}
          flowSelectedStepId={flowSelectedStepId}
          onFlowSelectedDataChange={(selectedData, stepId) => {
            console.log("플로우에서 선택된 데이터:", { selectedData, stepId });
            setFlowSelectedData(selectedData);
            setFlowSelectedStepId(stepId);
          }}
          onRefresh={
            onRefresh ||
            (() => {
              console.log("InteractiveScreenViewerDynamic onRefresh 호출");
            })
          }
          onFlowRefresh={onFlowRefresh}
          onClose={() => {
            // buttonActions.ts가 이미 처리함
          }}
          // 탭 관련 정보 전달
          parentTabId={parentTabId}
          parentTabsComponentId={parentTabsComponentId}
        />
      );
    }

    const widget = comp as WidgetComponent;
    const { widgetType, label, placeholder, required, readonly, columnName } = widget;
    const fieldName = columnName || comp.id;
    const currentValue = formData[fieldName] || "";

    // 스타일 적용
    const applyStyles = (element: React.ReactElement) => {
      if (!comp.style) return element;

      // ✅ 격자 시스템 잔재 제거: style.width, style.height는 무시
      // size.width, size.height가 부모 컨테이너에서 적용되므로
      const { width, height, ...styleWithoutSize } = comp.style;

      return React.cloneElement(element, {
        style: {
          ...element.props.style,
          ...styleWithoutSize, // width/height 제외한 스타일만 적용
          width: "100%",
          height: "100%",
          minHeight: "100%",
          maxHeight: "100%",
          boxSizing: "border-box",
        },
      });
    };

    // 조건부 비활성화 적용
    const isConditionallyDisabled = conditionalResult.disabled;

    // 동적 웹타입 렌더링 사용
    if (widgetType) {
      try {
        const dynamicElement = (
          <DynamicWebTypeRenderer
            webType={widgetType}
            props={{
              component: widget,
              value: currentValue,
              onChange: (value: any) => handleFormDataChange(fieldName, value),
              onFormDataChange: handleFormDataChange,
              formData: formData, // 🆕 전체 formData 전달
              isInteractive: true,
              readonly: readonly || isConditionallyDisabled, // 조건부 비활성화 적용
              disabled: isConditionallyDisabled, // 조건부 비활성화 전달
              required: required,
              placeholder: placeholder,
              className: "w-full h-full",
              isInModal: isInModal, // 🆕 EditModal 내부 여부 전달
              onSave: onSave, // 🆕 EditModal의 handleSave 콜백 전달
              groupedData: groupedData, // 🆕 그룹 데이터 전달 (RepeatScreenModal용)
            }}
            config={widget.webTypeConfig}
            onEvent={(event: string, data: any) => {
              // 이벤트 처리
              // console.log(`Widget event: ${event}`, data);
            }}
          />
        );

        return applyStyles(dynamicElement);
      } catch (error) {
        // console.error(`웹타입 "${widgetType}" 대화형 렌더링 실패:`, error);
        // 오류 발생 시 폴백으로 기본 input 렌더링
        const fallbackElement = (
          <Input
            type="text"
            value={currentValue}
            onChange={(e) => handleFormDataChange(fieldName, e.target.value)}
            placeholder={`${widgetType} (렌더링 오류)`}
            disabled={readonly || isConditionallyDisabled}
            required={required}
            className="h-full w-full"
          />
        );
        return applyStyles(fallbackElement);
      }
    }

    // 웹타입이 없는 경우 기본 input 렌더링 (하위 호환성)
    const defaultElement = (
      <Input
        type="text"
        value={currentValue}
        onChange={(e) => handleFormDataChange(fieldName, e.target.value)}
        placeholder={placeholder || "입력하세요"}
        disabled={readonly || isConditionallyDisabled}
        required={required}
        className="h-full w-full"
      />
    );
    return applyStyles(defaultElement);
  };

  // 버튼 렌더링
  const renderButton = (comp: ComponentData) => {
    const config = (comp as any).webTypeConfig as ButtonTypeConfig | undefined;
    const { label } = comp;

    // 버튼 액션 핸들러들
    const handleSaveAction = async () => {
      // EditModal에서 전달된 onSave가 있으면 우선 사용 (수정 모달)
      if (onSave) {
        try {
          await onSave();
        } catch (error) {
          console.error("저장 오류:", error);
          toast.error("저장 중 오류가 발생했습니다.");
        }
        return;
      }

      // 일반 저장 액션 (신규 생성)
      if (!screenInfo?.tableName) {
        toast.error("테이블명이 설정되지 않았습니다.");
        return;
      }

      try {
        // 🆕 리피터 데이터(배열)를 마스터 저장에서 제외 (V2Repeater가 별도로 저장)
        // 단, v2-media 컴포넌트의 파일 배열(objid 배열)은 포함
        const masterFormData: Record<string, any> = {};
        
        // v2-media 컴포넌트의 columnName 목록 수집
        const mediaColumnNames = new Set(
          allComponents
            .filter((c: any) => c.componentType === "v2-media" || c.url?.includes("v2-media"))
            .map((c: any) => c.columnName || c.componentConfig?.columnName)
            .filter(Boolean)
        );
        
        Object.entries(formData).forEach(([key, value]) => {
          if (!Array.isArray(value)) {
            // 배열이 아닌 값은 그대로 저장
            masterFormData[key] = value;
          } else if (mediaColumnNames.has(key)) {
            // v2-media 컴포넌트의 배열은 첫 번째 값만 저장 (단일 파일 컬럼 대응)
            // 또는 JSON 문자열로 변환하려면 JSON.stringify(value) 사용
            masterFormData[key] = value.length > 0 ? value[0] : null;
            console.log(`📷 미디어 데이터 저장: ${key}, objid: ${masterFormData[key]}`);
          } else {
            console.log(`🔄 리피터 데이터 제외 (별도 저장): ${key}, ${value.length}개 항목`);
          }
        });
        
        const saveData: DynamicFormData = {
          tableName: screenInfo.tableName,
          data: masterFormData,
        };

        // console.log("💾 저장 액션 실행:", saveData);
        const response = await dynamicFormApi.saveData(saveData);

        if (response.success) {
          const masterRecordId = response.data?.id || formData.id;
          
          // 리피터 데이터 저장 이벤트 발생 (V2Repeater 컴포넌트가 리스닝)
          window.dispatchEvent(
            new CustomEvent("repeaterSave", {
              detail: { 
                parentId: masterRecordId,
                masterRecordId, // 🆕 마스터 레코드 ID (FK 자동 연결용)
                mainFormData: formData,
                tableName: screenInfo.tableName,
              },
            }),
          );

          toast.success("데이터가 성공적으로 저장되었습니다.");
        } else {
          toast.error(response.message || "저장에 실패했습니다.");
        }
      } catch (error) {
        // console.error("저장 오류:", error);
        toast.error("저장 중 오류가 발생했습니다.");
      }
    };

    const handleDeleteAction = async () => {
      if (!config?.confirmationEnabled || window.confirm(config.confirmationMessage || "정말 삭제하시겠습니까?")) {
        // console.log("🗑️ 삭제 액션 실행");
        toast.success("삭제가 완료되었습니다.");
      }
    };

    const handlePopupAction = () => {
      if (config?.popupScreenId) {
        setPopupScreen({
          screenId: config.popupScreenId,
          title: config.popupTitle || "팝업 화면",
          size: config.popupSize || "medium",
        });
      }
    };

    const handleNavigateAction = () => {
      const navigateType = config?.navigateType || "url";

      if (navigateType === "screen" && config?.navigateScreenId) {
        const screenPath = `/screens/${config.navigateScreenId}`;

        if (config.navigateTarget === "_blank") {
          window.open(screenPath, "_blank");
        } else {
          window.location.href = screenPath;
        }
      } else if (navigateType === "url" && config?.navigateUrl) {
        if (config.navigateTarget === "_blank") {
          window.open(config.navigateUrl, "_blank");
        } else {
          window.location.href = config.navigateUrl;
        }
      }
    };

    const handleCustomAction = async () => {
      if (config?.customAction) {
        try {
          const result = eval(config.customAction);
          if (result instanceof Promise) {
            await result;
          }
          // console.log("⚡ 커스텀 액션 실행 완료");
        } catch (error) {
          throw new Error(`커스텀 액션 실행 실패: ${error.message}`);
        }
      }
    };

    // 🆕 즉시 저장(quickInsert) 액션 핸들러
    const handleQuickInsertAction = async () => {
      // componentConfig에서 quickInsertConfig 가져오기
      const quickInsertConfig = (comp as any).componentConfig?.action?.quickInsertConfig;

      if (!quickInsertConfig?.targetTable) {
        toast.error("대상 테이블이 설정되지 않았습니다.");
        return;
      }

      // 1. 대상 테이블의 컬럼 목록 조회 (자동 매핑용)
      let targetTableColumns: string[] = [];
      try {
        const { default: apiClient } = await import("@/lib/api/client");
        const columnsResponse = await apiClient.get(
          `/table-management/tables/${quickInsertConfig.targetTable}/columns`,
        );
        if (columnsResponse.data?.success && columnsResponse.data?.data) {
          const columnsData = columnsResponse.data.data.columns || columnsResponse.data.data;
          targetTableColumns = columnsData.map((col: any) => col.columnName || col.column_name || col.name);
          console.log("📍 대상 테이블 컬럼 목록:", targetTableColumns);
        }
      } catch (error) {
        console.error("대상 테이블 컬럼 조회 실패:", error);
      }

      // 2. 컬럼 매핑에서 값 수집
      const insertData: Record<string, any> = {};
      const columnMappings = quickInsertConfig.columnMappings || [];

      for (const mapping of columnMappings) {
        let value: any;

        switch (mapping.sourceType) {
          case "component":
            // 같은 화면의 컴포넌트에서 값 가져오기
            // 방법1: sourceColumnName 사용
            if (mapping.sourceColumnName && formData[mapping.sourceColumnName] !== undefined) {
              value = formData[mapping.sourceColumnName];
              console.log(`📍 컴포넌트 값 (sourceColumnName): ${mapping.sourceColumnName} = ${value}`);
            }
            // 방법2: sourceComponentId로 컴포넌트 찾아서 columnName 사용
            else if (mapping.sourceComponentId) {
              const sourceComp = allComponents.find((c: any) => c.id === mapping.sourceComponentId);
              if (sourceComp) {
                const fieldName = (sourceComp as any).columnName || sourceComp.id;
                value = formData[fieldName];
                console.log(`📍 컴포넌트 값 (컴포넌트 조회): ${fieldName} = ${value}`);
              }
            }
            break;

          case "leftPanel":
            // 분할 패널 좌측 선택 데이터에서 값 가져오기
            if (mapping.sourceColumn && splitPanelContext?.selectedLeftData) {
              value = splitPanelContext.selectedLeftData[mapping.sourceColumn];
            }
            break;

          case "fixed":
            value = mapping.fixedValue;
            break;

          case "currentUser":
            if (mapping.userField) {
              switch (mapping.userField) {
                case "userId":
                  value = user?.userId;
                  break;
                case "userName":
                  value = userName;
                  break;
                case "companyCode":
                  value = user?.companyCode;
                  break;
                case "deptCode":
                  value = authUser?.deptCode;
                  break;
              }
            }
            break;
        }

        if (value !== undefined && value !== null && value !== "") {
          insertData[mapping.targetColumn] = value;
        }
      }

      // 3. 좌측 패널 선택 데이터에서 자동 매핑 (컬럼명이 같고 대상 테이블에 있는 경우)
      if (splitPanelContext?.selectedLeftData && targetTableColumns.length > 0) {
        const leftData = splitPanelContext.selectedLeftData;
        console.log("📍 좌측 패널 자동 매핑 시작:", leftData);

        for (const [key, val] of Object.entries(leftData)) {
          // 이미 매핑된 컬럼은 스킵
          if (insertData[key] !== undefined) {
            continue;
          }

          // 대상 테이블에 해당 컬럼이 없으면 스킵
          if (!targetTableColumns.includes(key)) {
            continue;
          }

          // 시스템 컬럼 제외
          const systemColumns = ["id", "created_date", "updated_date", "writer", "writer_name"];
          if (systemColumns.includes(key)) {
            continue;
          }

          // _label, _name 으로 끝나는 표시용 컬럼 제외
          if (key.endsWith("_label") || key.endsWith("_name")) {
            continue;
          }

          // 값이 있으면 자동 추가
          if (val !== undefined && val !== null && val !== "") {
            insertData[key] = val;
            console.log(`📍 자동 매핑 추가: ${key} = ${val}`);
          }
        }
      }

      console.log("🚀 quickInsert 최종 데이터:", insertData);

      // 4. 필수값 검증
      if (Object.keys(insertData).length === 0) {
        toast.error("저장할 데이터가 없습니다. 값을 선택해주세요.");
        return;
      }

      // 5. 중복 체크 (설정된 경우)
      if (quickInsertConfig.duplicateCheck?.enabled && quickInsertConfig.duplicateCheck?.columns?.length > 0) {
        try {
          const { default: apiClient } = await import("@/lib/api/client");

          // 중복 체크를 위한 검색 조건 구성
          const searchConditions: Record<string, any> = {};
          for (const col of quickInsertConfig.duplicateCheck.columns) {
            if (insertData[col] !== undefined) {
              searchConditions[col] = { value: insertData[col], operator: "equals" };
            }
          }

          console.log("📍 중복 체크 조건:", searchConditions);

          // 기존 데이터 조회
          const checkResponse = await apiClient.post(`/table-management/tables/${quickInsertConfig.targetTable}/data`, {
            page: 1,
            pageSize: 1,
            search: searchConditions,
          });

          console.log("📍 중복 체크 응답:", checkResponse.data);

          // data 배열이 있고 길이가 0보다 크면 중복
          const existingData = checkResponse.data?.data?.data || checkResponse.data?.data || [];
          if (Array.isArray(existingData) && existingData.length > 0) {
            toast.error(quickInsertConfig.duplicateCheck.errorMessage || "이미 존재하는 데이터입니다.");
            return;
          }
        } catch (error) {
          console.error("중복 체크 오류:", error);
          // 중복 체크 실패 시 계속 진행
        }
      }

      // 6. API 호출
      try {
        const { default: apiClient } = await import("@/lib/api/client");

        const response = await apiClient.post(
          `/table-management/tables/${quickInsertConfig.targetTable}/add`,
          insertData,
        );

        if (response.data?.success) {
          // 7. 성공 후 동작
          if (quickInsertConfig.afterInsert?.showSuccessMessage !== false) {
            toast.success(quickInsertConfig.afterInsert?.successMessage || "저장되었습니다.");
          }

          // 데이터 새로고침 (테이블리스트, 카드 디스플레이)
          if (quickInsertConfig.afterInsert?.refreshData !== false) {
            console.log("📍 데이터 새로고침 이벤트 발송");
            if (typeof window !== "undefined") {
              window.dispatchEvent(new CustomEvent("refreshTable"));
              window.dispatchEvent(new CustomEvent("refreshCardDisplay"));
            }
          }

          // 지정된 컴포넌트 초기화
          if (quickInsertConfig.afterInsert?.clearComponents?.length > 0) {
            for (const componentId of quickInsertConfig.afterInsert.clearComponents) {
              const targetComp = allComponents.find((c: any) => c.id === componentId);
              if (targetComp) {
                const fieldName = (targetComp as any).columnName || targetComp.id;
                onFormDataChange?.(fieldName, "");
              }
            }
          }
        } else {
          toast.error(response.data?.message || "저장에 실패했습니다.");
        }
      } catch (error: any) {
        console.error("quickInsert 오류:", error);
        toast.error(error.response?.data?.message || error.message || "저장 중 오류가 발생했습니다.");
      }
    };

    const handleClick = async () => {
      try {
        const actionType = config?.actionType || "save";

        switch (actionType) {
          case "save":
            await handleSaveAction();
            break;
          case "delete":
            await handleDeleteAction();
            break;
          case "popup":
            handlePopupAction();
            break;
          case "navigate":
            handleNavigateAction();
            break;
          case "custom":
            await handleCustomAction();
            break;
          case "quickInsert":
            await handleQuickInsertAction();
            break;
          default:
          // console.log("🔘 기본 버튼 클릭");
        }
      } catch (error) {
        // console.error("버튼 액션 오류:", error);
        toast.error(error.message || "액션 실행 중 오류가 발생했습니다.");
      }
    };

    // 커스텀 색상이 있으면 Tailwind 클래스 대신 직접 스타일 적용
    const hasCustomColors = config?.backgroundColor || config?.textColor || comp.style?.backgroundColor || comp.style?.color;
    
    return (
      <button
        onClick={handleClick}
        disabled={config?.disabled}
        className={`w-full rounded-md px-3 py-2 text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ${
          hasCustomColors 
            ? '' 
            : 'bg-background border border-foreground text-foreground shadow-xs hover:bg-muted/50'
        }`}
        style={{
          // 컴포넌트 스타일 적용
          ...comp.style,
          // 설정값이 있으면 우선 적용
          backgroundColor: config?.backgroundColor || comp.style?.backgroundColor,
          color: config?.textColor || comp.style?.color,
          // 부모 컨테이너 크기에 맞춤
          width: "100%",
          height: "100%",
        }}
      >
        {label || "버튼"}
      </button>
    );
  };

  // 파일 컴포넌트 렌더링
  const renderFileComponent = (comp: FileComponent) => {
    const { label, readonly } = comp;
    const fieldName = comp.columnName || comp.id;

    // 화면 ID 추출 (URL에서)
    const screenId =
      screenInfo?.screenId ||
      (typeof window !== "undefined" && window.location.pathname.includes("/screens/")
        ? parseInt(window.location.pathname.split("/screens/")[1])
        : null);

    return (
      <div className="h-full w-full">
        {/* 실제 FileUploadComponent 사용 */}
        <FileUploadComponent
          component={comp}
          componentConfig={{
            ...comp.fileConfig,
            multiple: comp.fileConfig?.multiple !== false,
            accept: comp.fileConfig?.accept || "*/*",
            maxSize: (comp.fileConfig?.maxSize || 10) * 1024 * 1024, // MB to bytes
            disabled: readonly,
          }}
          componentStyle={{
            width: "100%",
            height: "100%",
          }}
          className="h-full w-full"
          isInteractive={true}
          isDesignMode={false}
          formData={{
            screenId, // 🎯 화면 ID 전달
            // 🎯 백엔드 API가 기대하는 정확한 형식으로 설정
            autoLink: true, // 자동 연결 활성화
            linkedTable: "screen_files", // 연결 테이블
            recordId: screenId, // 레코드 ID
            columnName: fieldName, // 컬럼명 (중요!)
            isVirtualFileColumn: true, // 가상 파일 컬럼
            id: formData.id,
            ...formData,
          }}
          onFormDataChange={(data) => {
            // console.log("📝 실제 화면 파일 업로드 완료:", data);
            if (onFormDataChange) {
              Object.entries(data).forEach(([key, value]) => {
                onFormDataChange(key, value);
              });
            }
          }}
          onUpdate={(updates) => {
            console.log("🔄🔄🔄 실제 화면 파일 컴포넌트 업데이트:", {
              componentId: comp.id,
              hasUploadedFiles: !!updates.uploadedFiles,
              filesCount: updates.uploadedFiles?.length || 0,
              hasLastFileUpdate: !!updates.lastFileUpdate,
              updates,
            });

            // 파일 업로드/삭제 완료 시 formData 업데이터
            if (updates.uploadedFiles && onFormDataChange) {
              onFormDataChange(fieldName, updates.uploadedFiles);
            }

            // 🎯 화면설계 모드와 동기화를 위한 전역 이벤트 발생 (업로드/삭제 모두)
            if (updates.uploadedFiles !== undefined && typeof window !== "undefined") {
              // 업로드인지 삭제인지 판단 (lastFileUpdate가 있으면 변경사항 있음)
              const action = updates.lastFileUpdate ? "update" : "sync";

              const eventDetail = {
                componentId: comp.id,
                files: updates.uploadedFiles,
                fileCount: updates.uploadedFiles.length,
                action: action,
                timestamp: updates.lastFileUpdate || Date.now(),
                source: "realScreen", // 실제 화면에서 온 이벤트임을 표시
              };

              // console.log("🚀🚀🚀 실제 화면 파일 변경 이벤트 발생:", eventDetail);

              const event = new CustomEvent("globalFileStateChanged", {
                detail: eventDetail,
              });
              window.dispatchEvent(event);

              // console.log("✅✅✅ 실제 화면 → 화면설계 모드 동기화 이벤트 발생 완료");

              // 추가 지연 이벤트들 (화면설계 모드가 열려있을 때를 대비)
              setTimeout(() => {
                // console.log("🔄 실제 화면 추가 이벤트 발생 (지연 100ms)");
                window.dispatchEvent(
                  new CustomEvent("globalFileStateChanged", {
                    detail: { ...eventDetail, delayed: true },
                  }),
                );
              }, 100);

              setTimeout(() => {
                // console.log("🔄 실제 화면 추가 이벤트 발생 (지연 500ms)");
                window.dispatchEvent(
                  new CustomEvent("globalFileStateChanged", {
                    detail: { ...eventDetail, delayed: true, attempt: 2 },
                  }),
                );
              }, 500);
            }
          }}
        />
      </div>
    );
  };

  // 메인 렌더링
  const { type, position, size, style = {} } = component;

  // ✅ 격자 시스템 잔재 제거: style.width, style.height 무시
  const { width: styleWidth, height: styleHeight, ...styleWithoutSize } = style;

  // TableSearchWidget의 경우 높이를 자동으로 설정
  const isTableSearchWidget = (component as any).componentId === "table-search-widget";

  // 🆕 라벨 표시 여부 확인 (V2 입력 컴포넌트)
  // labelDisplay가 false가 아니고, labelText 또는 label이 있으면 라벨 표시
  const isV2InputComponent = type === "v2-input" || type === "v2-select" || type === "v2-date";
  const hasVisibleLabel = isV2InputComponent && 
    style?.labelDisplay !== false && 
    (style?.labelText || (component as any).label);
  
  // 라벨이 있는 경우 상단 여백 계산 (라벨 폰트크기 + 여백)
  const labelFontSize = style?.labelFontSize ? parseInt(String(style.labelFontSize)) : 14;
  const labelMarginBottom = style?.labelMarginBottom ? parseInt(String(style.labelMarginBottom)) : 4;
  const labelOffset = hasVisibleLabel ? (labelFontSize + labelMarginBottom + 2) : 0;

  const componentStyle = {
    position: "absolute" as const,
    left: position?.x || 0,
    top: position?.y || 0, // 원래 위치 유지 (음수로 가면 overflow-hidden에 잘림)
    zIndex: position?.z || 1,
    ...styleWithoutSize, // width/height 제외한 스타일만 먼저 적용
    width: size?.width || 200, // size의 픽셀 값이 최종 우선순위
    height: isTableSearchWidget ? "auto" : size?.height || 10,
    minHeight: isTableSearchWidget ? "48px" : undefined,
    // 🆕 라벨이 있으면 overflow visible로 설정하여 라벨이 잘리지 않게 함
    overflow: labelOffset > 0 ? "visible" : undefined,
  };

  return (
    <>
      <div className="absolute" style={componentStyle}>
        {/* 위젯 렌더링 (라벨은 V2Input 내부에서 absolute로 표시됨) */}
        {renderInteractiveWidget(component)}
      </div>

      {/* 팝업 화면 렌더링 */}
      {popupScreen && (
        <Dialog open={!!popupScreen} onOpenChange={() => setPopupScreen(null)}>
          <DialogContent
            className="max-w-none overflow-hidden p-0"
            style={{
              width: popupScreen.size === "small" ? "600px" : popupScreen.size === "large" ? "1400px" : "1000px",
              height: "800px",
              maxWidth: "95vw",
              maxHeight: "90vh",
            }}
          >
            <DialogHeader>
              <DialogTitle>{popupScreen.title}</DialogTitle>
            </DialogHeader>

            {popupLoading ? (
              <div className="flex items-center justify-center p-8">
                <div className="text-gray-500">로딩 중...</div>
              </div>
            ) : (
              <div
                className="relative overflow-auto"
                style={{
                  width: popupScreenResolution?.width || 1200,
                  height: popupScreenResolution?.height || 600,
                  maxWidth: "100%",
                  maxHeight: "70vh",
                }}
              >
                {popupLayout.map((popupComponent) => (
                  <InteractiveScreenViewerDynamic
                    key={popupComponent.id}
                    component={popupComponent}
                    allComponents={popupLayout}
                    formData={popupFormData}
                    onFormDataChange={(fieldName, value) => {
                      setPopupFormData((prev) => ({ ...prev, [fieldName]: value }));
                    }}
                    screenInfo={popupScreenInfo}
                  />
                ))}
              </div>
            )}
          </DialogContent>
        </Dialog>
      )}
    </>
  );
};

// 기존 InteractiveScreenViewer와의 호환성을 위한 export
export { InteractiveScreenViewerDynamic as InteractiveScreenViewer };

InteractiveScreenViewerDynamic.displayName = "InteractiveScreenViewerDynamic";
