"use client";

import React, { useState, useRef, useEffect, useCallback } from "react";
import { cn } from "@/lib/utils";

interface EditableSpreadsheetProps {
  columns: string[];
  data: Record<string, any>[];
  onColumnsChange: (columns: string[]) => void;
  onDataChange: (data: Record<string, any>[]) => void;
  maxHeight?: string;
}

// 셀 범위 정의
interface CellRange {
  startRow: number;
  startCol: number;
  endRow: number;
  endCol: number;
}

/**
 * 엑셀처럼 편집 가능한 스프레드시트 컴포넌트
 * - 셀 클릭으로 편집
 * - Tab/Enter로 다음 셀 이동
 * - 마지막 행/열에서 자동 추가
 * - 헤더(컬럼명)도 편집 가능
 * - 다중 셀 선택 (드래그)
 * - 자동 채우기 (드래그 핸들) - 다중 셀 지원
 */
export const EditableSpreadsheet: React.FC<EditableSpreadsheetProps> = ({
  columns,
  data,
  onColumnsChange,
  onDataChange,
  maxHeight = "350px",
}) => {
  // 현재 편집 중인 셀 (row: -1은 헤더)
  const [editingCell, setEditingCell] = useState<{
    row: number;
    col: number;
  } | null>(null);
  const [editValue, setEditValue] = useState<string>("");
  
  // 선택 범위 (다중 셀 선택)
  const [selection, setSelection] = useState<CellRange | null>(null);
  
  // 셀 선택 드래그 중
  const [isDraggingSelection, setIsDraggingSelection] = useState(false);
  
  // 자동 채우기 드래그 상태
  const [isDraggingFill, setIsDraggingFill] = useState(false);
  const [fillPreviewEnd, setFillPreviewEnd] = useState<number | null>(null);
  
  // 복사된 범위 (점선 애니메이션 표시용)
  const [copiedRange, setCopiedRange] = useState<CellRange | null>(null);
  
  // Undo/Redo 히스토리
  interface HistoryState {
    columns: string[];
    data: Record<string, any>[];
  }
  const [history, setHistory] = useState<HistoryState[]>([]);
  const [historyIndex, setHistoryIndex] = useState(-1);
  const [isUndoRedo, setIsUndoRedo] = useState(false);
  
  const inputRef = useRef<HTMLInputElement>(null);
  const tableRef = useRef<HTMLDivElement>(null);
  
  // 히스토리에 현재 상태 저장
  const saveToHistory = useCallback(() => {
    if (isUndoRedo) return;
    
    const newState: HistoryState = {
      columns: [...columns],
      data: data.map(row => ({ ...row })),
    };
    
    setHistory(prev => {
      // 현재 인덱스 이후의 히스토리는 삭제 (새로운 분기)
      const newHistory = prev.slice(0, historyIndex + 1);
      newHistory.push(newState);
      // 최대 50개까지만 유지
      if (newHistory.length > 50) {
        newHistory.shift();
        return newHistory;
      }
      return newHistory;
    });
    setHistoryIndex(prev => Math.min(prev + 1, 49));
  }, [columns, data, historyIndex, isUndoRedo]);
  
  // 초기 상태 저장
  useEffect(() => {
    if (history.length === 0 && (columns.length > 0 || data.length > 0)) {
      setHistory([{ columns: [...columns], data: data.map(row => ({ ...row })) }]);
      setHistoryIndex(0);
    }
  }, []);
  
  // 데이터 변경 시 히스토리 저장 (Undo/Redo가 아닌 경우)
  useEffect(() => {
    if (!isUndoRedo && historyIndex >= 0) {
      const currentState = history[historyIndex];
      if (currentState) {
        const columnsChanged = JSON.stringify(columns) !== JSON.stringify(currentState.columns);
        const dataChanged = JSON.stringify(data) !== JSON.stringify(currentState.data);
        if (columnsChanged || dataChanged) {
          saveToHistory();
        }
      }
    }
    setIsUndoRedo(false);
  }, [columns, data]);
  
  // Undo 실행
  const handleUndo = useCallback(() => {
    if (historyIndex <= 0) return;
    
    const prevIndex = historyIndex - 1;
    const prevState = history[prevIndex];
    if (prevState) {
      setIsUndoRedo(true);
      setHistoryIndex(prevIndex);
      onColumnsChange([...prevState.columns]);
      onDataChange(prevState.data.map(row => ({ ...row })));
    }
  }, [history, historyIndex, onColumnsChange, onDataChange]);
  
  // Redo 실행
  const handleRedo = useCallback(() => {
    if (historyIndex >= history.length - 1) return;
    
    const nextIndex = historyIndex + 1;
    const nextState = history[nextIndex];
    if (nextState) {
      setIsUndoRedo(true);
      setHistoryIndex(nextIndex);
      onColumnsChange([...nextState.columns]);
      onDataChange(nextState.data.map(row => ({ ...row })));
    }
  }, [history, historyIndex, onColumnsChange, onDataChange]);

  // 범위 정규화 (시작이 끝보다 크면 교환)
  const normalizeRange = (range: CellRange): CellRange => {
    return {
      startRow: Math.min(range.startRow, range.endRow),
      startCol: Math.min(range.startCol, range.endCol),
      endRow: Math.max(range.startRow, range.endRow),
      endCol: Math.max(range.startCol, range.endCol),
    };
  };

  // 셀이 선택 범위 내에 있는지 확인
  const isCellInSelection = (row: number, col: number): boolean => {
    if (!selection) return false;
    const norm = normalizeRange(selection);
    return (
      row >= norm.startRow &&
      row <= norm.endRow &&
      col >= norm.startCol &&
      col <= norm.endCol
    );
  };

  // 셀이 선택 범위의 끝(우하단)인지 확인
  const isCellSelectionEnd = (row: number, col: number): boolean => {
    if (!selection) return false;
    const norm = normalizeRange(selection);
    return row === norm.endRow && col === norm.endCol;
  };

  // 셀 선택 시작 (클릭)
  const handleCellMouseDown = useCallback((row: number, col: number, e: React.MouseEvent) => {
    // 편집 중이면 종료
    if (editingCell) {
      setEditingCell(null);
      setEditValue("");
    }

    // 새 선택 시작
    setSelection({
      startRow: row,
      startCol: col,
      endRow: row,
      endCol: col,
    });
    setIsDraggingSelection(true);
    
    // 테이블에 포커스 (키보드 이벤트 수신용)
    tableRef.current?.focus();
  }, [editingCell]);

  // 셀 선택 드래그 중
  const handleCellMouseEnter = useCallback((row: number, col: number) => {
    if (isDraggingSelection && selection) {
      setSelection((prev) => prev ? {
        ...prev,
        endRow: row,
        endCol: col,
      } : null);
    }
  }, [isDraggingSelection, selection]);

  // 셀 선택 드래그 종료
  useEffect(() => {
    const handleMouseUp = () => {
      if (isDraggingSelection) {
        setIsDraggingSelection(false);
      }
    };

    document.addEventListener("mouseup", handleMouseUp);
    return () => document.removeEventListener("mouseup", handleMouseUp);
  }, [isDraggingSelection]);

  // 셀 편집 시작 (더블클릭)
  const startEditing = useCallback(
    (row: number, col: number) => {
      setEditingCell({ row, col });
      setSelection({
        startRow: row,
        startCol: col,
        endRow: row,
        endCol: col,
      });
      if (row === -1) {
        // 헤더 편집
        setEditValue(columns[col] || "");
      } else {
        // 데이터 셀 편집
        const colName = columns[col];
        setEditValue(String(data[row]?.[colName] ?? ""));
      }
    },
    [columns, data]
  );

  // 편집 완료
  const finishEditing = useCallback(() => {
    if (!editingCell) return;

    const { row, col } = editingCell;

    if (row === -1) {
      // 헤더(컬럼명) 변경
      const newColumns = [...columns];
      const oldColName = newColumns[col];
      const newColName = editValue.trim() || `Column${col + 1}`;

      if (oldColName !== newColName) {
        newColumns[col] = newColName;
        onColumnsChange(newColumns);

        // 데이터의 키도 함께 변경
        const newData = data.map((rowData) => {
          const newRowData: Record<string, any> = {};
          Object.keys(rowData).forEach((key) => {
            if (key === oldColName) {
              newRowData[newColName] = rowData[key];
            } else {
              newRowData[key] = rowData[key];
            }
          });
          return newRowData;
        });
        onDataChange(newData);
      }
    } else {
      // 데이터 셀 변경
      const colName = columns[col];
      const newData = [...data];
      if (!newData[row]) {
        newData[row] = {};
      }
      newData[row] = { ...newData[row], [colName]: editValue };
      onDataChange(newData);
    }

    setEditingCell(null);
    setEditValue("");
  }, [editingCell, editValue, columns, data, onColumnsChange, onDataChange]);

  // 다음 셀로 이동
  const moveToNextCell = useCallback(
    (direction: "right" | "down" | "left" | "up") => {
      if (!editingCell) return;

      finishEditing();

      const { row, col } = editingCell;
      let nextRow = row;
      let nextCol = col;

      switch (direction) {
        case "right":
          if (col < columns.length - 1) {
            nextCol = col + 1;
          } else {
            // 마지막 열에서 Tab → 새 열 추가 (빈 헤더로)
            const tempColId = `__temp_${Date.now()}`;
            const newColumns = [...columns, ""];
            onColumnsChange(newColumns);

            // 모든 행에 새 컬럼 추가 (임시 키 사용)
            const newData = data.map((rowData) => ({
              ...rowData,
              [tempColId]: "",
            }));
            onDataChange(newData);

            nextCol = columns.length;
          }
          break;

        case "down":
          if (row === -1) {
            nextRow = 0;
          } else if (row < data.length - 1) {
            nextRow = row + 1;
          } else {
            // 마지막 행에서 Enter → 새 행 추가
            const newRow: Record<string, any> = {};
            columns.forEach((c) => {
              newRow[c] = "";
            });
            onDataChange([...data, newRow]);
            nextRow = data.length;
          }
          break;

        case "left":
          if (col > 0) {
            nextCol = col - 1;
          }
          break;

        case "up":
          if (row > -1) {
            nextRow = row - 1;
          }
          break;
      }

      // 다음 셀 편집 시작
      setTimeout(() => {
        startEditing(nextRow, nextCol);
      }, 0);
    },
    [editingCell, columns, data, onColumnsChange, onDataChange, finishEditing, startEditing]
  );

  // 키보드 이벤트 처리
  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLInputElement>) => {
      switch (e.key) {
        case "Tab":
          e.preventDefault();
          moveToNextCell(e.shiftKey ? "left" : "right");
          break;
        case "Enter":
          e.preventDefault();
          moveToNextCell("down");
          break;
        case "Escape":
          setEditingCell(null);
          setEditValue("");
          break;
        case "ArrowUp":
          if (!e.shiftKey) {
            e.preventDefault();
            moveToNextCell("up");
          }
          break;
        case "ArrowDown":
          if (!e.shiftKey) {
            e.preventDefault();
            moveToNextCell("down");
          }
          break;
        case "ArrowLeft":
          // 커서가 맨 앞이면 왼쪽 셀로
          if (inputRef.current?.selectionStart === 0) {
            e.preventDefault();
            moveToNextCell("left");
          }
          break;
        case "ArrowRight":
          // 커서가 맨 뒤면 오른쪽 셀로
          if (inputRef.current?.selectionStart === editValue.length) {
            e.preventDefault();
            moveToNextCell("right");
          }
          break;
      }
    },
    [moveToNextCell, editValue]
  );

  // 편집 모드일 때 input에 포커스
  useEffect(() => {
    if (editingCell && inputRef.current) {
      inputRef.current.focus();
      inputRef.current.select();
    }
  }, [editingCell]);

  // 외부 클릭 시 편집 종료
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (tableRef.current && !tableRef.current.contains(e.target as Node)) {
        finishEditing();
        setSelection(null);
      }
    };

    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, [finishEditing]);

  // ============ 복사/붙여넣기 ============

  // 셀이 복사 범위 내에 있는지 확인
  const isCellInCopiedRange = (row: number, col: number): boolean => {
    if (!copiedRange) return false;
    const norm = normalizeRange(copiedRange);
    return (
      row >= norm.startRow &&
      row <= norm.endRow &&
      col >= norm.startCol &&
      col <= norm.endCol
    );
  };

  // 복사 범위의 테두리 위치 확인
  const getCopiedBorderPosition = (row: number, col: number): { top: boolean; right: boolean; bottom: boolean; left: boolean } => {
    if (!copiedRange) return { top: false, right: false, bottom: false, left: false };
    const norm = normalizeRange(copiedRange);
    
    if (!isCellInCopiedRange(row, col)) {
      return { top: false, right: false, bottom: false, left: false };
    }

    return {
      top: row === norm.startRow,
      right: col === norm.endCol,
      bottom: row === norm.endRow,
      left: col === norm.startCol,
    };
  };

  // 선택 범위 복사 (Ctrl+C)
  const handleCopy = useCallback(async () => {
    if (!selection || editingCell) return;

    const norm = normalizeRange(selection);
    const rows: string[] = [];

    for (let r = norm.startRow; r <= norm.endRow; r++) {
      const rowValues: string[] = [];
      for (let c = norm.startCol; c <= norm.endCol; c++) {
        if (r === -1) {
          // 헤더 복사
          rowValues.push(columns[c] || "");
        } else {
          // 데이터 복사
          const colName = columns[c];
          rowValues.push(String(data[r]?.[colName] ?? ""));
        }
      }
      rows.push(rowValues.join("\t"));
    }

    const text = rows.join("\n");
    
    try {
      await navigator.clipboard.writeText(text);
      // 복사 범위 저장 (점선 애니메이션 표시)
      setCopiedRange({ ...norm });
    } catch (err) {
      console.warn("클립보드 복사 실패:", err);
    }
  }, [selection, editingCell, columns, data]);

  // 붙여넣기 (Ctrl+V)
  const handlePaste = useCallback(async () => {
    if (!selection || editingCell) return;

    try {
      const text = await navigator.clipboard.readText();
      if (!text) return;

      const norm = normalizeRange(selection);
      const pasteRows = text.split(/\r?\n/).map((row) => row.split("\t"));
      
      // 빈 행 제거
      const filteredRows = pasteRows.filter((row) => row.some((cell) => cell.trim() !== ""));
      if (filteredRows.length === 0) return;

      const newData = [...data];
      const newColumns = [...columns];
      let columnsChanged = false;

      for (let ri = 0; ri < filteredRows.length; ri++) {
        const pasteRow = filteredRows[ri];
        const targetRow = norm.startRow + ri;

        for (let ci = 0; ci < pasteRow.length; ci++) {
          const targetCol = norm.startCol + ci;
          const value = pasteRow[ci];

          if (targetRow === -1) {
            // 헤더에 붙여넣기
            if (targetCol < newColumns.length) {
              newColumns[targetCol] = value;
              columnsChanged = true;
            }
          } else {
            // 데이터에 붙여넣기
            if (targetCol < columns.length) {
              // 필요시 행 추가
              while (newData.length <= targetRow) {
                const emptyRow: Record<string, any> = {};
                columns.forEach((c) => {
                  emptyRow[c] = "";
                });
                newData.push(emptyRow);
              }

              const colName = columns[targetCol];
              newData[targetRow] = {
                ...newData[targetRow],
                [colName]: value,
              };
            }
          }
        }
      }

      if (columnsChanged) {
        onColumnsChange(newColumns);
      }
      onDataChange(newData);

      // 붙여넣기 범위로 선택 확장
      setSelection({
        startRow: norm.startRow,
        startCol: norm.startCol,
        endRow: Math.min(norm.startRow + filteredRows.length - 1, data.length - 1),
        endCol: Math.min(norm.startCol + (filteredRows[0]?.length || 1) - 1, columns.length - 1),
      });

      // 붙여넣기 후 복사 범위 초기화
      setCopiedRange(null);
    } catch (err) {
      console.warn("클립보드 붙여넣기 실패:", err);
    }
  }, [selection, editingCell, columns, data, onColumnsChange, onDataChange]);

  // Delete 키로 선택 범위 삭제
  const handleDelete = useCallback(() => {
    if (!selection || editingCell) return;

    const norm = normalizeRange(selection);
    const newData = [...data];

    for (let r = norm.startRow; r <= norm.endRow; r++) {
      if (r >= 0 && r < newData.length) {
        for (let c = norm.startCol; c <= norm.endCol; c++) {
          if (c < columns.length) {
            const colName = columns[c];
            newData[r] = {
              ...newData[r],
              [colName]: "",
            };
          }
        }
      }
    }

    onDataChange(newData);
  }, [selection, editingCell, columns, data, onDataChange]);

  // 전역 키보드 이벤트 (복사/붙여넣기/삭제)
  useEffect(() => {
    const handleGlobalKeyDown = (e: KeyboardEvent) => {
      // 편집 중이면 무시 (input에서 자체 처리)
      if (editingCell) return;
      
      // 선택이 없으면 무시
      if (!selection) return;

      // 다른 입력 필드에 포커스가 있으면 무시
      const activeElement = document.activeElement;
      const isInputFocused = activeElement instanceof HTMLInputElement ||
                             activeElement instanceof HTMLTextAreaElement ||
                             activeElement instanceof HTMLSelectElement;
      
      // 테이블 내부의 input이 아닌 다른 input에 포커스가 있으면 무시
      if (isInputFocused && !tableRef.current?.contains(activeElement)) {
        return;
      }

      if ((e.ctrlKey || e.metaKey) && e.key === "z") {
        // Ctrl+Z: Undo
        e.preventDefault();
        handleUndo();
      } else if ((e.ctrlKey || e.metaKey) && e.key === "y") {
        // Ctrl+Y: Redo
        e.preventDefault();
        handleRedo();
      } else if ((e.ctrlKey || e.metaKey) && e.key === "c") {
        e.preventDefault();
        handleCopy();
      } else if ((e.ctrlKey || e.metaKey) && e.key === "v") {
        e.preventDefault();
        handlePaste();
      } else if (e.key === "Delete" || e.key === "Backspace") {
        // 다른 곳에 포커스가 있으면 Delete 무시
        if (isInputFocused) return;
        e.preventDefault();
        handleDelete();
      } else if (e.key === "Escape") {
        // Esc로 복사 범위 표시 취소
        setCopiedRange(null);
      } else if (e.key === "F2") {
        // F2로 편집 모드 진입 (기존 값 유지)
        const norm = normalizeRange(selection);
        if (norm.startRow >= 0 && norm.startRow === norm.endRow && norm.startCol === norm.endCol) {
          e.preventDefault();
          const colName = columns[norm.startCol];
          setEditingCell({ row: norm.startRow, col: norm.startCol });
          setEditValue(String(data[norm.startRow]?.[colName] ?? ""));
        }
      } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
        // 일반 문자 키 입력 시 편집 모드 진입 (엑셀처럼)
        const norm = normalizeRange(selection);
        if (norm.startRow >= 0 && norm.startRow === norm.endRow && norm.startCol === norm.endCol) {
          // 단일 셀 선택 시에만
          e.preventDefault();
          setEditingCell({ row: norm.startRow, col: norm.startCol });
          setEditValue(e.key); // 입력한 문자로 시작
        }
      }
    };

    document.addEventListener("keydown", handleGlobalKeyDown);
    return () => document.removeEventListener("keydown", handleGlobalKeyDown);
  }, [editingCell, selection, handleCopy, handlePaste, handleDelete, handleUndo, handleRedo]);

  // 행 삭제
  const handleDeleteRow = (rowIndex: number) => {
    const newData = data.filter((_, i) => i !== rowIndex);
    onDataChange(newData);
  };

  // 열 삭제
  const handleDeleteColumn = (colIndex: number) => {
    if (columns.length <= 1) return;

    const colName = columns[colIndex];
    const newColumns = columns.filter((_, i) => i !== colIndex);
    onColumnsChange(newColumns);

    const newData = data.map((row) => {
      const { [colName]: removed, ...rest } = row;
      return rest;
    });
    onDataChange(newData);
  };

  // 컬럼 문자 (A, B, C, ...)
  const getColumnLetter = (index: number): string => {
    let letter = "";
    let i = index;
    while (i >= 0) {
      letter = String.fromCharCode(65 + (i % 26)) + letter;
      i = Math.floor(i / 26) - 1;
    }
    return letter;
  };

  // ============ 자동 채우기 로직 ============

  // 값에서 마지막 숫자 패턴 추출
  const extractNumberPattern = (value: string): { 
    prefix: string; 
    number: number; 
    suffix: string;
    numLength: number;
    isZeroPadded: boolean;
  } | null => {
    if (/^-?\d+(\.\d+)?$/.test(value)) {
      const isZeroPadded = value.startsWith("0") && value.length > 1 && !value.includes(".");
      return { 
        prefix: "", 
        number: parseFloat(value), 
        suffix: "",
        numLength: value.replace("-", "").split(".")[0].length,
        isZeroPadded
      };
    }

    const match = value.match(/^(.*)(\d+)(\D*)$/);
    if (match) {
      const numStr = match[2];
      const isZeroPadded = numStr.startsWith("0") && numStr.length > 1;
      return {
        prefix: match[1],
        number: parseInt(numStr, 10),
        suffix: match[3],
        numLength: numStr.length,
        isZeroPadded
      };
    }

    return null;
  };

  // 날짜 패턴 인식
  const extractDatePattern = (value: string): Date | null => {
    const dateMatch = value.match(/^(\d{4})-(\d{2})-(\d{2})$/);
    if (dateMatch) {
      const date = new Date(parseInt(dateMatch[1]), parseInt(dateMatch[2]) - 1, parseInt(dateMatch[3]));
      if (!isNaN(date.getTime())) {
        return date;
      }
    }
    return null;
  };

  // 다음 값 생성
  const generateNextValue = (sourceValue: string, step: number): string => {
    if (!sourceValue || sourceValue.trim() === "") {
      return "";
    }

    const datePattern = extractDatePattern(sourceValue);
    if (datePattern) {
      const newDate = new Date(datePattern);
      newDate.setDate(newDate.getDate() + step);
      const year = newDate.getFullYear();
      const month = String(newDate.getMonth() + 1).padStart(2, "0");
      const day = String(newDate.getDate()).padStart(2, "0");
      return `${year}-${month}-${day}`;
    }

    const numberPattern = extractNumberPattern(sourceValue);
    if (numberPattern) {
      const newNumber = numberPattern.number + step;
      const absNumber = Math.max(0, newNumber);
      
      let numStr: string;
      if (numberPattern.isZeroPadded) {
        numStr = String(absNumber).padStart(numberPattern.numLength, "0");
      } else {
        numStr = String(absNumber);
      }
      
      return numberPattern.prefix + numStr + numberPattern.suffix;
    }

    return sourceValue;
  };

  // 자동 채우기 드래그 시작
  const handleFillDragStart = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    
    // 편집 중이면 먼저 현재 편집 값을 저장
    if (editingCell) {
      const { row, col } = editingCell;
      if (row === -1) {
        // 헤더 변경
        const newColumns = [...columns];
        const oldColName = newColumns[col];
        const newColName = editValue.trim() || `Column${col + 1}`;
        if (oldColName !== newColName) {
          newColumns[col] = newColName;
          onColumnsChange(newColumns);
        }
      } else {
        // 데이터 셀 변경
        const colName = columns[col];
        const newData = [...data];
        if (!newData[row]) {
          newData[row] = {};
        }
        newData[row] = { ...newData[row], [colName]: editValue };
        onDataChange(newData);
      }
      setEditingCell(null);
      setEditValue("");
    }
    
    if (!selection) return;
    const norm = normalizeRange(selection);
    if (norm.startRow < 0) return; // 헤더는 제외
    
    setIsDraggingFill(true);
    setFillPreviewEnd(norm.endRow);
  };

  // 자동 채우기 드래그 중
  const handleFillDragMove = useCallback((e: MouseEvent) => {
    if (!isDraggingFill || !selection || !tableRef.current) return;

    const rows = tableRef.current.querySelectorAll("tbody tr");
    const mouseY = e.clientY;

    for (let i = 0; i < rows.length - 1; i++) {
      const row = rows[i] as HTMLElement;
      const rect = row.getBoundingClientRect();
      
      if (mouseY >= rect.top && mouseY <= rect.bottom) {
        setFillPreviewEnd(i);
        break;
      } else if (mouseY > rect.bottom && i === rows.length - 2) {
        setFillPreviewEnd(i);
      }
    }
  }, [isDraggingFill, selection]);

  // 열의 숫자 패턴 간격 계산 (예: 201, 202 → 간격 1)
  const calculateColumnIncrement = (colIndex: number, startRow: number, endRow: number): number | null => {
    if (startRow === endRow) return 1; // 단일 행이면 기본 증가 1
    
    const colName = columns[colIndex];
    const increments: number[] = [];
    
    for (let row = startRow; row < endRow; row++) {
      const currentValue = String(data[row]?.[colName] ?? "");
      const nextValue = String(data[row + 1]?.[colName] ?? "");
      
      const currentPattern = extractNumberPattern(currentValue);
      const nextPattern = extractNumberPattern(nextValue);
      
      if (currentPattern && nextPattern) {
        // 접두사와 접미사가 같은지 확인
        if (currentPattern.prefix === nextPattern.prefix && currentPattern.suffix === nextPattern.suffix) {
          increments.push(nextPattern.number - currentPattern.number);
        } else {
          return null; // 패턴이 다르면 복사 모드
        }
      } else {
        return null; // 숫자 패턴이 없으면 복사 모드
      }
    }
    
    // 모든 간격이 같은지 확인
    if (increments.length > 0 && increments.every(inc => inc === increments[0])) {
      return increments[0];
    }
    
    return null;
  };

  // 자동 채우기 드래그 종료 (다중 셀 지원)
  // - 숫자 패턴이 있으면: 패턴 간격을 인식하여 증가 (201, 202 → 203, 204)
  // - 숫자 패턴이 없으면: 선택된 패턴 그대로 반복 (복사)
  const handleFillDragEnd = useCallback(() => {
    if (!isDraggingFill || !selection || fillPreviewEnd === null) {
      setIsDraggingFill(false);
      setFillPreviewEnd(null);
      return;
    }

    const norm = normalizeRange(selection);
    const endRow = fillPreviewEnd;
    const selectionHeight = norm.endRow - norm.startRow + 1;

    if (endRow !== norm.endRow && norm.startRow >= 0) {
      const newData = [...data];
      
      // 각 열별로 증가 패턴 계산
      const columnIncrements: Map<number, number | null> = new Map();
      for (let col = norm.startCol; col <= norm.endCol; col++) {
        columnIncrements.set(col, calculateColumnIncrement(col, norm.startRow, norm.endRow));
      }

      if (endRow > norm.endRow) {
        // 아래로 채우기
        for (let targetRow = norm.endRow + 1; targetRow <= endRow; targetRow++) {
          if (!newData[targetRow]) {
            newData[targetRow] = {};
            columns.forEach((c) => {
              newData[targetRow][c] = "";
            });
          }

          // 선택된 모든 열에 대해 채우기
          for (let col = norm.startCol; col <= norm.endCol; col++) {
            const colName = columns[col];
            const increment = columnIncrements.get(col);
            
            if (increment !== null) {
              // 숫자 패턴 증가 모드
              // 마지막 선택 행의 값을 기준으로 증가
              const lastValue = String(data[norm.endRow]?.[colName] ?? "");
              const step = (targetRow - norm.endRow) * increment;
              newData[targetRow] = {
                ...newData[targetRow],
                [colName]: generateNextValue(lastValue, step),
              };
            } else {
              // 복사 모드 (패턴 반복)
              const sourceRowOffset = (targetRow - norm.endRow - 1) % selectionHeight;
              const sourceRow = norm.startRow + sourceRowOffset;
              const sourceValue = String(data[sourceRow]?.[colName] ?? "");
              newData[targetRow] = {
                ...newData[targetRow],
                [colName]: sourceValue,
              };
            }
          }
        }
      } else if (endRow < norm.startRow) {
        // 위로 채우기
        for (let targetRow = norm.startRow - 1; targetRow >= endRow; targetRow--) {
          if (!newData[targetRow]) {
            newData[targetRow] = {};
            columns.forEach((c) => {
              newData[targetRow][c] = "";
            });
          }

          for (let col = norm.startCol; col <= norm.endCol; col++) {
            const colName = columns[col];
            const increment = columnIncrements.get(col);
            
            if (increment !== null) {
              // 숫자 패턴 감소 모드
              const firstValue = String(data[norm.startRow]?.[colName] ?? "");
              const step = (targetRow - norm.startRow) * increment;
              newData[targetRow] = {
                ...newData[targetRow],
                [colName]: generateNextValue(firstValue, step),
              };
            } else {
              // 복사 모드 (패턴 반복)
              const sourceRowOffset = (norm.startRow - targetRow - 1) % selectionHeight;
              const sourceRow = norm.endRow - sourceRowOffset;
              const sourceValue = String(data[sourceRow]?.[colName] ?? "");
              newData[targetRow] = {
                ...newData[targetRow],
                [colName]: sourceValue,
              };
            }
          }
        }
      }

      onDataChange(newData);
    }

    setIsDraggingFill(false);
    setFillPreviewEnd(null);
  }, [isDraggingFill, selection, fillPreviewEnd, columns, data, onDataChange]);

  // 드래그 이벤트 리스너
  useEffect(() => {
    if (isDraggingFill) {
      document.addEventListener("mousemove", handleFillDragMove);
      document.addEventListener("mouseup", handleFillDragEnd);
      return () => {
        document.removeEventListener("mousemove", handleFillDragMove);
        document.removeEventListener("mouseup", handleFillDragEnd);
      };
    }
  }, [isDraggingFill, handleFillDragMove, handleFillDragEnd]);

  // 셀이 자동 채우기 미리보기 범위에 있는지 확인
  const isInFillPreview = (rowIndex: number, colIndex: number): boolean => {
    if (!isDraggingFill || !selection || fillPreviewEnd === null) return false;
    
    const norm = normalizeRange(selection);
    
    // 열이 선택 범위 내에 있어야 함
    if (colIndex < norm.startCol || colIndex > norm.endCol) return false;

    if (fillPreviewEnd > norm.endRow) {
      return rowIndex > norm.endRow && rowIndex <= fillPreviewEnd;
    } else if (fillPreviewEnd < norm.startRow) {
      return rowIndex >= fillPreviewEnd && rowIndex < norm.startRow;
    }
    
    return false;
  };

  return (
    <div
      ref={tableRef}
      tabIndex={0}
      className="overflow-auto rounded-md border border-border select-none outline-none focus:ring-2 focus:ring-primary/20"
      style={{ maxHeight }}
    >
      <table className="min-w-full border-collapse text-xs">
        {/* 열 인덱스 헤더 (A, B, C, ...) */}
        <thead className="sticky top-0 z-10 bg-muted">
          <tr>
            {/* 빈 코너 셀 */}
            <th className="sticky left-0 z-20 w-10 border-b border-r border-border bg-muted px-1 py-1 text-center text-[10px] text-muted-foreground">
              
            </th>
            {columns.map((_, colIndex) => (
              <th
                key={colIndex}
                className="min-w-[100px] border-b border-r border-border bg-muted px-2 py-1 text-center font-normal text-muted-foreground"
              >
                <div className="flex items-center justify-center gap-1">
                  <span>{getColumnLetter(colIndex)}</span>
                  {columns.length > 1 && (
                    <button
                      onClick={() => handleDeleteColumn(colIndex)}
                      className="ml-1 text-muted-foreground/50 hover:text-destructive"
                      title="열 삭제"
                    >
                      ×
                    </button>
                  )}
                </div>
              </th>
            ))}
            {/* 새 열 추가 버튼 */}
            <th className="w-8 border-b border-border bg-muted px-1 py-1">
              <button
                onClick={() => {
                  onColumnsChange([...columns, ""]);
                  const tempColId = `__temp_${Date.now()}`;
                  const newData = data.map((row) => ({ ...row, [tempColId]: "" }));
                  onDataChange(newData);
                }}
                className="text-muted-foreground/50 hover:text-primary"
                title="열 추가"
              >
                +
              </button>
            </th>
          </tr>

          {/* 컬럼명 헤더 (편집 가능) */}
          <tr>
            <th className="sticky left-0 z-20 w-10 border-b border-r border-border bg-primary/10 px-1 py-1 text-center font-medium">
              1
            </th>
            {columns.map((colName, colIndex) => (
              <th
                key={colIndex}
                className={cn(
                  "min-w-[100px] cursor-pointer border-b border-r border-border bg-primary/5 px-0 py-0 font-medium text-primary",
                  (editingCell?.row === -1 && editingCell?.col === colIndex) ||
                    isCellInSelection(-1, colIndex)
                    ? "ring-2 ring-primary ring-inset"
                    : ""
                )}
                onMouseDown={(e) => handleCellMouseDown(-1, colIndex, e)}
                onMouseEnter={() => handleCellMouseEnter(-1, colIndex)}
                onDoubleClick={() => startEditing(-1, colIndex)}
              >
                {editingCell?.row === -1 && editingCell?.col === colIndex ? (
                  <input
                    ref={inputRef}
                    type="text"
                    value={editValue}
                    onChange={(e) => setEditValue(e.target.value)}
                    onKeyDown={handleKeyDown}
                    onBlur={finishEditing}
                    className="w-full bg-white px-2 py-1 text-xs font-medium text-primary outline-none"
                  />
                ) : (
                  <div className="px-2 py-1">{colName || <span className="text-muted-foreground/50 italic">빈 헤더</span>}</div>
                )}
              </th>
            ))}
            <th className="w-8 border-b border-border bg-primary/5"></th>
          </tr>
        </thead>

        <tbody>
          {data.map((row, rowIndex) => (
            <tr key={rowIndex} className="group">
              {/* 행 번호 */}
              <td className="sticky left-0 z-10 w-10 border-b border-r border-border bg-muted/50 px-1 py-1 text-center text-muted-foreground">
                <div className="flex items-center justify-center gap-0.5">
                  <span>{rowIndex + 2}</span>
                  <button
                    onClick={() => handleDeleteRow(rowIndex)}
                    className="hidden text-muted-foreground/50 hover:text-destructive group-hover:inline"
                    title="행 삭제"
                  >
                    ×
                  </button>
                </div>
              </td>

              {/* 데이터 셀 */}
              {columns.map((colName, colIndex) => {
                const isSelected = isCellInSelection(rowIndex, colIndex);
                const isEditing = editingCell?.row === rowIndex && editingCell?.col === colIndex;
                const inFillPreview = isInFillPreview(rowIndex, colIndex);
                const isSelectionEnd = isCellSelectionEnd(rowIndex, colIndex);
                const copiedBorder = getCopiedBorderPosition(rowIndex, colIndex);
                const isCopied = isCellInCopiedRange(rowIndex, colIndex);

                return (
                  <td
                    key={colIndex}
                    className={cn(
                      "relative cursor-cell border-b border-r border-border px-0 py-0",
                      isSelected ? "bg-primary/10" : "",
                      isEditing ? "ring-2 ring-primary ring-inset" : "",
                      inFillPreview ? "bg-primary/20" : ""
                    )}
                    onMouseDown={(e) => handleCellMouseDown(rowIndex, colIndex, e)}
                    onMouseEnter={() => handleCellMouseEnter(rowIndex, colIndex)}
                    onDoubleClick={() => startEditing(rowIndex, colIndex)}
                  >
                    {isEditing ? (
                      <input
                        ref={inputRef}
                        type="text"
                        value={editValue}
                        onChange={(e) => setEditValue(e.target.value)}
                        onKeyDown={handleKeyDown}
                        onBlur={finishEditing}
                        className="w-full bg-white px-2 py-1 text-xs outline-none"
                      />
                    ) : (
                      <div
                        className="max-w-[200px] truncate px-2 py-1"
                        title={String(row[colName] ?? "")}
                      >
                        {String(row[colName] ?? "")}
                      </div>
                    )}

                    {/* 복사 범위 점선 테두리 (Marching Ants) */}
                    {isCopied && (
                      <>
                        {copiedBorder.top && (
                          <div className="pointer-events-none absolute left-0 right-0 top-0 h-[2px] animate-marching-ants-h" />
                        )}
                        {copiedBorder.right && (
                          <div className="pointer-events-none absolute bottom-0 right-0 top-0 w-[2px] animate-marching-ants-v" />
                        )}
                        {copiedBorder.bottom && (
                          <div className="pointer-events-none absolute bottom-0 left-0 right-0 h-[2px] animate-marching-ants-h" />
                        )}
                        {copiedBorder.left && (
                          <div className="pointer-events-none absolute bottom-0 left-0 top-0 w-[2px] animate-marching-ants-v" />
                        )}
                      </>
                    )}

                    {/* 자동 채우기 핸들 - 선택 범위의 우하단에서만 표시 (편집 중에도 표시) */}
                    {isSelectionEnd && selection && normalizeRange(selection).startRow >= 0 && (
                      <div
                        className="absolute bottom-0 right-0 z-20 h-2.5 w-2.5 translate-x-1/2 translate-y-1/2 cursor-crosshair border border-white bg-primary"
                        onMouseDown={handleFillDragStart}
                        title="자동 채우기"
                      />
                    )}
                  </td>
                );
              })}
              <td className="w-8 border-b border-border"></td>
            </tr>
          ))}

          {/* 새 행 추가 영역 */}
          <tr className="bg-muted/20">
            <td className="sticky left-0 z-10 w-10 border-r border-border bg-muted/30 px-1 py-1 text-center">
              <button
                onClick={() => {
                  const newRow: Record<string, any> = {};
                  columns.forEach((c) => {
                    newRow[c] = "";
                  });
                  onDataChange([...data, newRow]);
                }}
                className="text-muted-foreground/50 hover:text-primary"
                title="행 추가"
              >
                +
              </button>
            </td>
            <td
              colSpan={columns.length + 1}
              className="cursor-pointer px-2 py-1 text-muted-foreground/50 hover:bg-muted/50"
              onClick={() => {
                const newRow: Record<string, any> = {};
                columns.forEach((c) => {
                  newRow[c] = "";
                });
                onDataChange([...data, newRow]);
                setTimeout(() => {
                  startEditing(data.length, 0);
                }, 0);
              }}
            >
              클릭하여 새 행 추가...
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  );
};
