"use client";

import * as React from "react";
import dynamic from "next/dynamic";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { GenericData } from "./export-excel-form";
import * as GC from "@mescius/spread-sheets";
import { toast } from "sonner";
import { updateFormDataInDB } from "@/lib/forms/services";
import { Loader, Save, AlertTriangle } from "lucide-react";
import '@mescius/spread-sheets/styles/gc.spread.sheets.excel2016colorful.css';
import { DataTableColumnJSON, ColumnType } from "./form-data-table-columns";


// SpreadSheets를 동적으로 import (SSR 비활성화)
const SpreadSheets = dynamic(
  () => import("@mescius/spread-sheets-react").then(mod => mod.SpreadSheets),
  {
    ssr: false,
    loading: () => (
      <div className="flex items-center justify-center h-full">
        <Loader className="mr-2 h-4 w-4 animate-spin" />
        Loading SpreadSheets...
      </div>
    )
  }
);

// 라이센스 키 설정을 클라이언트에서만 실행
if (typeof window !== 'undefined' && process.env.NEXT_PUBLIC_SPREAD_LICENSE) {
  GC.Spread.Sheets.LicenseKey = process.env.NEXT_PUBLIC_SPREAD_LICENSE;
}

interface TemplateItem {
  TMPL_ID: string;
  NAME: string;
  TMPL_TYPE: string;
  SPR_LST_SETUP: {
    ACT_SHEET: string;
    HIDN_SHEETS: Array<string>;
    CONTENT?: string;
    DATA_SHEETS: Array<{
      SHEET_NAME: string;
      REG_TYPE_ID: string;
      MAP_CELL_ATT: Array<{
        ATT_ID: string;
        IN: string;
      }>;
    }>;
  };
  GRD_LST_SETUP: {
    REG_TYPE_ID: string;
    SPR_ITM_IDS: Array<string>;
    ATTS: Array<{}>;
  };
  SPR_ITM_LST_SETUP: {
    ACT_SHEET: string;
    HIDN_SHEETS: Array<string>;
    CONTENT?: string;
    DATA_SHEETS: Array<{
      SHEET_NAME: string;
      REG_TYPE_ID: string;
      MAP_CELL_ATT: Array<{
        ATT_ID: string;
        IN: string;
      }>;
    }>;
  };
}

interface ValidationError {
  cellAddress: string;
  attId: string;
  value: any;
  expectedType: ColumnType;
  message: string;
}

interface CellMapping {
  attId: string;
  cellAddress: string;
  isEditable: boolean;
  dataRowIndex?: number;
}

interface TemplateViewDialogProps {
  isOpen: boolean;
  onClose: () => void;
  templateData: TemplateItem[] | any;
  selectedRow?: GenericData; // SPREAD_ITEM용
  tableData?: GenericData[]; // SPREAD_LIST용
  formCode: string;
  columnsJSON: DataTableColumnJSON[]
  contractItemId: number;
  editableFieldsMap?: Map<string, string[]>;
  onUpdateSuccess?: (updatedValues: Record<string, any> | GenericData[]) => void;
}

export function TemplateViewDialog({
  isOpen,
  onClose,
  templateData,
  selectedRow,
  tableData = [],
  formCode,
  contractItemId,
  columnsJSON,
  editableFieldsMap = new Map(),
  onUpdateSuccess
}: TemplateViewDialogProps) {
  const [hostStyle, setHostStyle] = React.useState({
    width: '100%',
    height: '100%'
  });

  const [isPending, setIsPending] = React.useState(false);
  const [hasChanges, setHasChanges] = React.useState(false);
  const [currentSpread, setCurrentSpread] = React.useState<any>(null);
  const [cellMappings, setCellMappings] = React.useState<CellMapping[]>([]);
  const [isClient, setIsClient] = React.useState(false);
  const [templateType, setTemplateType] = React.useState<'SPREAD_LIST' | 'SPREAD_ITEM' | 'GRD_LIST' | null>(null);
  const [validationErrors, setValidationErrors] = React.useState<ValidationError[]>([]);
  const [selectedTemplateId, setSelectedTemplateId] = React.useState<string>("");
  const [availableTemplates, setAvailableTemplates] = React.useState<TemplateItem[]>([]);

  const determineTemplateType = React.useCallback((template: TemplateItem): 'SPREAD_LIST' | 'SPREAD_ITEM' | 'GRD_LIST' | null => {
    // 1. SPREAD_LIST: TMPL_TYPE이 SPREAD_LIST이고 SPR_LST_SETUP.CONTENT가 있음
    if (template.TMPL_TYPE === "SPREAD_LIST" && (template.SPR_LST_SETUP?.CONTENT || template.SPR_ITM_LST_SETUP?.CONTENT)) {
      return 'SPREAD_LIST';
    }

    // 2. SPREAD_ITEM: TMPL_TYPE이 SPREAD_ITEM이고 SPR_ITM_LST_SETUP.CONTENT가 있음
    if (template.TMPL_TYPE === "SPREAD_ITEM" && (template.SPR_LST_SETUP?.CONTENT || template.SPR_ITM_LST_SETUP?.CONTENT)) {
      return 'SPREAD_ITEM';
    }

    // 3. GRD_LIST: GRD_LST_SETUP이 있고 columnsJSON이 있음 (동적 테이블)
    if (template.GRD_LST_SETUP && columnsJSON.length > 0) {
      return 'GRD_LIST';
    }

    return null; // 유효하지 않은 템플릿
  }, [columnsJSON]);

  const isValidTemplate = React.useCallback((template: TemplateItem): boolean => {
    return determineTemplateType(template) !== null;
  }, [determineTemplateType]);


  // 클라이언트 사이드에서만 렌더링되도록 보장
  React.useEffect(() => {
    setIsClient(true);
  }, []);

  // 사용 가능한 템플릿들을 필터링하고 설정
  React.useEffect(() => {
    if (!templateData) return;

    let templates: TemplateItem[];
    if (Array.isArray(templateData)) {
      templates = templateData as TemplateItem[];
    } else {
      templates = [templateData as TemplateItem];
    }

    // 유효한 템플릿들만 필터링
    const validTemplates = templates.filter(isValidTemplate);

    setAvailableTemplates(validTemplates);

    // 첫 번째 유효한 템플릿을 기본으로 선택
    if (validTemplates.length > 0 && !selectedTemplateId) {
      const firstTemplate = validTemplates[0];
      const templateTypeToSet = determineTemplateType(firstTemplate);

      setSelectedTemplateId(firstTemplate.TMPL_ID);
      setTemplateType(templateTypeToSet);
    }
  }, [templateData, selectedTemplateId, isValidTemplate, determineTemplateType]);


  // 선택된 템플릿 변경 처리
  const handleTemplateChange = (templateId: string) => {
    const template = availableTemplates.find(t => t.TMPL_ID === templateId);
    if (template) {
      const templateTypeToSet = determineTemplateType(template);

      setSelectedTemplateId(templateId);
      setTemplateType(templateTypeToSet);
      setHasChanges(false);
      setValidationErrors([]);

      // SpreadSheets 재초기화
      if (currentSpread && template) {
        initSpread(currentSpread, template);
      }
    }
  };
  // 현재 선택된 템플릿 가져오기
  const selectedTemplate = React.useMemo(() => {
    return availableTemplates.find(t => t.TMPL_ID === selectedTemplateId);
  }, [availableTemplates, selectedTemplateId]);


  // 편집 가능한 필드 목록 계산
  const editableFields = React.useMemo(() => {
    // SPREAD_ITEM인 경우: selectedRow의 TAG_NO로 확인
    if (templateType === 'SPREAD_ITEM' && selectedRow?.TAG_NO) {
      if (!editableFieldsMap.has(selectedRow.TAG_NO)) {
        return [];
      }
      return editableFieldsMap.get(selectedRow.TAG_NO) || [];
    }

    // SPREAD_LIST 또는 GRD_LIST인 경우: 첫 번째 행의 TAG_NO를 기준으로 처리
    if ((templateType === 'SPREAD_LIST' || templateType === 'GRD_LIST') && tableData.length > 0) {
      const firstRowTagNo = tableData[0]?.TAG_NO;
      if (firstRowTagNo && editableFieldsMap.has(firstRowTagNo)) {
        return editableFieldsMap.get(firstRowTagNo) || [];
      }
    }

    return [];
  }, [templateType, selectedRow?.TAG_NO, tableData, editableFieldsMap]);

  // 필드가 편집 가능한지 판별하는 함수
  const isFieldEditable = React.useCallback((attId: string, rowData?: GenericData) => {
    // columnsJSON에서 해당 attId의 shi 값 확인
    const columnConfig = columnsJSON.find(col => col.key === attId);
    if (columnConfig?.shi === true) {
      return false; // columnsJSON에서 shi가 true이면 편집 불가
    }

    // TAG_NO와 TAG_DESC는 기본적으로 편집 가능 (columnsJSON의 shi가 false인 경우)
    if (attId === "TAG_NO" || attId === "TAG_DESC") {
      return false;
    }

    if (attId === "status") {
      return false;
    }

    // SPREAD_ITEM인 경우: editableFields 체크
    // if (templateType === 'SPREAD_ITEM') {
    //   return editableFields.includes(attId);
    // }

    // SPREAD_LIST 또는 GRD_LIST인 경우: 개별 행의 편집 가능성도 고려
    if (templateType === 'SPREAD_LIST' || templateType === 'GRD_LIST') {
      // 기본적으로 editableFields에 포함되어야 함
      // if (!editableFields.includes(attId)) {
      //   return false;
      // }

      // rowData가 제공된 경우 해당 행의 shi 상태도 확인
      if (rowData && rowData.shi === true) {
        return false;
      }

      return true;
    }

    return true;
  }, [templateType, columnsJSON, editableFields]);

  // 편집 가능한 필드 개수 계산
  const editableFieldsCount = React.useMemo(() => {
    return cellMappings.filter(m => m.isEditable).length;
  }, [cellMappings]);

  // 셀 주소를 행과 열로 변환하는 함수
  const parseCellAddress = (address: string): { row: number, col: number } | null => {
    if (!address || address.trim() === "") return null;

    const match = address.match(/^([A-Z]+)(\d+)$/);
    if (!match) return null;

    const [, colStr, rowStr] = match;

    let col = 0;
    for (let i = 0; i < colStr.length; i++) {
      col = col * 26 + (colStr.charCodeAt(i) - 65 + 1);
    }
    col -= 1;

    const row = parseInt(rowStr) - 1;

    return { row, col };
  };

  // 행과 열을 셀 주소로 변환하는 함수 (GRD_LIST용)
  const getCellAddress = (row: number, col: number): string => {
    let colStr = '';
    let colNum = col;
    while (colNum >= 0) {
      colStr = String.fromCharCode((colNum % 26) + 65) + colStr;
      colNum = Math.floor(colNum / 26) - 1;
    }
    return colStr + (row + 1);
  };

  // 데이터 타입 검증 함수
  const validateCellValue = (value: any, columnType: ColumnType, options?: string[]): string | null => {
    if (value === undefined || value === null || value === "") {
      return null; // 빈 값은 별도 required 검증에서 처리
    }

    switch (columnType) {
      case "NUMBER":
        if (isNaN(Number(value))) {
          return "Value must be a valid number";
        }
        break;
      case "LIST":
        if (options && !options.includes(String(value))) {
          return `Value must be one of: ${options.join(", ")}`;
        }
        break;
      case "STRING":
        // STRING 타입은 대부분의 값을 허용
        break;
      default:
        // 커스텀 타입의 경우 추가 검증 로직이 필요할 수 있음
        break;
    }

    return null;
  };

  // 전체 데이터 검증 함수
  const validateAllData = React.useCallback(() => {
    if (!currentSpread || !selectedTemplate) return [];

    const activeSheet = currentSpread.getActiveSheet();
    const errors: ValidationError[] = [];

    cellMappings.forEach(mapping => {
      const columnConfig = columnsJSON.find(col => col.key === mapping.attId);
      if (!columnConfig) return;

      const cellPos = parseCellAddress(mapping.cellAddress);
      if (!cellPos) return;

      if (templateType === 'SPREAD_ITEM') {
        // 단일 행 검증
        const cellValue = activeSheet.getValue(cellPos.row, cellPos.col);
        const errorMessage = validateCellValue(cellValue, columnConfig.type, columnConfig.options);

        if (errorMessage) {
          errors.push({
            cellAddress: mapping.cellAddress,
            attId: mapping.attId,
            value: cellValue,
            expectedType: columnConfig.type,
            message: errorMessage
          });
        }
      } else if (templateType === 'SPREAD_LIST' || templateType === 'GRD_LIST') {
        // 복수 행 검증 - 각 매핑은 이미 개별 행을 가리킴
        const cellValue = activeSheet.getValue(cellPos.row, cellPos.col);
        const errorMessage = validateCellValue(cellValue, columnConfig.type, columnConfig.options);

        if (errorMessage) {
          errors.push({
            cellAddress: mapping.cellAddress,
            attId: mapping.attId,
            value: cellValue,
            expectedType: columnConfig.type,
            message: errorMessage
          });
        }
      }
    });

    setValidationErrors(errors);
    return errors;
  }, [currentSpread, selectedTemplate, cellMappings, columnsJSON, templateType]);

  // ═══════════════════════════════════════════════════════════════════════════════
  // 🛠️ 헬퍼 함수들
  // ═══════════════════════════════════════════════════════════════════════════════

  // 🎨 셀 스타일 생성
  const createCellStyle = React.useCallback((isEditable: boolean) => {
    const style = new GC.Spread.Sheets.Style();
    if (isEditable) {
      style.backColor = "#f0fdf4"; // 연한 초록 (편집 가능)
    } else {
      style.backColor = "#f9fafb"; // 연한 회색 (읽기 전용)
      style.foreColor = "#6b7280";
    }
    return style;
  }, []);

  // 🎯 드롭다운 설정
  const setupOptimizedListValidation = React.useCallback((activeSheet: any, cellPos: { row: number, col: number }, options: string[], rowCount: number) => {
    try {
      console.log(`🎯 Setting up dropdown for ${rowCount} rows with options:`, options);

      // ✅ options 정규화
      const safeOptions = options
        .filter(opt => opt !== null && opt !== undefined && opt !== '')
        .map(opt => String(opt).trim())
        .filter(opt => opt.length > 0)
        .filter((opt, index, arr) => arr.indexOf(opt) === index)
        .slice(0, 20);

      if (safeOptions.length === 0) {
        console.warn(`⚠️ No valid options found, skipping`);
        return;
      }

      console.log(`📋 Safe options:`, safeOptions);

      // ✅ DataValidation용 문자열 준비
      const optionsString = safeOptions.join(',');

      // 🔑 핵심 수정: 각 셀마다 개별 ComboBox 인스턴스 생성!
      for (let i = 0; i < rowCount; i++) {
        try {
          const targetRow = cellPos.row + i;

          // ✅ 각 셀마다 새로운 ComboBox 인스턴스 생성
          const comboBoxCellType = new GC.Spread.Sheets.CellTypes.ComboBox();
          comboBoxCellType.items(safeOptions); // 배열로 전달
          comboBoxCellType.editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.text);

          // ✅ 각 셀마다 새로운 DataValidation 인스턴스 생성
          const cellValidator = GC.Spread.Sheets.DataValidation.createListValidator(optionsString);

          // ComboBox + DataValidation 둘 다 적용
          activeSheet.setCellType(targetRow, cellPos.col, comboBoxCellType);
          activeSheet.setDataValidator(targetRow, cellPos.col, cellValidator);

          // 셀 잠금 해제
          const cell = activeSheet.getCell(targetRow, cellPos.col);
          cell.locked(false);

          console.log(`✅ Individual dropdown applied to [${targetRow}, ${cellPos.col}]`);

        } catch (cellError) {
          console.warn(`⚠️ Failed to apply to row ${cellPos.row + i}:`, cellError);
        }
      }

      console.log(`✅ Safe dropdown setup completed for ${rowCount} cells`);

    } catch (error) {
      console.error('❌ Dropdown setup failed:', error);
    }
  }, []);

  // 🛡️ 안전한 시트 검증 함수 추가
const validateActiveSheet = React.useCallback((activeSheet: any, functionName: string = 'unknown') => {
  console.log(`🔍 Validating activeSheet for ${functionName}:`);
  
  if (!activeSheet) {
    console.error(`❌ activeSheet is null/undefined in ${functionName}`);
    return false;
  }
  
  console.log(`✅ activeSheet exists (type: ${typeof activeSheet})`);
  console.log(`✅ constructor: ${activeSheet.constructor?.name}`);
  
  // 핵심 메서드들 존재 여부 확인
  const requiredMethods = ['getRowCount', 'getColumnCount', 'setRowCount', 'setColumnCount', 'getCell', 'getValue', 'setStyle'];
  const missingMethods = requiredMethods.filter(method => typeof activeSheet[method] !== 'function');
  
  if (missingMethods.length > 0) {
    console.error(`❌ Missing methods in ${functionName}:`, missingMethods);
    console.log(`📋 Available methods:`, Object.getOwnPropertyNames(activeSheet).filter(prop => typeof activeSheet[prop] === 'function').slice(0, 20));
    return false;
  }
  
  console.log(`✅ All required methods available for ${functionName}`);
  return true;
}, []);
// 🛡️ 안전한 ActiveSheet 가져오기 함수
const getSafeActiveSheet = React.useCallback((spread: any, functionName: string = 'unknown') => {
  console.log(`🔍 Getting safe activeSheet for ${functionName}`);
  
  if (!spread) {
    console.error(`❌ Spread is null/undefined in ${functionName}`);
    return null;
  }
  
  try {
    // 현재 활성 시트 가져오기
    let activeSheet = spread.getActiveSheet();
    
    if (!activeSheet) {
      console.warn(`⚠️ ActiveSheet is null, attempting to get first sheet in ${functionName}`);
      
      // 첫 번째 시트 시도
      const sheetCount = spread.getSheetCount();
      console.log(`📊 Total sheets: ${sheetCount}`);
      
      if (sheetCount > 0) {
        activeSheet = spread.getSheet(0);
        if (activeSheet) {
          spread.setActiveSheetIndex(0);
          console.log(`✅ Successfully got first sheet in ${functionName}`);
        }
      }
    }
    
    if (!activeSheet) {
      console.error(`❌ Failed to get any valid sheet in ${functionName}`);
      return null;
    }
    
    // 시트 유효성 검증
    const validation = validateActiveSheet(activeSheet, functionName);
    if (!validation) {
      console.error(`❌ Sheet validation failed in ${functionName}`);
      return null;
    }
    
    console.log(`✅ Got valid activeSheet for ${functionName}: ${activeSheet.name?.() || 'unnamed'}`);
    return activeSheet;
    
  } catch (error) {
    console.error(`❌ Error getting activeSheet in ${functionName}:`, error);
    return null;
  }
}, [validateActiveSheet]);

// 🛡️ 수정된 ensureRowCapacity 함수
const ensureRowCapacity = React.useCallback((activeSheet: any, requiredRowCount: number) => {
  try {
    // 🔍 상세한 null/undefined 체크
    if (!activeSheet) {
      console.error('❌ activeSheet is null/undefined in ensureRowCapacity');
      return false;
    }

    console.log('🔍 ActiveSheet validation in ensureRowCapacity:');
    console.log('  - Type:', typeof activeSheet);
    console.log('  - Constructor:', activeSheet.constructor?.name);
    console.log('  - Is null:', activeSheet === null);
    console.log('  - Is undefined:', activeSheet === undefined);
    
    // 🔍 메서드 존재 여부 확인
    if (typeof activeSheet.getRowCount !== 'function') {
      console.error('❌ getRowCount method does not exist on activeSheet');
      console.log('📋 Available properties:', Object.getOwnPropertyNames(activeSheet).slice(0, 20));
      return false;
    }

    // 🔍 시트 상태 확인
    const currentRowCount = activeSheet.getRowCount();
    console.log(`📊 Current row count: ${currentRowCount} (type: ${typeof currentRowCount})`);

    if (typeof currentRowCount !== 'number' || isNaN(currentRowCount)) {
      console.error('❌ getRowCount returned invalid value:', currentRowCount);
      return false;
    }

    if (requiredRowCount > currentRowCount) {
      // 🔍 setRowCount 메서드 확인
      if (typeof activeSheet.setRowCount !== 'function') {
        console.error('❌ setRowCount method does not exist on activeSheet');
        return false;
      }

      const newRowCount = requiredRowCount + 10;
      activeSheet.setRowCount(newRowCount);
      console.log(`📈 Expanded sheet: ${currentRowCount} → ${newRowCount} rows`);
      
      // 🔍 설정 후 검증
      const verifyRowCount = activeSheet.getRowCount();
      console.log(`✅ Verified new row count: ${verifyRowCount}`);
      
      return true;
    } else {
      console.log(`✅ Sheet already has sufficient rows: ${currentRowCount} >= ${requiredRowCount}`);
      return true;
    }

  } catch (error) {
    console.error('❌ Error in ensureRowCapacity:', error);
    console.error('❌ Error stack:', error.stack);
    return false;
  }
}, []);

// 🛡️ 안전한 컬럼 용량 확보 함수
const ensureColumnCapacity = React.useCallback((activeSheet: any, requiredColumnCount: number) => {
  try {
    // 🔍 상세한 null/undefined 체크
    if (!activeSheet) {
      console.error('❌ activeSheet is null/undefined in ensureColumnCapacity');
      return false;
    }

    console.log('🔍 ActiveSheet validation in ensureColumnCapacity:');
    console.log('  - Type:', typeof activeSheet);
    console.log('  - Constructor:', activeSheet.constructor?.name);
    console.log('  - Is null:', activeSheet === null);
    console.log('  - Is undefined:', activeSheet === undefined);

    // 🔍 메서드 존재 여부 확인
    if (typeof activeSheet.getColumnCount !== 'function') {
      console.error('❌ getColumnCount method does not exist on activeSheet');
      console.log('📋 Available properties:', Object.getOwnPropertyNames(activeSheet).slice(0, 20));
      return false;
    }

    const currentColumnCount = activeSheet.getColumnCount();
    console.log(`📊 Current column count: ${currentColumnCount} (type: ${typeof currentColumnCount})`);

    if (typeof currentColumnCount !== 'number' || isNaN(currentColumnCount)) {
      console.error('❌ getColumnCount returned invalid value:', currentColumnCount);
      return false;
    }

    if (requiredColumnCount > currentColumnCount) {
      if (typeof activeSheet.setColumnCount !== 'function') {
        console.error('❌ setColumnCount method does not exist on activeSheet');
        return false;
      }

      const newColumnCount = requiredColumnCount + 10;
      activeSheet.setColumnCount(newColumnCount);
      console.log(`📈 Expanded columns: ${currentColumnCount} → ${newColumnCount}`);
      
      // 🔍 설정 후 검증
      const verifyColumnCount = activeSheet.getColumnCount();
      console.log(`✅ Verified new column count: ${verifyColumnCount}`);
      
      return true;
    } else {
      console.log(`✅ Sheet already has sufficient columns: ${currentColumnCount} >= ${requiredColumnCount}`);
      return true;
    }

  } catch (error) {
    console.error('❌ Error in ensureColumnCapacity:', error);
    console.error('❌ Error stack:', error.stack);
    return false;
  }
}, []);


// 🎯 텍스트 너비 계산 함수들 (createGrdListTable 함수 위에 추가)
const measureTextWidth = React.useCallback((text: string, fontSize: number = 12, fontFamily: string = 'Arial'): number => {
  // Canvas를 사용한 정확한 텍스트 너비 측정
  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');
  if (!context) return text.length * 8; // fallback
  
  context.font = `${fontSize}px ${fontFamily}`;
  const metrics = context.measureText(text || '');
  return Math.ceil(metrics.width);
}, []);

const calculateColumnWidth = React.useCallback((
  headerText: string, 
  dataValues: any[] = [], 
  minWidth: number = 80, 
  maxWidth: number = 300,
  padding: number = 20
): number => {
  // 헤더 텍스트 너비 계산
  const headerWidth = measureTextWidth(headerText, 12, 'Arial');
  
  // 데이터 값들의 최대 너비 계산
  let maxDataWidth = 0;
  if (dataValues.length > 0) {
    maxDataWidth = Math.max(
      ...dataValues
        .slice(0, 10) // 성능을 위해 처음 10개만 샘플링
        .map(value => measureTextWidth(String(value || ''), 11, 'Arial'))
    );
  }
  
  // 헤더와 데이터 중 더 큰 너비 + 패딩 적용
  const calculatedWidth = Math.max(headerWidth, maxDataWidth) + padding;
  
  // 최소/최대 너비 제한 적용
  return Math.min(Math.max(calculatedWidth, minWidth), maxWidth);
}, [measureTextWidth]);

const setOptimalColumnWidths = React.useCallback((activeSheet: any, columns: any[], startCol: number, tableData: any[]) => {
  console.log('🎨 Setting optimal column widths...');
  
  columns.forEach((column, colIndex) => {
    const targetCol = startCol + colIndex;
    
    // 해당 컬럼의 데이터 값들 추출
    const dataValues = tableData.map(row => row[column.key]).filter(val => val != null);
    
    // 최적 너비 계산
    const optimalWidth = calculateColumnWidth(
      column.label || column.key, 
      dataValues,
      column.type === 'NUMBER' ? 100 : 80, // 숫자는 좀 더 넓게
      column.type === 'STRING' ? 250 : 200, // 문자열은 더 넓게
      column.type === 'LIST' ? 30 : 20 // 드롭다운은 여유 패딩
    );
    
    // 컬럼 너비 설정
    activeSheet.setColumnWidth(targetCol, optimalWidth);
    
    console.log(`📏 Column ${targetCol} (${column.key}): width set to ${optimalWidth}px`);
  });
}, [calculateColumnWidth]);

  // 🔍 컬럼 그룹 분석 함수
  const analyzeColumnGroups = React.useCallback((columns: DataTableColumnJSON[]) => {
    const groups: Array<{
      head: string;
      isGroup: boolean;
      columns: DataTableColumnJSON[];
    }> = [];

    let i = 0;
    while (i < columns.length) {
      const currentCol = columns[i];

      // head가 없거나 빈 문자열인 경우 단일 컬럼으로 처리
      if (!currentCol.head || !currentCol.head.trim()) {
        groups.push({
          head: '',
          isGroup: false,
          columns: [currentCol]
        });
        i++;
        continue;
      }

      // 같은 head를 가진 연속된 컬럼들을 찾기
      const groupHead = currentCol.head.trim();
      const groupColumns: DataTableColumnJSON[] = [currentCol];
      let j = i + 1;

      while (j < columns.length && columns[j].head && columns[j].head.trim() === groupHead) {
        groupColumns.push(columns[j]);
        j++;
      }

      // 그룹 추가
      groups.push({
        head: groupHead,
        isGroup: groupColumns.length > 1,
        columns: groupColumns
      });

      i = j; // 다음 그룹으로 이동
    }

    return { groups };
  }, []);


// 🆕 수정된 createGrdListTable 함수
// 🆕 개선된 GRD_LIST용 동적 테이블 생성 함수
const createGrdListTable = React.useCallback((activeSheet: any, template: TemplateItem) => {
  console.log('🏗️ Creating GRD_LIST table');

  // columnsJSON의 visible 컬럼들을 seq 순서로 정렬하여 사용
  const visibleColumns = columnsJSON
    .filter(col => col.hidden !== true)
    .sort((a, b) => {
      const seqA = a.seq !== undefined ? a.seq : 999999;
      const seqB = b.seq !== undefined ? b.seq : 999999;
      return seqA - seqB;
    });

  console.log('📊 Using columns:', visibleColumns.map(c => `${c.key}(seq:${c.seq})`));
  console.log(`📊 Total visible columns: ${visibleColumns.length}`);

  if (visibleColumns.length === 0) {
    console.warn('❌ No visible columns found in columnsJSON');
    return [];
  }

  // ⭐ 컬럼 용량 확보
  const startCol = 1;
  const requiredColumnCount = startCol + visibleColumns.length;
  ensureColumnCapacity(activeSheet, requiredColumnCount);

  // 테이블 생성 시작
  const mappings: CellMapping[] = [];

  // 🔍 그룹 헤더 분석
  const groupInfo = analyzeColumnGroups(visibleColumns);
  const hasGroups = groupInfo.groups.length > 0;

  // 헤더 행 계산: 그룹이 있으면 2행, 없으면 1행
  const groupHeaderRow = 0;
  const columnHeaderRow = hasGroups ? 1 : 0;
  const dataStartRow = hasGroups ? 2 : 1;

  // 🎨 헤더 스타일 생성
  const groupHeaderStyle = new GC.Spread.Sheets.Style();
  groupHeaderStyle.backColor = "#1e40af";
  groupHeaderStyle.foreColor = "#ffffff";
  groupHeaderStyle.font = "bold 13px Arial";
  groupHeaderStyle.hAlign = GC.Spread.Sheets.HorizontalAlign.center;
  groupHeaderStyle.vAlign = GC.Spread.Sheets.VerticalAlign.center;

  const columnHeaderStyle = new GC.Spread.Sheets.Style();
  columnHeaderStyle.backColor = "#3b82f6";
  columnHeaderStyle.foreColor = "#ffffff";
  columnHeaderStyle.font = "bold 12px Arial";
  columnHeaderStyle.hAlign = GC.Spread.Sheets.HorizontalAlign.center;
  columnHeaderStyle.vAlign = GC.Spread.Sheets.VerticalAlign.center;

  let currentCol = startCol;

  // 🏗️ 그룹 헤더 및 컬럼 헤더 생성
  if (hasGroups) {
    // 그룹 헤더가 있는 경우
    groupInfo.groups.forEach(group => {
      if (group.isGroup) {
        // 그룹 헤더 생성 및 병합
        const groupStartCol = currentCol;
        const groupEndCol = currentCol + group.columns.length - 1;

        // 그룹 헤더 셀 설정
        const groupHeaderCell = activeSheet.getCell(groupHeaderRow, groupStartCol);
        groupHeaderCell.value(group.head);

        // 그룹 헤더 병합
        if (group.columns.length > 1) {
          activeSheet.addSpan(groupHeaderRow, groupStartCol, 1, group.columns.length);
        }

        // 그룹 헤더 스타일 적용
        for (let col = groupStartCol; col <= groupEndCol; col++) {
          activeSheet.setStyle(groupHeaderRow, col, groupHeaderStyle);
          activeSheet.getCell(groupHeaderRow, col).locked(true);
        }

        console.log(`📝 Group Header [${groupHeaderRow}, ${groupStartCol}-${groupEndCol}]: ${group.head}`);

        // 그룹 내 개별 컬럼 헤더 생성
        group.columns.forEach((column, index) => {
          const colIndex = groupStartCol + index;
          const columnHeaderCell = activeSheet.getCell(columnHeaderRow, colIndex);
          columnHeaderCell.value(column.label);
          activeSheet.setStyle(columnHeaderRow, colIndex, columnHeaderStyle);
          columnHeaderCell.locked(true);

          console.log(`📝 Column Header [${columnHeaderRow}, ${colIndex}]: ${column.label}`);
        });

        currentCol += group.columns.length;
      } else {
        // 그룹이 아닌 단일 컬럼
        const column = group.columns[0];

        // 그룹 헤더 행에는 빈 셀
        const groupHeaderCell = activeSheet.getCell(groupHeaderRow, currentCol);
        groupHeaderCell.value("");
        activeSheet.setStyle(groupHeaderRow, currentCol, groupHeaderStyle);
        groupHeaderCell.locked(true);

        // 컬럼 헤더 생성
        const columnHeaderCell = activeSheet.getCell(columnHeaderRow, currentCol);
        columnHeaderCell.value(column.label);
        activeSheet.setStyle(columnHeaderRow, currentCol, columnHeaderStyle);
        columnHeaderCell.locked(true);

        console.log(`📝 Single Column [${columnHeaderRow}, ${currentCol}]: ${column.label}`);
        currentCol++;
      }
    });
  } else {
    // 그룹이 없는 경우
    visibleColumns.forEach((column, colIndex) => {
      const targetCol = startCol + colIndex;
      const columnConfig = columnsJSON.find(col => col.key === column.key);
      
      // 📋 각 행마다 개별 셀 설정
      tableData.forEach((rowData, rowIndex) => {
        const targetRow = dataStartRow + rowIndex;
        const cell = activeSheet.getCell(targetRow, targetCol);
        const value = rowData[column.key];
        const cellEditable = isFieldEditable(column.key, rowData);
    
        // 🔧 새로 추가: 셀 타입 및 편집기 설정
        if (columnConfig) {
          setupCellTypeAndEditor(activeSheet, { row: targetRow, col: targetCol }, columnConfig, cellEditable, 1);
        }
    
        // 값 설정
        cell.value(value ?? null);
    
        // 스타일 설정
        const style = createCellStyle(cellEditable);
        activeSheet.setStyle(targetRow, targetCol, style);
    
        // 개별 매핑 추가
        mappings.push({
          attId: column.key,
          cellAddress: getCellAddress(targetRow, targetCol),
          isEditable: cellEditable,
          dataRowIndex: rowIndex
        });
      });
    });
  }

  // 🔄 데이터 행 및 매핑 생성 (SPREAD_LIST 방식과 동일한 로직)
  const dataRowCount = tableData.length;
  ensureRowCapacity(activeSheet, dataStartRow + dataRowCount);

  // 📋 각 컬럼별로 매핑 생성 (SPREAD_LIST와 동일한 방식)
  visibleColumns.forEach((column, colIndex) => {
    const targetCol = startCol + colIndex;
    
    console.log(`🔄 Processing column ${column.key} with ${dataRowCount} rows`);

    // 📋 각 행마다 개별 매핑 생성 (SPREAD_LIST와 동일)
    tableData.forEach((rowData, rowIndex) => {
      const targetRow = dataStartRow + rowIndex;
      const cellAddress = getCellAddress(targetRow, targetCol);
      
      // 🛡️ readonly 체크 (SPREAD_LIST와 동일한 로직)
      const cellEditable = isFieldEditable(column.key, rowData);
      
      // 개별 매핑 추가
      mappings.push({
        attId: column.key,
        cellAddress: cellAddress,
        isEditable: cellEditable,
        dataRowIndex: rowIndex
      });

      console.log(`📝 Mapping ${column.key} Row ${rowIndex}: ${cellAddress} (${cellEditable ? 'Editable' : 'ReadOnly'})`);
    });

    // 📋 LIST 타입 드롭다운 설정 (편집 가능한 행이 있는 경우만)
    if (column.type === "LIST" && column.options) {
      const hasEditableRows = tableData.some((rowData) => isFieldEditable(column.key, rowData));
      if (hasEditableRows) {
        const cellPos = { row: dataStartRow, col: targetCol };
        setupOptimizedListValidation(activeSheet, cellPos, column.options, dataRowCount);
        console.log(`📋 Dropdown set for ${column.key}: ${hasEditableRows ? 'Has editable rows' : 'All readonly'}`);
      }
    }
  });

  // 🎨 개별 셀 데이터 및 스타일 설정 (SPREAD_LIST와 동일한 방식)
  tableData.forEach((rowData, rowIndex) => {
    const targetRow = dataStartRow + rowIndex;
    
    visibleColumns.forEach((column, colIndex) => {
      const targetCol = startCol + colIndex;
      const cell = activeSheet.getCell(targetRow, targetCol);
      const value = rowData[column.key];

      // 값 설정
      cell.value(value ?? null);

      // 🛡️ 편집 권한 및 스타일 재확인 (SPREAD_LIST와 동일)
      const cellEditable = isFieldEditable(column.key, rowData);
      cell.locked(!cellEditable);
      const style = createCellStyle(cellEditable);
      activeSheet.setStyle(targetRow, targetCol, style);

      // 🔍 디버깅: readonly 상태 로깅
      if (!cellEditable) {
        const columnConfig = columnsJSON.find(col => col.key === column.key);
        const reasons = [];
        
        if (columnConfig?.shi === true) {
          reasons.push('column.shi=true');
        }
        if (rowData.shi === true) {
          reasons.push('row.shi=true');
        }
        if (!editableFields.includes(column.key) && column.key !== "TAG_NO" && column.key !== "TAG_DESC") {
          reasons.push('not in editableFields');
        }
        
        console.log(`🔒 ReadOnly [${targetRow}, ${targetCol}] ${column.key}: ${reasons.join(', ')}`);
      }
    });
  });

  // 🎨 컬럼 너비 자동 설정
  setOptimalColumnWidths(activeSheet, visibleColumns, startCol, tableData);

  console.log(`🏗️ GRD_LIST table created with ${mappings.length} mappings, hasGroups: ${hasGroups}`);
  console.log(`📊 Readonly analysis:`);
  console.log(`   Total cells: ${mappings.length}`);
  console.log(`   Editable cells: ${mappings.filter(m => m.isEditable).length}`);
  console.log(`   Readonly cells: ${mappings.filter(m => !m.isEditable).length}`);
  
  return mappings;
}, [tableData, columnsJSON, isFieldEditable, createCellStyle, ensureRowCapacity, ensureColumnCapacity, setupOptimizedListValidation, setOptimalColumnWidths, editableFields, getCellAddress, analyzeColumnGroups]);

// 🛡️ 추가: readonly 상태 확인 헬퍼 함수
const analyzeReadonlyStatus = React.useCallback((column: DataTableColumnJSON, rowData: GenericData) => {
  const reasons: string[] = [];
  
  // 1. 컬럼 자체가 readonly인지 확인
  if (column.shi === true) {
    reasons.push('Column marked as readonly (shi=true)');
  }
  
  // 2. 행 자체가 readonly인지 확인
  if (rowData.shi === true) {
    reasons.push('Row marked as readonly (shi=true)');
  }
  
  // 3. editableFields에 포함되지 않은 경우
  if (!editableFields.includes(column.key) && column.key !== "TAG_NO" && column.key !== "TAG_DESC") {
    reasons.push('Not in editable fields list');
  }
  
  // 4. 특수 필드 체크
  if (column.key === "TAG_NO" || column.key === "TAG_DESC") {
    // TAG_NO와 TAG_DESC는 기본 편집 가능하지만 다른 조건들은 적용됨
    if (column.shi === true || rowData.shi === true) {
      // 다른 readonly 조건이 있으면 적용
    } else {
      return { isEditable: true, reasons: ['Default editable field'] };
    }
  }
  
  const isEditable = reasons.length === 0;
  
  return {
    isEditable,
    reasons: isEditable ? ['Editable'] : reasons
  };
}, [editableFields]);



// 🛡️ 수정된 시트 보호 및 이벤트 설정 함수
const setupSheetProtectionAndEvents = React.useCallback((activeSheet: any, mappings: CellMapping[]) => {
  console.log(`🛡️ Setting up protection and events for ${mappings.length} mappings`);

  // 🔧 1단계: 먼저 시트 보호를 완전히 해제하고 강력한 잠금 해제 실행
  console.log('🔓 Step 1: Forcing unlock all editable cells...');
  activeSheet.options.isProtected = false;

  // 🔧 2단계: 모든 편집 가능한 셀에 대해 강제 잠금 해제 및 CellType 설정
  mappings.forEach((mapping, index) => {
    if (!mapping.isEditable) return;
    
    const cellPos = parseCellAddress(mapping.cellAddress);
    if (!cellPos) return;
    
    try {
      const cell = activeSheet.getCell(cellPos.row, cellPos.col);
      const columnConfig = columnsJSON.find(col => col.key === mapping.attId);
      
      // 강제 잠금 해제
      cell.locked(false);
      
      // CellType 명시적 설정
      if (columnConfig?.type === "LIST" && columnConfig.options) {
        // LIST 타입: ComboBox 설정
        const comboBox = new GC.Spread.Sheets.CellTypes.ComboBox();
        comboBox.items(columnConfig.options);
        comboBox.editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.text);
        activeSheet.setCellType(cellPos.row, cellPos.col, comboBox);
        console.log(`📋 ComboBox set for ${mapping.attId} at ${mapping.cellAddress}`);
      } else {
        // 다른 모든 타입: 기본 텍스트 편집기 설정
        const textCellType = new GC.Spread.Sheets.CellTypes.Text();
        activeSheet.setCellType(cellPos.row, cellPos.col, textCellType);
        console.log(`📝 Text editor set for ${mapping.attId} at ${mapping.cellAddress}`);
        
        // NUMBER 타입인 경우에만 validation 추가 (편집은 가능하게)
        if (columnConfig?.type === "NUMBER") {
          const numberValidator = GC.Spread.Sheets.DataValidation.createNumberValidator(
            GC.Spread.Sheets.ConditionalFormatting.ComparisonOperators.between,
            -999999999, 999999999, true
          );
          numberValidator.showInputMessage(false);
          numberValidator.showErrorMessage(false);
          activeSheet.setDataValidator(cellPos.row, cellPos.col, numberValidator);
        }
      }
      
      // 편집 가능 스타일 명확히 표시
      const editableStyle = createCellStyle(true);
      activeSheet.setStyle(cellPos.row, cellPos.col, editableStyle);
      
      console.log(`🔓 Forced unlock: ${mapping.attId} at ${mapping.cellAddress}`);
      
    } catch (error) {
      console.error(`❌ Error processing cell ${mapping.cellAddress}:`, error);
    }
  });

  // 🔧 3단계: 시트 보호 재설정 (편집 허용하는 설정으로)
  activeSheet.options.isProtected = true;
  activeSheet.options.protectionOptions = {
    allowSelectLockedCells: true,
    allowSelectUnlockedCells: true,
    allowSort: false,
    allowFilter: false,
    allowEditObjects: true,        // ✅ 편집 객체 허용
    allowResizeRows: false,
    allowResizeColumns: false,
    allowFormatCells: false,
    allowInsertRows: false,
    allowInsertColumns: false,
    allowDeleteRows: false,
    allowDeleteColumns: false
  };

  // 🔧 4단계: 편집 테스트 실행
  console.log('🧪 Testing cell editability...');
  const editableMapping = mappings.find(m => m.isEditable);
  if (editableMapping) {
    const cellPos = parseCellAddress(editableMapping.cellAddress);
    if (cellPos) {
      try {
        const cell = activeSheet.getCell(cellPos.row, cellPos.col);
        const testValue = 'TEST_' + Math.random().toString(36).substr(2, 5);
        const originalValue = cell.value();
        
        console.log(`🧪 Testing ${editableMapping.attId} at ${editableMapping.cellAddress}`);
        console.log(`🧪 Locked status: ${cell.locked()}`);
        
        // 직접 값 설정 테스트
        cell.value(testValue);
        const newValue = cell.value();
        
        if (newValue === testValue) {
          console.log('✅ Cell edit test PASSED');
          cell.value(originalValue); // 원래 값 복원
        } else {
          console.log(`❌ Cell edit test FAILED: ${newValue} !== ${testValue}`);
        }
      } catch (testError) {
        console.error('❌ Edit test error:', testError);
      }
    }
  }

  // 🎯 변경 감지 이벤트
  const changeEvents = [
    GC.Spread.Sheets.Events.CellChanged,
    GC.Spread.Sheets.Events.ValueChanged,
    GC.Spread.Sheets.Events.ClipboardPasted
  ];

  changeEvents.forEach(eventType => {
    activeSheet.bind(eventType, () => {
      console.log(`📝 ${eventType} detected`);
      setHasChanges(true);
    });
  });

  // 🚫 편집 시작 권한 확인 (수정됨)
  activeSheet.bind(GC.Spread.Sheets.Events.EditStarting, (event: any, info: any) => {
    console.log(`🎯 EditStarting: Row ${info.row}, Col ${info.col}`);

    // ✅ 정확한 매핑 찾기 (행/열 정확히 일치)
    const exactMapping = mappings.find(m => {
      const cellPos = parseCellAddress(m.cellAddress);
      return cellPos && cellPos.row === info.row && cellPos.col === info.col;
    });

    if (!exactMapping) {
      console.log(`ℹ️ No mapping found for [${info.row}, ${info.col}] - allowing edit`);
      return; // 매핑이 없으면 허용 (템플릿 영역 밖)
    }

    console.log(`📋 Found mapping: ${exactMapping.attId} at ${exactMapping.cellAddress}, isEditable: ${exactMapping.isEditable}`);

    // 🔍 추가 디버깅: 셀의 실제 상태 확인
    const cell = activeSheet.getCell(info.row, info.col);
    const isLocked = cell.locked();
    const cellValue = cell.value();
    
    console.log(`🔍 Cell state check:`, {
      attId: exactMapping.attId,
      isEditable: exactMapping.isEditable,
      isLocked: isLocked,
      currentValue: cellValue
    });

    // 🔧 추가: EditStarting 시점에서도 강제 잠금 해제 재시도
    if (exactMapping.isEditable && isLocked) {
      console.log(`🔓 Re-unlocking cell during EditStarting...`);
      cell.locked(false);
      
      // CellType도 재설정
      const columnConfig = columnsJSON.find(col => col.key === exactMapping.attId);
      if (columnConfig?.type !== "LIST") {
        const textCellType = new GC.Spread.Sheets.CellTypes.Text();
        activeSheet.setCellType(info.row, info.col, textCellType);
      }
    }

    // 기본 편집 권한 확인
    if (!exactMapping.isEditable) {
      console.log(`🚫 Field ${exactMapping.attId} is not editable`);
      toast.warning(`${exactMapping.attId} field is read-only`);
      info.cancel = true;
      return;
    }

    // SPREAD_LIST 또는 GRD_LIST 개별 행 SHI 확인
    if ((templateType === 'SPREAD_LIST' || templateType === 'GRD_LIST') && exactMapping.dataRowIndex !== undefined) {
      const dataRowIndex = exactMapping.dataRowIndex;

      console.log(`🔍 Checking SHI for data row ${dataRowIndex}`);

      if (dataRowIndex >= 0 && dataRowIndex < tableData.length) {
        const rowData = tableData[dataRowIndex];
        if (rowData?.shi === true) {
          console.log(`🚫 Row ${dataRowIndex} is in SHI mode`);
          toast.warning(`Row ${dataRowIndex + 1}: ${exactMapping.attId} field is read-only (SHI mode)`);
          info.cancel = true;
          return;
        }
      } else {
        console.warn(`⚠️ Invalid dataRowIndex: ${dataRowIndex} (tableData.length: ${tableData.length})`);
      }
    }

    console.log(`✅ Edit allowed for ${exactMapping.attId}`);
  });

  // ✅ 편집 완료 검증 (기존 로직 유지)
  activeSheet.bind(GC.Spread.Sheets.Events.EditEnded, (event: any, info: any) => {
    console.log(`🏁 EditEnded: Row ${info.row}, Col ${info.col}, New value: ${activeSheet.getValue(info.row, info.col)}`);

    // ✅ 정확한 매핑 찾기
    const exactMapping = mappings.find(m => {
      const cellPos = parseCellAddress(m.cellAddress);
      return cellPos && cellPos.row === info.row && cellPos.col === info.col;
    });

    if (!exactMapping) {
      console.log(`ℹ️ No mapping found for [${info.row}, ${info.col}] - skipping validation`);
      return;
    }

    const columnConfig = columnsJSON.find(col => col.key === exactMapping.attId);
    if (columnConfig) {
      const cellValue = activeSheet.getValue(info.row, info.col);
      console.log(`🔍 Validating ${exactMapping.attId}: "${cellValue}"`);

      const errorMessage = validateCellValue(cellValue, columnConfig.type, columnConfig.options);
      const cell = activeSheet.getCell(info.row, info.col);

      if (errorMessage) {
        console.log(`❌ Validation failed: ${errorMessage}`);

        // 🚨 에러 스타일 적용 (편집 가능 상태 유지)
        const errorStyle = new GC.Spread.Sheets.Style();
        errorStyle.backColor = "#fef2f2";
        errorStyle.foreColor = "#dc2626";
        errorStyle.borderLeft = new GC.Spread.Sheets.LineBorder("#dc2626", GC.Spread.Sheets.LineStyle.thick);
        errorStyle.borderRight = new GC.Spread.Sheets.LineBorder("#dc2626", GC.Spread.Sheets.LineStyle.thick);
        errorStyle.borderTop = new GC.Spread.Sheets.LineBorder("#dc2626", GC.Spread.Sheets.LineStyle.thick);
        errorStyle.borderBottom = new GC.Spread.Sheets.LineBorder("#dc2626", GC.Spread.Sheets.LineStyle.thick);

        activeSheet.setStyle(info.row, info.col, errorStyle);
        cell.locked(!exactMapping.isEditable); // 편집 가능 상태 유지

        toast.warning(`Invalid value in ${exactMapping.attId}: ${errorMessage}. Please correct the value.`, { duration: 5000 });
      } else {
        console.log(`✅ Validation passed`);

        // ✅ 정상 스타일 복원
        const normalStyle = createCellStyle(exactMapping.isEditable);
        activeSheet.setStyle(info.row, info.col, normalStyle);
        cell.locked(!exactMapping.isEditable);
      }
    }

    // 🔄 변경 상태 업데이트
    setHasChanges(true);
  });

  // 🔧 5단계: 설정 완료 후 1초 뒤에 추가 잠금 해제 실행 (안전장치)
  setTimeout(() => {
    console.log('🔄 Running safety unlock after 1 second...');
    mappings.forEach(mapping => {
      if (!mapping.isEditable) return;
      
      const cellPos = parseCellAddress(mapping.cellAddress);
      if (!cellPos) return;
      
      try {
        const cell = activeSheet.getCell(cellPos.row, cellPos.col);
        if (cell.locked()) {
          console.log(`🔓 Safety unlock: ${mapping.attId}`);
          cell.locked(false);
        }
      } catch (error) {
        console.error(`❌ Safety unlock error for ${mapping.cellAddress}:`, error);
      }
    });
  }, 1000);

  console.log(`🛡️ Protection and events configured for ${mappings.length} mappings`);
  console.log(`🔓 Editable cells: ${mappings.filter(m => m.isEditable).length}`);
  console.log(`🔒 Readonly cells: ${mappings.filter(m => !m.isEditable).length}`);
}, [templateType, tableData, createCellStyle, validateCellValue, columnsJSON]);

// 🔧 셀 타입 및 편집기 설정 함수 (initSpread 함수 내부에 추가)
const setupCellTypeAndEditor = React.useCallback((activeSheet: any, cellPos: { row: number, col: number }, columnConfig: DataTableColumnJSON, isEditable: boolean, rowCount: number = 1) => {
  console.log(`🔧 Setting up cell type for ${columnConfig.key} (${columnConfig.type}) at [${cellPos.row}, ${cellPos.col}]`);
  
  try {
    // 편집 가능한 셀에만 적절한 셀 타입 설정
    if (isEditable) {
      for (let i = 0; i < rowCount; i++) {
        const targetRow = cellPos.row + i;
        const cell = activeSheet.getCell(targetRow, cellPos.col);
        
        // 셀 잠금 해제
        cell.locked(false);
        
        switch (columnConfig.type) {
          case "LIST":
            // 드롭다운은 기존 setupOptimizedListValidation 함수에서 처리
            break;
            
          case "NUMBER":
            // 숫자 입력용 셀 타입 설정
            const numberCellType = new GC.Spread.Sheets.CellTypes.Text();
            activeSheet.setCellType(targetRow, cellPos.col, numberCellType);
            
            // 숫자 validation 설정 (선택사항)
            const numberValidator = GC.Spread.Sheets.DataValidation.createNumberValidator(
              GC.Spread.Sheets.ConditionalFormatting.ComparisonOperators.between,
              -999999999, 999999999, true
            );
            numberValidator.showInputMessage(true);
            numberValidator.inputTitle("Number Input");
            numberValidator.inputMessage("Please enter a valid number");
            activeSheet.setDataValidator(targetRow, cellPos.col, numberValidator);
            break;
            
          case "STRING":
          default:
            // 기본 텍스트 입력용 셀 타입 설정
            const textCellType = new GC.Spread.Sheets.CellTypes.Text();
            activeSheet.setCellType(targetRow, cellPos.col, textCellType);
            break;
        }
        
        console.log(`✅ Cell type set for [${targetRow}, ${cellPos.col}]: ${columnConfig.type}`);
      }
    } else {
      // 읽기 전용 셀 설정
      for (let i = 0; i < rowCount; i++) {
        const targetRow = cellPos.row + i;
        const cell = activeSheet.getCell(targetRow, cellPos.col);
        cell.locked(true);
      }
    }
    
  } catch (error) {
    console.error(`❌ Error setting cell type for ${columnConfig.key}:`, error);
  }
}, []);

  // ═══════════════════════════════════════════════════════════════════════════════
  // 🏗️ 메인 SpreadSheets 초기화 함수
  // ═══════════════════════════════════════════════════════════════════════════════

// 🛡️ 수정된 initSpread 함수 - activeSheet 참조 문제 해결
const initSpread = React.useCallback((spread: any, template?: TemplateItem) => {
  const workingTemplate = template || selectedTemplate;
  if (!spread || !workingTemplate) {
    console.error('❌ Invalid spread or template in initSpread');
    return;
  }

  try {
    // 🔄 초기 설정
    setCurrentSpread(spread);
    setHasChanges(false);
    setValidationErrors([]);

    // 성능을 위한 렌더링 일시 중단
    spread.suspendPaint();

    try {
      // ⚠️ 초기 activeSheet 가져오기
      let activeSheet = getSafeActiveSheet(spread, 'initSpread-initial');
      if (!activeSheet) {
        throw new Error('Failed to get initial activeSheet');
      }

      // 시트 보호 해제 (편집을 위해)
      activeSheet.options.isProtected = false;

      let mappings: CellMapping[] = [];

      // 🆕 GRD_LIST 처리
      if (templateType === 'GRD_LIST' && workingTemplate.GRD_LST_SETUP) {
        console.log('🏗️ Processing GRD_LIST template');

        // 기본 워크북 설정
        spread.clearSheets();
        spread.addSheet(0);
        const sheet = spread.getSheet(0);
        sheet.name('Data');
        spread.setActiveSheet('Data');

        // 동적 테이블 생성
        mappings = createGrdListTable(sheet, workingTemplate);

      } else {
        // 🔍 SPREAD_LIST 및 SPREAD_ITEM 처리
        let contentJson = null;
        let dataSheets = null;

        // SPR_LST_SETUP.CONTENT 우선 사용
        if (workingTemplate.SPR_LST_SETUP?.CONTENT) {
          contentJson = workingTemplate.SPR_LST_SETUP.CONTENT;
          dataSheets = workingTemplate.SPR_LST_SETUP.DATA_SHEETS;
          console.log('✅ Using SPR_LST_SETUP for template:', workingTemplate.NAME);
        }
        // SPR_ITM_LST_SETUP.CONTENT 대안 사용
        else if (workingTemplate.SPR_ITM_LST_SETUP?.CONTENT) {
          contentJson = workingTemplate.SPR_ITM_LST_SETUP.CONTENT;
          dataSheets = workingTemplate.SPR_ITM_LST_SETUP.DATA_SHEETS;
          console.log('✅ Using SPR_ITM_LST_SETUP for template:', workingTemplate.NAME);
        }

        if (!contentJson) {
          throw new Error(`No template content found for ${workingTemplate.NAME}`);
        }

        if (!dataSheets || dataSheets.length === 0) {
          throw new Error(`No data sheets configuration found for ${workingTemplate.NAME}`);
        }

        console.log('🔍 Template info:', {
          templateName: workingTemplate.NAME,
          templateType: templateType,
          dataSheetsCount: dataSheets.length,
          hasSelectedRow: !!selectedRow,
          tableDataLength: tableData.length
        });

        // 🏗️ SpreadSheets 템플릿 로드
        const jsonData = typeof contentJson === 'string' ? JSON.parse(contentJson) : contentJson;
        
        console.log('📥 Loading template JSON...');
        spread.fromJSON(jsonData);
        console.log('✅ Template JSON loaded');

        // ⚠️ 중요: 템플릿 로드 후 activeSheet 다시 가져오기
        activeSheet = getSafeActiveSheet(spread, 'initSpread-after-fromJSON');
        if (!activeSheet) {
          throw new Error('ActiveSheet became null after loading template');
        }

        console.log('🔍 Active sheet after template load:', {
          name: activeSheet.name?.() || 'unnamed',
          rowCount: activeSheet.getRowCount(),
          colCount: activeSheet.getColumnCount()
        });

        // 시트 보호 다시 해제 (템플릿 로드 후 다시 설정될 수 있음)
        activeSheet.options.isProtected = false;

        // 📊 데이터 매핑 및 로딩 처리
        console.log(`🔄 Processing ${dataSheets.length} data sheets`);

        dataSheets.forEach((dataSheet, sheetIndex) => {
          console.log(`📋 Processing data sheet ${sheetIndex}:`, {
            sheetName: dataSheet.SHEET_NAME,
            mappingCount: dataSheet.MAP_CELL_ATT?.length || 0
          });

          if (dataSheet.MAP_CELL_ATT && dataSheet.MAP_CELL_ATT.length > 0) {
            dataSheet.MAP_CELL_ATT.forEach((mapping, mappingIndex) => {
              const { ATT_ID, IN } = mapping;

              if (!ATT_ID || !IN || IN.trim() === "") {
                console.warn(`⚠️ Invalid mapping: ATT_ID=${ATT_ID}, IN=${IN}`);
                return;
              }

              const cellPos = parseCellAddress(IN);
              if (!cellPos) {
                console.warn(`⚠️ Invalid cell address: ${IN}`);
                return;
              }

              const columnConfig = columnsJSON.find(col => col.key === ATT_ID);

              // 🎯 템플릿 타입별 데이터 처리
              if (templateType === 'SPREAD_ITEM' && selectedRow) {
                console.log(`📝 Processing SPREAD_ITEM for ${ATT_ID}`);
                
                const isEditable = isFieldEditable(ATT_ID);
                const value = selectedRow[ATT_ID];
              
                // 매핑 정보 저장
                mappings.push({
                  attId: ATT_ID,
                  cellAddress: IN,
                  isEditable: isEditable,
                  dataRowIndex: 0
                });
              
                // ⚠️ 안전한 셀 참조 및 값 설정
                try {
                  const cell = activeSheet.getCell(cellPos.row, cellPos.col);
                  console.log(`🔄 Setting SPREAD_ITEM cell [${cellPos.row}, ${cellPos.col}] ${ATT_ID}: "${value}"`);
                  
                  // 🔧 새로 추가: 셀 타입 및 편집기 설정
                  setupCellTypeAndEditor(activeSheet, cellPos, columnConfig, isEditable, 1);
                  
                  // 값 설정
                  cell.value(value ?? null);
                  
                  // 스타일 설정
                  const style = createCellStyle(isEditable);
                  activeSheet.setStyle(cellPos.row, cellPos.col, style);
              
                  // LIST 타입 드롭다운 설정 (기존 코드 유지)
                  if (columnConfig?.type === "LIST" && columnConfig.options && isEditable) {
                    setupOptimizedListValidation(activeSheet, cellPos, columnConfig.options, 1);
                  }
                  
                  console.log(`✅ SPREAD_ITEM cell set successfully`);
                } catch (cellError) {
                  console.error(`❌ Error setting SPREAD_ITEM cell:`, cellError);
                }
              } else if (templateType === 'SPREAD_LIST' && tableData.length > 0) {
                console.log(`📊 Processing SPREAD_LIST for ${ATT_ID} with ${tableData.length} rows`);
                
                // 🚀 행 확장 - 안전한 방법으로
                const requiredRows = cellPos.row + tableData.length;
                console.log(`🚀 Ensuring ${requiredRows} rows for SPREAD_LIST`);
                
                // ⚠️ activeSheet 유효성 재검증
                const currentActiveSheet = getSafeActiveSheet(spread, 'ensureRowCapacity');
                if (!currentActiveSheet) {
                  console.error(`❌ ActiveSheet is null before ensureRowCapacity`);
                  return;
                }
                
                if (!ensureRowCapacity(currentActiveSheet, requiredRows)) {
                  console.error(`❌ Failed to ensure row capacity for ${requiredRows} rows`);
                  return;
                }

                // activeSheet 참조 업데이트
                activeSheet = currentActiveSheet;

                // 매핑 생성
                tableData.forEach((rowData, index) => {
                  const targetRow = cellPos.row + index;
                  const targetCellAddress = getCellAddress(targetRow, cellPos.col);
                  const cellEditable = isFieldEditable(ATT_ID, rowData);

                  mappings.push({
                    attId: ATT_ID,
                    cellAddress: targetCellAddress,
                    isEditable: cellEditable,
                    dataRowIndex: index
                  });
                });

                // LIST 타입 드롭다운 설정
                if (columnConfig?.type === "LIST" && columnConfig.options) {
                  const hasEditableRows = tableData.some((rowData) => isFieldEditable(ATT_ID, rowData));
                  if (hasEditableRows) {
                    setupOptimizedListValidation(activeSheet, cellPos, columnConfig.options, tableData.length);
                  }
                }
// 개별 셀 데이터 및 스타일 설정
tableData.forEach((rowData, index) => {
  const targetRow = cellPos.row + index;
  
  try {
    const cell = activeSheet.getCell(targetRow, cellPos.col);
    const value = rowData[ATT_ID];
    const cellEditable = isFieldEditable(ATT_ID, rowData);

    console.log(`🔄 Setting SPREAD_LIST Row ${index} ${ATT_ID}: "${value}"`);
    
    // 🔧 새로 추가: 각 셀에 대한 타입 및 편집기 설정
    setupCellTypeAndEditor(activeSheet, { row: targetRow, col: cellPos.col }, columnConfig, cellEditable, 1);
    
    // 값 설정
    cell.value(value ?? null);

    // 스타일 설정
    const style = createCellStyle(cellEditable);
    activeSheet.setStyle(targetRow, cellPos.col, style);
    
  } catch (cellError) {
    console.error(`❌ Error setting SPREAD_LIST cell Row ${index}:`, cellError);
  }
});


                console.log(`✅ SPREAD_LIST processing completed for ${ATT_ID}`);
              }
            });
          }
        });
      }

      // 💾 매핑 정보 저장 및 이벤트 설정
      setCellMappings(mappings);
      
      // ⚠️ 최종 activeSheet 재확인 후 이벤트 설정
      const finalActiveSheet = getSafeActiveSheet(spread, 'setupSheetProtectionAndEvents');
      if (finalActiveSheet) {
        setupSheetProtectionAndEvents(finalActiveSheet, mappings);
      } else {
        console.error('❌ Failed to get activeSheet for events setup');
      }

      console.log(`✅ Template initialization completed with ${mappings.length} mappings`);

    } finally {
      // 렌더링 재개
      spread.resumePaint();
    }

  } catch (error) {
    console.error('❌ Error initializing spread:', error);
    // toast.error(`Failed to load template: ${error.message}`);
    if (spread?.resumePaint) {
      spread.resumePaint();
    }
  }
}, [selectedTemplate, templateType, selectedRow, tableData, isFieldEditable, columnsJSON, createCellStyle, setupOptimizedListValidation, ensureRowCapacity, setupSheetProtectionAndEvents, createGrdListTable, getCellAddress, getSafeActiveSheet, validateActiveSheet]);
  // 변경사항 저장 함수
  const handleSaveChanges = React.useCallback(async () => {
    if (!currentSpread || !hasChanges) {
      toast.info("No changes to save");
      return;
    }

    // 저장 전 데이터 검증
    const errors = validateAllData();
    if (errors.length > 0) {
      toast.error(`Cannot save: ${errors.length} validation errors found. Please fix them first.`);
      return;
    }

    try {
      setIsPending(true);

      const activeSheet = currentSpread.getActiveSheet();

      if (templateType === 'SPREAD_ITEM' && selectedRow) {
        // 단일 행 저장
        const dataToSave = { ...selectedRow };

        cellMappings.forEach(mapping => {
          if (mapping.isEditable) {
            const cellPos = parseCellAddress(mapping.cellAddress);
            if (cellPos) {
              const cellValue = activeSheet.getValue(cellPos.row, cellPos.col);
              dataToSave[mapping.attId] = cellValue;
            }
          }
        });

        dataToSave.TAG_NO = selectedRow.TAG_NO;

        const { success, message } = await updateFormDataInDB(
          formCode,
          contractItemId,
          dataToSave
        );

        if (!success) {
          toast.error(message);
          return;
        }

        toast.success("Changes saved successfully!");
        onUpdateSuccess?.(dataToSave);

      } else if ((templateType === 'SPREAD_LIST' || templateType === 'GRD_LIST') && tableData.length > 0) {
        // 복수 행 저장 (SPREAD_LIST와 GRD_LIST 동일 처리)
        const updatedRows: GenericData[] = [];
        let saveCount = 0;

        for (let i = 0; i < tableData.length; i++) {
          const originalRow = tableData[i];
          const dataToSave = { ...originalRow };
          let hasRowChanges = false;

          // 각 매핑에 대해 해당 행의 값 확인
          cellMappings.forEach(mapping => {
            if (mapping.dataRowIndex === i && mapping.isEditable) {
              const columnConfig = columnsJSON.find(col => col.key === mapping.attId);
              const isColumnEditable = columnConfig?.shi !== true;
              const isRowEditable = originalRow.shi !== true;

              if (isColumnEditable && isRowEditable) {
                const cellPos = parseCellAddress(mapping.cellAddress);
                if (cellPos) {
                  const cellValue = activeSheet.getValue(cellPos.row, cellPos.col);

                  // 값이 변경되었는지 확인
                  if (cellValue !== originalRow[mapping.attId]) {
                    dataToSave[mapping.attId] = cellValue;
                    hasRowChanges = true;
                  }
                }
              }
            }
          });

          // 변경사항이 있는 행만 저장
          if (hasRowChanges) {
            dataToSave.TAG_NO = originalRow.TAG_NO; // TAG_NO는 절대 변경되지 않도록

            const { success } = await updateFormDataInDB(
              formCode,
              contractItemId,
              dataToSave
            );

            if (success) {
              updatedRows.push(dataToSave);
              saveCount++;
            }
          } else {
            updatedRows.push(originalRow); // 변경사항이 없으면 원본 유지
          }
        }

        if (saveCount > 0) {
          toast.success(`${saveCount} rows saved successfully!`);
          onUpdateSuccess?.(updatedRows);
        } else {
          toast.info("No changes to save");
        }
      }

      setHasChanges(false);
      setValidationErrors([]);

    } catch (error) {
      console.error("Error saving changes:", error);
      toast.error("An unexpected error occurred while saving");
    } finally {
      setIsPending(false);
    }
  }, [currentSpread, hasChanges, templateType, selectedRow, tableData, formCode, contractItemId, onUpdateSuccess, cellMappings, columnsJSON, validateAllData]);

  if (!isOpen) return null;

  // 데이터 유효성 검사
  const isDataValid = templateType === 'SPREAD_ITEM' ? !!selectedRow : tableData.length > 0;
  const dataCount = templateType === 'SPREAD_ITEM' ? 1 : tableData.length;
  

  return (
    <Dialog open={isOpen} onOpenChange={onClose}>
      <DialogContent
        className="w-[80%] max-w-none h-[80vh] flex flex-col"
        style={{ maxWidth: "80vw" }}
      >
        <DialogHeader className="flex-shrink-0">
          <DialogTitle>SEDP Template - {formCode}</DialogTitle>
          <DialogDescription>
            <div className="space-y-3">
              {/* 템플릿 선택 */}
              {availableTemplates.length > 1 && (
                <div className="flex items-center gap-4">
                  <span className="text-sm font-medium">Template:</span>
                  <Select value={selectedTemplateId} onValueChange={handleTemplateChange}>
                    <SelectTrigger className="w-64">
                      <SelectValue placeholder="Select a template" />
                    </SelectTrigger>
                    <SelectContent>
                      {availableTemplates.map(template => (
                        <SelectItem key={template.TMPL_ID} value={template.TMPL_ID}>
                          {template.NAME} ({
                           template.TMPL_TYPE
                          })
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
              )}

              {/* 템플릿 정보 */}
              {selectedTemplate && (
                <div className="flex items-center gap-4 text-sm">
                  <span className="font-medium text-blue-600">
                    Template Type: {
                      templateType === 'SPREAD_LIST' ? 'List View (SPREAD_LIST)' :
                        templateType === 'SPREAD_ITEM' ? 'Item View (SPREAD_ITEM)' :
                          'Grid List View (GRD_LIST)'
                    }
                  </span>
                  {templateType === 'SPREAD_ITEM' && selectedRow && (
                    <span>• Selected TAG_NO: {selectedRow.TAG_NO || 'N/A'}</span>
                  )}
                  {(templateType === 'SPREAD_LIST' || templateType === 'GRD_LIST') && (
                    <span>• {dataCount} rows</span>
                  )}
                  {hasChanges && (
                    <span className="text-orange-600 font-medium">
                      • Unsaved changes
                    </span>
                  )}
                  {validationErrors.length > 0 && (
                    <span className="text-red-600 font-medium flex items-center">
                      <AlertTriangle className="w-4 h-4 mr-1" />
                      {validationErrors.length} validation errors
                    </span>
                  )}
                </div>
              )}

              {/* 범례 */}
              <div className="flex items-center gap-4 text-xs">
                <span className="text-muted-foreground">
                  <span className="inline-block w-3 h-3 bg-green-100 border border-green-400 mr-1"></span>
                  Editable fields
                </span>
                <span className="text-muted-foreground">
                  <span className="inline-block w-3 h-3 bg-gray-100 border border-gray-300 mr-1"></span>
                  Read-only fields
                </span>
                <span className="text-muted-foreground">
                  <span className="inline-block w-3 h-3 bg-red-100 border border-red-300 mr-1"></span>
                  Validation errors
                </span>
                {cellMappings.length > 0 && (
                  <span className="text-blue-600">
                    {editableFieldsCount} of {cellMappings.length} fields editable
                  </span>
                )}
              </div>
            </div>
          </DialogDescription>
        </DialogHeader>

        {/* SpreadSheets 컴포넌트 영역 */}
        <div className="flex-1 overflow-hidden">
          {selectedTemplate && isClient && isDataValid ? (
            <SpreadSheets
              key={`${templateType}-${selectedTemplate.TMPL_ID}-${selectedTemplateId}`}
              workbookInitialized={initSpread}
              hostStyle={hostStyle}
            />
          ) : (
            <div className="flex items-center justify-center h-full text-muted-foreground">
              {!isClient ? (
                <>
                  <Loader className="mr-2 h-4 w-4 animate-spin" />
                  Loading...
                </>
              ) : !selectedTemplate ? (
                "No template available"
              ) : !isDataValid ? (
                `No ${templateType === 'SPREAD_ITEM' ? 'selected row' : 'data'} available`
              ) : (
                "Template not ready"
              )}
            </div>
          )}
        </div>

        <DialogFooter className="flex-shrink-0">
          <div className="flex items-center gap-2">
            <Button variant="outline" onClick={onClose}>
              Close
            </Button>

            {hasChanges && (
              <Button
                variant="default"
                onClick={handleSaveChanges}
                disabled={isPending || validationErrors.length > 0}
              >
                {isPending ? (
                  <>
                    <Loader className="mr-2 h-4 w-4 animate-spin" />
                    Saving...
                  </>
                ) : (
                  <>
                    <Save className="mr-2 h-4 w-4" />
                    Save Changes
                  </>
                )}
              </Button>
            )}

            {validationErrors.length > 0 && (
              <Button
                variant="outline"
                onClick={validateAllData}
                className="text-red-600 border-red-300 hover:bg-red-50"
              >
                <AlertTriangle className="mr-2 h-4 w-4" />
                Check Errors ({validationErrors.length})
              </Button>
            )}
          </div>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}