"use client";

import React, { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Plus, Columns } from "lucide-react";
import { ItemSelectionModal } from "./ItemSelectionModal";
import { RepeaterTable } from "./RepeaterTable";
import { ModalRepeaterTableProps, RepeaterColumnConfig, JoinCondition, DynamicDataSourceOption } from "./types";
import { useCalculation } from "./useCalculation";
import { cn } from "@/lib/utils";
import { apiClient } from "@/lib/api/client";
import { ComponentRendererProps } from "@/types/component";

// ✅ ComponentRendererProps 상속으로 필수 props 자동 확보
export interface ModalRepeaterTableComponentProps extends ComponentRendererProps {
  config?: ModalRepeaterTableProps;
  // ModalRepeaterTableProps의 개별 prop들도 지원 (호환성)
  sourceTable?: string;
  sourceColumns?: string[];
  sourceSearchFields?: string[];
  targetTable?: string;
  modalTitle?: string;
  modalButtonText?: string;
  multiSelect?: boolean;
  columns?: RepeaterColumnConfig[];
  calculationRules?: any[];
  value?: any[];
  onChange?: (newData: any[]) => void;
  uniqueField?: string;
  filterCondition?: Record<string, any>;
  companyCode?: string;
}

/**
 * 외부 테이블에서 참조 값을 조회하는 함수
 * @param referenceTable 참조 테이블명 (예: "customer_item_mapping")
 * @param referenceField 참조할 컬럼명 (예: "basic_price")
 * @param joinConditions 조인 조건 배열
 * @param sourceItem 소스 데이터 (모달에서 선택한 항목)
 * @param currentItem 현재 빌드 중인 항목 (이미 설정된 필드들)
 * @returns 참조된 값 또는 undefined
 */
async function fetchReferenceValue(
  referenceTable: string,
  referenceField: string,
  joinConditions: JoinCondition[],
  sourceItem: any,
  currentItem: any
): Promise<any> {
  if (joinConditions.length === 0) {
    console.warn("⚠️ 조인 조건이 없습니다. 참조 조회를 건너뜁니다.");
    return undefined;
  }

  try {
    // 조인 조건을 WHERE 절로 변환
    const whereConditions: Record<string, any> = {};
    
    for (const condition of joinConditions) {
      const { sourceTable = "target", sourceField, targetField, operator = "=" } = condition;
      
      // 소스 테이블에 따라 값을 가져오기
      let value: any;
      if (sourceTable === "source") {
        // 소스 테이블 (item_info 등): 모달에서 선택한 원본 데이터
        value = sourceItem[sourceField];
        console.log(`  📘 소스 테이블에서 값 가져오기: ${sourceField} =`, value);
      } else {
        // 저장 테이블 (sales_order_mng 등): 반복 테이블에 이미 복사된 값
        value = currentItem[sourceField];
        console.log(`  📗 저장 테이블(반복테이블)에서 값 가져오기: ${sourceField} =`, value);
      }
      
      if (value === undefined || value === null) {
        console.warn(`⚠️ 조인 조건의 소스 필드 "${sourceField}" 값이 없습니다. (sourceTable: ${sourceTable})`);
        return undefined;
      }
      
      // 연산자가 "=" 인 경우만 지원 (확장 가능)
      if (operator === "=") {
        // 숫자형 ID인 경우 숫자로 변환 (문자열 '189' → 숫자 189)
        // 백엔드에서 entity 타입 컬럼 검색 시 문자열이면 ILIKE 검색을 수행하므로
        // 정확한 ID 매칭을 위해 숫자로 변환해야 함
        let convertedValue = value;
        if (targetField.endsWith('_id') || targetField === 'id') {
          const numValue = Number(value);
          if (!isNaN(numValue)) {
            convertedValue = numValue;
            console.log(`  🔢 ID 타입 변환: ${targetField} = "${value}" → ${numValue}`);
          }
        }
        whereConditions[targetField] = convertedValue;
      } else {
        console.warn(`⚠️ 연산자 "${operator}"는 아직 지원되지 않습니다.`);
      }
    }

    console.log(`🔍 참조 조회 API 호출:`, {
      table: referenceTable,
      field: referenceField,
      where: whereConditions,
    });

    // API 호출: 테이블 데이터 조회 (POST 방식)
    const requestBody = {
      search: whereConditions,  // ✅ filters → search 변경 (백엔드 파라미터명)
      size: 1, // 첫 번째 결과만 가져오기
      page: 1,
    };
    
    console.log("📤 API 요청 Body:", JSON.stringify(requestBody, null, 2));
    
    const response = await apiClient.post(
      `/table-management/tables/${referenceTable}/data`,
      requestBody
    );

    console.log("📥 API 전체 응답:", {
      success: response.data.success,
      dataLength: response.data.data?.data?.length,  // ✅ data.data.data 구조
      total: response.data.data?.total,              // ✅ data.data.total
      firstRow: response.data.data?.data?.[0],       // ✅ data.data.data[0]
    });

    if (response.data.success && response.data.data?.data?.length > 0) {
      const firstRow = response.data.data.data[0];  // ✅ data.data.data[0]
      const value = firstRow[referenceField];
      
      console.log(`✅ 참조 조회 성공:`, {
        table: referenceTable,
        field: referenceField,
        value,
        fullRow: firstRow,
      });
      
      return value;
    } else {
      console.warn(`⚠️ 참조 조회 결과 없음:`, {
        table: referenceTable,
        where: whereConditions,
        responseData: response.data.data,
        total: response.data.total,
      });
      return undefined;
    }
  } catch (error) {
    console.error(`❌ 참조 조회 API 오류:`, error);
    return undefined;
  }
}

export function ModalRepeaterTableComponent({
  // ComponentRendererProps (자동 전달)
  component,
  isDesignMode = false,
  isSelected = false,
  isInteractive = false,
  onClick,
  onDragStart,
  onDragEnd,
  className,
  style,
  formData,
  onFormDataChange,
  
  // ModalRepeaterTable 전용 props
  config,
  sourceTable: propSourceTable,
  sourceColumns: propSourceColumns,
  sourceSearchFields: propSourceSearchFields,
  targetTable: propTargetTable,
  modalTitle: propModalTitle,
  modalButtonText: propModalButtonText,
  multiSelect: propMultiSelect,
  columns: propColumns,
  calculationRules: propCalculationRules,
  value: propValue,
  onChange: propOnChange,
  uniqueField: propUniqueField,
  filterCondition: propFilterCondition,
  companyCode: propCompanyCode,
  
  ...props
}: ModalRepeaterTableComponentProps) {
  // ✅ config 또는 component.config 또는 개별 prop 우선순위로 병합
  const componentConfig = {
    ...config,
    ...component?.config,
  };

  // config prop 우선, 없으면 개별 prop 사용
  const sourceTable = componentConfig?.sourceTable || propSourceTable || "";
  const targetTable = componentConfig?.targetTable || propTargetTable;
  
  // sourceColumns에서 빈 문자열 필터링
  const rawSourceColumns = componentConfig?.sourceColumns || propSourceColumns || [];
  const sourceColumns = rawSourceColumns.filter((col: string) => col && col.trim() !== "");
  
  // 모달 컬럼 라벨 (컬럼명 -> 표시 라벨)
  const sourceColumnLabels = componentConfig?.sourceColumnLabels || {};
  
  const sourceSearchFields = componentConfig?.sourceSearchFields || propSourceSearchFields || [];
  const modalTitle = componentConfig?.modalTitle || propModalTitle || "항목 검색";
  const modalButtonText = componentConfig?.modalButtonText || propModalButtonText || "품목 검색";
  const multiSelect = componentConfig?.multiSelect ?? propMultiSelect ?? true;
  const calculationRules = componentConfig?.calculationRules || propCalculationRules || [];
  
  // ✅ value는 formData[columnName] 우선, 없으면 prop 사용
  const columnName = component?.columnName;
  const externalValue = (columnName && formData?.[columnName]) || componentConfig?.value || propValue || [];
  
  // 빈 객체 판단 함수 (수정 모달의 실제 데이터는 유지)
  const isEmptyRow = (item: any): boolean => {
    if (!item || typeof item !== 'object') return true;
    
    // id가 있으면 실제 데이터 (수정 모달)
    if (item.id) return false;
    
    // 모든 값이 비어있는지 확인 (계산 필드 제외)
    const hasValue = Object.entries(item).some(([key, value]) => {
      // 계산 필드나 메타데이터는 제외
      if (key.startsWith('_') || key === 'total_amount') return false;
      
      // 실제 값이 있는지 확인
      return value !== undefined && 
             value !== null && 
             value !== '' &&
             value !== 0 &&
             value !== '0' &&
             value !== '0.00';
    });
    
    return !hasValue;
  };
  
  // 🆕 내부 상태로 데이터 관리 (즉시 UI 반영을 위해)
  const [localValue, setLocalValue] = useState<any[]>(() => {
    return externalValue.filter((item) => !isEmptyRow(item));
  });
  
  // 🆕 외부 값(formData, propValue) 변경 시 내부 상태 동기화
  useEffect(() => {
    // 빈 객체 필터링
    const filteredValue = externalValue.filter((item) => !isEmptyRow(item));
    
    // 외부 값이 변경되었고, 내부 값과 다른 경우에만 동기화
    if (JSON.stringify(filteredValue) !== JSON.stringify(localValue)) {
      setLocalValue(filteredValue);
    }
  }, [externalValue]);
  
  // ✅ onChange 래퍼 (기존 onChange 콜백 + onFormDataChange 호출 + 납기일 일괄 적용)
  const handleChange = (newData: any[]) => {
    // 🆕 납기일 일괄 적용 로직 (납기일 필드가 있는 경우만)
    let processedData = newData;
    
    // 납기일 필드 찾기 (item_due_date, delivery_date, due_date 등)
    const dateField = columns.find(
      (col) => 
        col.field === "item_due_date" || 
        col.field === "delivery_date" || 
        col.field === "due_date"
    );
    
    if (dateField && !isDeliveryDateApplied && newData.length > 0) {
      // 현재 상태: 납기일이 있는 행과 없는 행 개수 체크
      const itemsWithDate = newData.filter((item) => item[dateField.field]);
      const itemsWithoutDate = newData.filter((item) => !item[dateField.field]);
      
      // 정확히 1개만 날짜가 있고, 나머지는 모두 비어있을 때 일괄 적용
      if (itemsWithDate.length === 1 && itemsWithoutDate.length > 0) {
        const selectedDate = itemsWithDate[0][dateField.field];
        processedData = newData.map((item) => ({
          ...item,
          [dateField.field]: selectedDate, // 모든 행에 동일한 납기일 적용
        }));
        
        setIsDeliveryDateApplied(true); // 플래그 활성화
      }
    }
    
    // 🆕 수주일 일괄 적용 로직 (order_date 필드가 있는 경우만)
    const orderDateField = columns.find(
      (col) => 
        col.field === "order_date" || 
        col.field === "ordered_date"
    );
    
    if (orderDateField && !isOrderDateApplied && newData.length > 0) {
      // ⚠️ 중요: 원본 newData를 참조해야 납기일의 영향을 받지 않음
      const itemsWithOrderDate = newData.filter((item) => item[orderDateField.field]);
      const itemsWithoutOrderDate = newData.filter((item) => !item[orderDateField.field]);
      
      // ✅ 조건: 모든 행이 비어있는 초기 상태 → 어느 행에서든 첫 선택 시 전체 적용
      if (itemsWithOrderDate.length === 1 && itemsWithoutOrderDate.length === newData.length - 1) {
        const selectedOrderDate = itemsWithOrderDate[0][orderDateField.field];
        processedData = processedData.map((item) => ({
          ...item,
          [orderDateField.field]: selectedOrderDate,
        }));
        
        setIsOrderDateApplied(true); // 플래그 활성화
      }
    }
    
    // 🆕 내부 상태 즉시 업데이트 (UI 즉시 반영) - 일괄 적용된 데이터로 업데이트
    setLocalValue(processedData);
    
    // 기존 onChange 콜백 호출 (호환성)
    const externalOnChange = componentConfig?.onChange || propOnChange;
    if (externalOnChange) {
      externalOnChange(processedData);
    }
    
    // 🆕 onFormDataChange 호출하여 EditModal의 groupData 업데이트
    if (onFormDataChange && columnName) {
      onFormDataChange(columnName, processedData);
    }
  };
  
  // uniqueField 자동 보정: order_no는 item_info 테이블에 없으므로 item_number로 변경
  const rawUniqueField = componentConfig?.uniqueField || propUniqueField;
  const uniqueField = rawUniqueField === "order_no" && sourceTable === "item_info" 
    ? "item_number" 
    : rawUniqueField;
  
  const filterCondition = componentConfig?.filterCondition || propFilterCondition || {};
  const companyCode = componentConfig?.companyCode || propCompanyCode;
  const [modalOpen, setModalOpen] = useState(false);

  // 체크박스 선택 상태
  const [selectedRows, setSelectedRows] = useState<Set<number>>(new Set());

  // 균등 분배 트리거 (값이 변경되면 RepeaterTable에서 균등 분배 실행)
  const [equalizeWidthsTrigger, setEqualizeWidthsTrigger] = useState(0);

  // 🆕 납기일 일괄 적용 플래그 (딱 한 번만 실행)
  const [isDeliveryDateApplied, setIsDeliveryDateApplied] = useState(false);
  
  // 🆕 수주일 일괄 적용 플래그 (딱 한 번만 실행)
  const [isOrderDateApplied, setIsOrderDateApplied] = useState(false);
  
  // 🆕 동적 데이터 소스 활성화 상태 (컬럼별로 현재 선택된 옵션 ID)
  const [activeDataSources, setActiveDataSources] = useState<Record<string, string>>({});

  // columns가 비어있으면 sourceColumns로부터 자동 생성
  const columns = React.useMemo((): RepeaterColumnConfig[] => {
    const configuredColumns = componentConfig?.columns || propColumns || [];
    
    if (configuredColumns.length > 0) {
      return configuredColumns;
    }

    // columns가 비어있으면 sourceColumns로부터 자동 생성
    if (sourceColumns.length > 0) {
      const autoColumns: RepeaterColumnConfig[] = sourceColumns.map((field) => ({
        field: field,
        label: field, // 필드명을 라벨로 사용 (나중에 설정에서 변경 가능)
        editable: false, // 기본적으로 읽기 전용
        type: "text" as const,
        width: "150px",
      }));
      return autoColumns;
    }

    console.warn("⚠️ [ModalRepeaterTable] columns와 sourceColumns 모두 비어있음!");
    return [];
  }, [componentConfig?.columns, propColumns, sourceColumns]);

  // 초기 props 검증
  useEffect(() => {
    if (rawSourceColumns.length !== sourceColumns.length) {
      console.warn(`⚠️ [ModalRepeaterTable] sourceColumns 필터링: ${rawSourceColumns.length}개 → ${sourceColumns.length}개`);
    }
    
    if (rawUniqueField !== uniqueField) {
      console.warn(`⚠️ [ModalRepeaterTable] uniqueField 자동 보정: "${rawUniqueField}" → "${uniqueField}"`);
    }
    
    if (columns.length === 0) {
      console.error("❌ [ModalRepeaterTable] columns가 비어있습니다!", { sourceColumns });
    }
  }, []);

  // 🆕 저장 요청 시에만 데이터 전달 (beforeFormSave 이벤트 리스너)
  useEffect(() => {
    const handleSaveRequest = async (event: Event) => {
      const componentKey = columnName || component?.id || "modal_repeater_data";
      
      if (localValue.length === 0) {
        console.warn("⚠️ [ModalRepeaterTable] 저장할 데이터 없음");
        return;
      }
      
      // sourceColumns에 포함된 컬럼 제외 (조인된 컬럼 제거)
      // 단, columnMappings에 정의된 컬럼은 저장해야 하므로 제외하지 않음
      const mappedFields = columns
        .filter(col => col.mapping?.type === "source" && col.mapping?.sourceField)
        .map(col => col.field);
      
      const filteredData = localValue.map((item: any) => {
        const filtered: Record<string, any> = {};
        
        Object.keys(item).forEach((key) => {
          // 메타데이터 필드 제외
          if (key.startsWith("_")) {
            return;
          }
          
          // sourceColumns에 포함되어 있지만 columnMappings에도 정의된 경우 → 저장함
          if (mappedFields.includes(key)) {
            filtered[key] = item[key];
            return;
          }
          
          // sourceColumns에만 있고 매핑 안 된 경우 → 제외 (조인 전용)
          if (sourceColumns.includes(key)) {
            return;
          }
          
          // 나머지는 모두 저장
          filtered[key] = item[key];
        });
        
        return filtered;
      });
      
      // targetTable 메타데이터를 배열 항목에 추가
      const dataWithTargetTable = targetTable 
        ? filteredData.map((item: any) => ({
            ...item,
            _targetTable: targetTable, // 백엔드가 인식할 메타데이터
          }))
        : filteredData;
      
      // CustomEvent의 detail에 데이터 추가
      if (event instanceof CustomEvent && event.detail) {
        event.detail.formData[componentKey] = dataWithTargetTable;
        console.log("✅ [ModalRepeaterTable] 저장 데이터 준비:", {
          key: componentKey,
          itemCount: dataWithTargetTable.length,
          targetTable: targetTable || "미설정",
        });
      }
      
      // 기존 onFormDataChange도 호출 (호환성)
      if (onFormDataChange) {
        onFormDataChange(componentKey, dataWithTargetTable);
      }
    };
    
    // 저장 버튼 클릭 시 데이터 수집
    window.addEventListener("beforeFormSave", handleSaveRequest as EventListener);
    
    return () => {
      window.removeEventListener("beforeFormSave", handleSaveRequest as EventListener);
    };
  }, [localValue, columnName, component?.id, onFormDataChange, targetTable]);

  const { calculateRow, calculateAll } = useCalculation(calculationRules);
  
  /**
   * 동적 데이터 소스 변경 시 호출
   * 해당 컬럼의 모든 행 데이터를 새로운 소스에서 다시 조회
   */
  const handleDataSourceChange = async (columnField: string, optionId: string) => {
    console.log(`🔄 데이터 소스 변경: ${columnField} → ${optionId}`);
    
    // 활성화 상태 업데이트
    setActiveDataSources((prev) => ({
      ...prev,
      [columnField]: optionId,
    }));
    
    // 해당 컬럼 찾기
    const column = columns.find((col) => col.field === columnField);
    if (!column?.dynamicDataSource?.enabled) {
      console.warn(`⚠️ 컬럼 "${columnField}"에 동적 데이터 소스가 설정되지 않음`);
      return;
    }
    
    // 선택된 옵션 찾기
    const option = column.dynamicDataSource.options.find((opt) => opt.id === optionId);
    if (!option) {
      console.warn(`⚠️ 옵션 "${optionId}"을 찾을 수 없음`);
      return;
    }
    
    // 모든 행에 대해 새 값 조회
    const updatedData = await Promise.all(
      localValue.map(async (row, index) => {
        try {
          const newValue = await fetchDynamicValue(option, row);
          console.log(`  ✅ 행 ${index}: ${columnField} = ${newValue}`);
          return {
            ...row,
            [columnField]: newValue,
          };
        } catch (error) {
          console.error(`  ❌ 행 ${index} 조회 실패:`, error);
          return row;
        }
      })
    );
    
    // 계산 필드 업데이트 후 데이터 반영
    const calculatedData = calculateAll(updatedData);
    handleChange(calculatedData);
  };
  
  /**
   * 동적 데이터 소스 옵션에 따라 값 조회
   */
  async function fetchDynamicValue(
    option: DynamicDataSourceOption,
    rowData: any
  ): Promise<any> {
    if (option.sourceType === "table" && option.tableConfig) {
      // 테이블 직접 조회 (단순 조인)
      const { tableName, valueColumn, joinConditions } = option.tableConfig;
      
      const whereConditions: Record<string, any> = {};
      for (const cond of joinConditions) {
        let value = rowData[cond.sourceField];
        if (value === undefined || value === null) {
          console.warn(`⚠️ 조인 조건의 소스 필드 "${cond.sourceField}" 값이 없음`);
          return undefined;
        }
        // 숫자형 ID인 경우 숫자로 변환
        if (cond.targetField.endsWith('_id') || cond.targetField === 'id') {
          const numValue = Number(value);
          if (!isNaN(numValue)) {
            value = numValue;
          }
        }
        whereConditions[cond.targetField] = value;
      }
      
      console.log(`🔍 테이블 조회: ${tableName}`, whereConditions);
      
      const response = await apiClient.post(
        `/table-management/tables/${tableName}/data`,
        { search: whereConditions, size: 1, page: 1 }
      );
      
      if (response.data.success && response.data.data?.data?.length > 0) {
        return response.data.data.data[0][valueColumn];
      }
      return undefined;
      
    } else if (option.sourceType === "multiTable" && option.multiTableConfig) {
      // 테이블 복합 조인 (2개 이상 테이블 순차 조인)
      const { joinChain, valueColumn } = option.multiTableConfig;
      
      if (!joinChain || joinChain.length === 0) {
        console.warn("⚠️ 조인 체인이 비어있습니다.");
        return undefined;
      }
      
      console.log(`🔗 복합 조인 시작: ${joinChain.length}단계`);
      
      // 현재 값을 추적 (첫 단계는 현재 행에서 시작)
      let currentValue: any = null;
      let currentRow: any = null;
      
      for (let i = 0; i < joinChain.length; i++) {
        const step = joinChain[i];
        const { tableName, joinCondition, outputField } = step;
        
        // 조인 조건 값 가져오기
        let fromValue: any;
        if (i === 0) {
          // 첫 번째 단계: 현재 행에서 값 가져오기
          fromValue = rowData[joinCondition.fromField];
          console.log(`  📍 단계 ${i + 1}: 현재행.${joinCondition.fromField} = ${fromValue}`);
        } else {
          // 이후 단계: 이전 조회 결과에서 값 가져오기
          fromValue = currentRow?.[joinCondition.fromField] || currentValue;
          console.log(`  📍 단계 ${i + 1}: 이전결과.${joinCondition.fromField} = ${fromValue}`);
        }
        
        if (fromValue === undefined || fromValue === null) {
          console.warn(`⚠️ 단계 ${i + 1}: 조인 조건 값이 없습니다. (${joinCondition.fromField})`);
          return undefined;
        }
        
        // 테이블 조회
        // 숫자형 ID인 경우 숫자로 변환
        let convertedFromValue = fromValue;
        if (joinCondition.toField.endsWith('_id') || joinCondition.toField === 'id') {
          const numValue = Number(fromValue);
          if (!isNaN(numValue)) {
            convertedFromValue = numValue;
          }
        }
        const whereConditions: Record<string, any> = {
          [joinCondition.toField]: convertedFromValue
        };
        
        console.log(`  🔍 단계 ${i + 1}: ${tableName} 조회`, whereConditions);
        
        try {
          const response = await apiClient.post(
            `/table-management/tables/${tableName}/data`,
            { search: whereConditions, size: 1, page: 1 }
          );
          
          if (response.data.success && response.data.data?.data?.length > 0) {
            currentRow = response.data.data.data[0];
            currentValue = outputField ? currentRow[outputField] : currentRow;
            console.log(`  ✅ 단계 ${i + 1} 성공:`, { outputField, value: currentValue });
          } else {
            console.warn(`  ⚠️ 단계 ${i + 1}: 조회 결과 없음`);
            return undefined;
          }
        } catch (error) {
          console.error(`  ❌ 단계 ${i + 1} 조회 실패:`, error);
          return undefined;
        }
      }
      
      // 최종 값 반환 (마지막 테이블에서 valueColumn 가져오기)
      const finalValue = currentRow?.[valueColumn];
      console.log(`🎯 복합 조인 완료: ${valueColumn} = ${finalValue}`);
      return finalValue;
      
    } else if (option.sourceType === "api" && option.apiConfig) {
      // 전용 API 호출 (복잡한 다중 조인)
      const { endpoint, method = "GET", parameterMappings, responseValueField } = option.apiConfig;
      
      // 파라미터 빌드
      const params: Record<string, any> = {};
      for (const mapping of parameterMappings) {
        const value = rowData[mapping.sourceField];
        if (value !== undefined && value !== null) {
          params[mapping.paramName] = value;
        }
      }
      
      console.log(`🔍 API 호출: ${method} ${endpoint}`, params);
      
      let response;
      if (method === "POST") {
        response = await apiClient.post(endpoint, params);
      } else {
        response = await apiClient.get(endpoint, { params });
      }
      
      if (response.data.success && response.data.data) {
        // responseValueField로 값 추출 (중첩 경로 지원: "data.price")
        const keys = responseValueField.split(".");
        let value = response.data.data;
        for (const key of keys) {
          value = value?.[key];
        }
        return value;
      }
      return undefined;
    }
    
    return undefined;
  }

  // 초기 데이터에 계산 필드 적용
  useEffect(() => {
    if (localValue.length > 0 && calculationRules.length > 0) {
      const calculated = calculateAll(localValue);
      // 값이 실제로 변경된 경우만 업데이트
      if (JSON.stringify(calculated) !== JSON.stringify(localValue)) {
        handleChange(calculated);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const handleAddItems = async (items: any[]) => {
    console.log("➕ handleAddItems 호출:", items.length, "개 항목");
    console.log("📋 소스 데이터:", items);

    // 매핑 규칙에 따라 데이터 변환 (비동기 처리)
    const mappedItems = await Promise.all(items.map(async (sourceItem) => {
      const newItem: any = {};

      // ⚠️ 중요: reference 매핑은 다른 컬럼에 의존할 수 있으므로
      // 1단계: source/manual 매핑을 먼저 처리
      // 2단계: reference 매핑을 나중에 처리
      
      const referenceColumns: typeof columns = [];
      const otherColumns: typeof columns = [];
      
      for (const col of columns) {
        if (col.mapping?.type === "reference") {
          referenceColumns.push(col);
        } else {
          otherColumns.push(col);
        }
      }

      // 1단계: source/manual 컬럼 먼저 처리
      for (const col of otherColumns) {
        console.log(`🔄 컬럼 "${col.field}" 매핑 처리:`, col.mapping);

        // 1. 매핑 규칙이 있는 경우
        if (col.mapping) {
          if (col.mapping.type === "source") {
            // 소스 테이블 컬럼에서 복사
            const sourceField = col.mapping.sourceField;
            if (sourceField && sourceItem[sourceField] !== undefined) {
              newItem[col.field] = sourceItem[sourceField];
              console.log(`  ✅ 소스 복사: ${sourceField} → ${col.field}:`, newItem[col.field]);
            } else {
              console.warn(`  ⚠️ 소스 필드 "${sourceField}" 값이 없음`);
            }
          } else if (col.mapping.type === "manual") {
            // 사용자 입력 (빈 값)
            newItem[col.field] = undefined;
            console.log(`  ✏️ 수동 입력 필드`);
          }
        } 
        // 2. 매핑 규칙이 없는 경우 - 소스 데이터에서 같은 필드명으로 복사
        else if (sourceItem[col.field] !== undefined) {
          newItem[col.field] = sourceItem[col.field];
          console.log(`  📝 직접 복사: ${col.field}:`, newItem[col.field]);
        }

        // 3. 기본값 적용
        if (col.defaultValue !== undefined && newItem[col.field] === undefined) {
          newItem[col.field] = col.defaultValue;
          console.log(`  🎯 기본값 적용: ${col.field}:`, col.defaultValue);
        }
      }

      // 2단계: reference 컬럼 처리 (다른 컬럼들이 모두 설정된 후)
      console.log("🔗 2단계: reference 컬럼 처리 시작");
      for (const col of referenceColumns) {
        console.log(`🔄 컬럼 "${col.field}" 참조 매핑 처리:`, col.mapping);
        
        // 외부 테이블 참조 (API 호출)
        console.log(`  ⏳ 참조 조회 시작: ${col.mapping?.referenceTable}.${col.mapping?.referenceField}`);
        
        try {
          const referenceValue = await fetchReferenceValue(
            col.mapping!.referenceTable!,
            col.mapping!.referenceField!,
            col.mapping!.joinCondition || [],
            sourceItem,
            newItem
          );
          
          if (referenceValue !== null && referenceValue !== undefined) {
            newItem[col.field] = referenceValue;
            console.log(`  ✅ 참조 조회 성공: ${col.field}:`, referenceValue);
          } else {
            newItem[col.field] = undefined;
            console.warn(`  ⚠️ 참조 조회 결과 없음`);
          }
        } catch (error) {
          console.error(`  ❌ 참조 조회 오류:`, error);
          newItem[col.field] = undefined;
        }
        
        // 기본값 적용
        if (col.defaultValue !== undefined && newItem[col.field] === undefined) {
          newItem[col.field] = col.defaultValue;
          console.log(`  🎯 기본값 적용: ${col.field}:`, col.defaultValue);
        }
      }

      console.log("📦 변환된 항목:", newItem);
      return newItem;
    }));

    // 계산 필드 업데이트
    const calculatedItems = calculateAll(mappedItems);

    // 기존 데이터에 추가
    const newData = [...localValue, ...calculatedItems];
    console.log("✅ 최종 데이터:", newData.length, "개 항목");

    // ✅ 통합 onChange 호출 (formData 반영 포함)
    handleChange(newData);
  };

  const handleRowChange = (index: number, newRow: any) => {
    // 계산 필드 업데이트
    const calculatedRow = calculateRow(newRow);

    // 데이터 업데이트
    const newData = [...localValue];
    newData[index] = calculatedRow;
    
    // ✅ 통합 onChange 호출 (formData 반영 포함)
    handleChange(newData);
  };

  const handleRowDelete = (index: number) => {
    const newData = localValue.filter((_, i) => i !== index);
    
    // ✅ 통합 onChange 호출 (formData 반영 포함)
    handleChange(newData);
  };

  // 선택된 항목 일괄 삭제 핸들러
  const handleBulkDelete = () => {
    if (selectedRows.size === 0) return;
    
    // 선택되지 않은 항목만 남김
    const newData = localValue.filter((_, index) => !selectedRows.has(index));
    
    // 데이터 업데이트 및 선택 상태 초기화
    handleChange(newData);
    setSelectedRows(new Set());
  };

  // 컬럼명 -> 라벨명 매핑 생성 (sourceColumnLabels 우선, 없으면 columns에서 가져옴)
  const columnLabels = columns.reduce((acc, col) => {
    // sourceColumnLabels에 정의된 라벨 우선 사용
    acc[col.field] = sourceColumnLabels[col.field] || col.label;
    return acc;
  }, { ...sourceColumnLabels } as Record<string, string>);

  return (
    <div className={cn("space-y-4", className)}>
      {/* 추가 버튼 */}
      <div className="flex justify-between items-center">
        <div className="flex items-center gap-2">
          <span className="text-sm text-muted-foreground">
            {localValue.length > 0 && `${localValue.length}개 항목`}
            {selectedRows.size > 0 && ` (${selectedRows.size}개 선택됨)`}
          </span>
          {columns.length > 0 && (
            <Button
              variant="outline"
              size="sm"
              onClick={() => setEqualizeWidthsTrigger((prev) => prev + 1)}
              className="h-7 text-xs px-2"
              title="컬럼 너비 균등 분배"
            >
              <Columns className="h-3.5 w-3.5 mr-1" />
              균등 분배
            </Button>
          )}
        </div>
        <div className="flex gap-2">
          {selectedRows.size > 0 && (
            <Button
              variant="destructive"
              onClick={handleBulkDelete}
              className="h-8 text-xs sm:h-10 sm:text-sm"
            >
              선택 삭제 ({selectedRows.size})
            </Button>
          )}
          <Button
            onClick={() => setModalOpen(true)}
            className="h-8 text-xs sm:h-10 sm:text-sm"
          >
            <Plus className="h-4 w-4 mr-2" />
            {modalButtonText}
          </Button>
        </div>
      </div>

      {/* Repeater 테이블 */}
      <RepeaterTable
        columns={columns}
        data={localValue}
        onDataChange={handleChange}
        onRowChange={handleRowChange}
        onRowDelete={handleRowDelete}
        activeDataSources={activeDataSources}
        onDataSourceChange={handleDataSourceChange}
        selectedRows={selectedRows}
        onSelectionChange={setSelectedRows}
        equalizeWidthsTrigger={equalizeWidthsTrigger}
      />

      {/* 항목 선택 모달 */}
      <ItemSelectionModal
        open={modalOpen}
        onOpenChange={setModalOpen}
        sourceTable={sourceTable}
        sourceColumns={sourceColumns}
        sourceSearchFields={sourceSearchFields}
        multiSelect={multiSelect}
        filterCondition={filterCondition}
        modalTitle={modalTitle}
        alreadySelected={localValue}
        uniqueField={uniqueField}
        onSelect={handleAddItems}
        columnLabels={columnLabels}
      />
    </div>
  );
}

