"use client";

import React, { useState, useEffect, useRef } from "react";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { ChevronDown, Check, GripVertical } from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox";
import { RepeaterColumnConfig } from "./types";
import { cn } from "@/lib/utils";

// @dnd-kit imports
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragEndEvent,
} from "@dnd-kit/core";
import {
  SortableContext,
  sortableKeyboardCoordinates,
  verticalListSortingStrategy,
  useSortable,
  arrayMove,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";

// SortableRow 컴포넌트 - 드래그 가능한 테이블 행
interface SortableRowProps {
  id: string;
  children: (props: { 
    attributes: React.HTMLAttributes<HTMLElement>; 
    listeners: React.HTMLAttributes<HTMLElement> | undefined;
    isDragging: boolean;
  }) => React.ReactNode;
  className?: string;
}

function SortableRow({ id, children, className }: SortableRowProps) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id });

  const style: React.CSSProperties = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
    backgroundColor: isDragging ? "#f0f9ff" : undefined,
  };

  return (
    <tr ref={setNodeRef} style={style} className={className}>
      {children({ attributes, listeners, isDragging })}
    </tr>
  );
}

interface RepeaterTableProps {
  columns: RepeaterColumnConfig[];
  data: any[];
  onDataChange: (newData: any[]) => void;
  onRowChange: (index: number, newRow: any) => void;
  onRowDelete: (index: number) => void;
  // 동적 데이터 소스 관련
  activeDataSources?: Record<string, string>; // 컬럼별 현재 활성화된 데이터 소스 ID
  onDataSourceChange?: (columnField: string, optionId: string) => void; // 데이터 소스 변경 콜백
  // 체크박스 선택 관련
  selectedRows: Set<number>; // 선택된 행 인덱스
  onSelectionChange: (selectedRows: Set<number>) => void; // 선택 변경 콜백
  // 균등 분배 트리거
  equalizeWidthsTrigger?: number; // 값이 변경되면 균등 분배 실행
}

export function RepeaterTable({
  columns,
  data,
  onDataChange,
  onRowChange,
  onRowDelete,
  activeDataSources = {},
  onDataSourceChange,
  selectedRows,
  onSelectionChange,
  equalizeWidthsTrigger,
}: RepeaterTableProps) {
  // 컨테이너 ref - 실제 너비 측정용
  const containerRef = useRef<HTMLDivElement>(null);
  
  // 균등 분배 모드 상태 (true일 때 테이블이 컨테이너에 맞춤)
  const [isEqualizedMode, setIsEqualizedMode] = useState(false);

  // DnD 센서 설정
  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8, // 8px 이동해야 드래그 시작 (클릭과 구분)
      },
    }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  );

  // 드래그 종료 핸들러
  const handleDragEnd = (event: DragEndEvent) => {
    const { active, over } = event;

    if (over && active.id !== over.id) {
      const oldIndex = data.findIndex((_, idx) => `row-${idx}` === active.id);
      const newIndex = data.findIndex((_, idx) => `row-${idx}` === over.id);

      if (oldIndex !== -1 && newIndex !== -1) {
        const newData = arrayMove(data, oldIndex, newIndex);
        onDataChange(newData);

        // 선택된 행 인덱스도 업데이트
        if (selectedRows.size > 0) {
          const newSelectedRows = new Set<number>();
          selectedRows.forEach((oldIdx) => {
            if (oldIdx === oldIndex) {
              newSelectedRows.add(newIndex);
            } else if (oldIdx > oldIndex && oldIdx <= newIndex) {
              newSelectedRows.add(oldIdx - 1);
            } else if (oldIdx < oldIndex && oldIdx >= newIndex) {
              newSelectedRows.add(oldIdx + 1);
            } else {
              newSelectedRows.add(oldIdx);
            }
          });
          onSelectionChange(newSelectedRows);
        }
      }
    }
  };
  
  const [editingCell, setEditingCell] = useState<{
    rowIndex: number;
    field: string;
  } | null>(null);
  
  // 동적 데이터 소스 Popover 열림 상태
  const [openPopover, setOpenPopover] = useState<string | null>(null);
  
  // 컬럼 너비 상태 관리
  const [columnWidths, setColumnWidths] = useState<Record<string, number>>(() => {
    const widths: Record<string, number> = {};
    columns.forEach((col) => {
      widths[col.field] = col.width ? parseInt(col.width) : 120;
    });
    return widths;
  });
  
  // 기본 너비 저장 (리셋용)
  const defaultWidths = React.useMemo(() => {
    const widths: Record<string, number> = {};
    columns.forEach((col) => {
      widths[col.field] = col.width ? parseInt(col.width) : 120;
    });
    return widths;
  }, [columns]);
  
  // 리사이즈 상태
  const [resizing, setResizing] = useState<{ field: string; startX: number; startWidth: number } | null>(null);
  
  // 리사이즈 핸들러
  const handleMouseDown = (e: React.MouseEvent, field: string) => {
    e.preventDefault();
    setResizing({
      field,
      startX: e.clientX,
      startWidth: columnWidths[field] || 120,
    });
    // 수동 조정 시 균등 분배 모드 해제
    setIsEqualizedMode(false);
  };
  
  // 컬럼 확장 상태 추적 (토글용)
  const [expandedColumns, setExpandedColumns] = useState<Set<string>>(new Set());

  // 데이터 기준 최적 너비 계산
  const calculateAutoFitWidth = (field: string): number => {
    const column = columns.find(col => col.field === field);
    if (!column) return 120;

    // 헤더 텍스트 길이 (대략 8px per character + padding)
    const headerWidth = (column.label?.length || field.length) * 8 + 40;

    // 데이터 중 가장 긴 텍스트 찾기
    let maxDataWidth = 0;
    data.forEach(row => {
      const value = row[field];
      if (value !== undefined && value !== null) {
        let displayText = String(value);
        
        // 숫자는 천단위 구분자 포함
        if (typeof value === 'number') {
          displayText = value.toLocaleString();
        }
        // 날짜는 yyyy-mm-dd 형식
        if (column.type === 'date' && displayText.includes('T')) {
          displayText = displayText.split('T')[0];
        }
        
        // 대략적인 너비 계산 (8px per character + padding)
        const textWidth = displayText.length * 8 + 32;
        maxDataWidth = Math.max(maxDataWidth, textWidth);
      }
    });

    // 헤더와 데이터 중 큰 값 사용, 최소 60px, 최대 400px
    const optimalWidth = Math.max(headerWidth, maxDataWidth);
    return Math.min(Math.max(optimalWidth, 60), 400);
  };

  // 더블클릭으로 auto-fit / 기본 너비 토글
  const handleDoubleClick = (field: string) => {
    // 개별 컬럼 조정 시 균등 분배 모드 해제
    setIsEqualizedMode(false);
    
    setExpandedColumns(prev => {
      const newSet = new Set(prev);
      if (newSet.has(field)) {
        // 확장 상태 → 기본 너비로 복구
        newSet.delete(field);
        setColumnWidths(prevWidths => ({
          ...prevWidths,
          [field]: defaultWidths[field] || 120,
        }));
      } else {
        // 기본 상태 → 데이터 기준 auto-fit
        newSet.add(field);
        const autoWidth = calculateAutoFitWidth(field);
        setColumnWidths(prevWidths => ({
          ...prevWidths,
          [field]: autoWidth,
        }));
      }
      return newSet;
    });
  };

  // 균등 분배 트리거 감지
  useEffect(() => {
    if (equalizeWidthsTrigger === undefined || equalizeWidthsTrigger === 0) return;
    if (!containerRef.current) return;
    
    // 실제 컨테이너 너비 측정
    const containerWidth = containerRef.current.offsetWidth;
    
    // 체크박스 컬럼 너비(40px) + 테이블 border(2px) 제외한 가용 너비 계산
    const checkboxColumnWidth = 40;
    const borderWidth = 2;
    const availableWidth = containerWidth - checkboxColumnWidth - borderWidth;
    
    // 컬럼 수로 나눠서 균등 분배 (최소 60px 보장)
    const equalWidth = Math.max(60, Math.floor(availableWidth / columns.length));
    
    const newWidths: Record<string, number> = {};
    columns.forEach((col) => {
      newWidths[col.field] = equalWidth;
    });
    
    setColumnWidths(newWidths);
    setExpandedColumns(new Set()); // 확장 상태 초기화
    setIsEqualizedMode(true); // 균등 분배 모드 활성화
  }, [equalizeWidthsTrigger, columns]);
  
  useEffect(() => {
    if (!resizing) return;
    
    const handleMouseMove = (e: MouseEvent) => {
      if (!resizing) return;
      const diff = e.clientX - resizing.startX;
      const newWidth = Math.max(60, resizing.startWidth + diff);
      setColumnWidths((prev) => ({
        ...prev,
        [resizing.field]: newWidth,
      }));
    };
    
    const handleMouseUp = () => {
      setResizing(null);
    };
    
    document.addEventListener("mousemove", handleMouseMove);
    document.addEventListener("mouseup", handleMouseUp);
    
    return () => {
      document.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseup", handleMouseUp);
    };
  }, [resizing, columns, data]);

  // 데이터 변경 감지 (필요시 활성화)
  // useEffect(() => {
  //   console.log("📊 RepeaterTable 데이터 업데이트:", data.length, "개 행");
  // }, [data]);

  const handleCellEdit = (rowIndex: number, field: string, value: any) => {
    const newRow = { ...data[rowIndex], [field]: value };
    onRowChange(rowIndex, newRow);
  };

  // 전체 선택 체크박스 핸들러
  const handleSelectAll = (checked: boolean) => {
    if (checked) {
      // 모든 행 선택
      const allIndices = new Set(data.map((_, index) => index));
      onSelectionChange(allIndices);
    } else {
      // 전체 해제
      onSelectionChange(new Set());
    }
  };

  // 개별 행 선택 핸들러
  const handleRowSelect = (rowIndex: number, checked: boolean) => {
    const newSelection = new Set(selectedRows);
    if (checked) {
      newSelection.add(rowIndex);
    } else {
      newSelection.delete(rowIndex);
    }
    onSelectionChange(newSelection);
  };

  // 전체 선택 상태 계산
  const isAllSelected = data.length > 0 && selectedRows.size === data.length;
  const isIndeterminate = selectedRows.size > 0 && selectedRows.size < data.length;

  const renderCell = (
    row: any,
    column: RepeaterColumnConfig,
    rowIndex: number
  ) => {
    const isEditing =
      editingCell?.rowIndex === rowIndex && editingCell?.field === column.field;
    const value = row[column.field];

    // 계산 필드는 편집 불가
    if (column.calculated || !column.editable) {
      return (
        <div className="px-2 py-1">
          {column.type === "number"
            ? typeof value === "number"
              ? value.toLocaleString()
              : value || "0"
            : value || "-"}
        </div>
      );
    }

    // 편집 가능한 필드
    switch (column.type) {
      case "number":
        return (
          <Input
            type="number"
            value={value || ""}
            onChange={(e) =>
              handleCellEdit(rowIndex, column.field, parseFloat(e.target.value) || 0)
            }
            className="h-8 text-xs border-gray-200 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 rounded-none min-w-0 w-full"
          />
        );

      case "date":
        // ISO 형식(2025-11-23T00:00:00.000Z)을 yyyy-mm-dd로 변환
        const formatDateValue = (val: any): string => {
          if (!val) return "";
          // 이미 yyyy-mm-dd 형식이면 그대로 반환
          if (typeof val === "string" && /^\d{4}-\d{2}-\d{2}$/.test(val)) {
            return val;
          }
          // ISO 형식이면 날짜 부분만 추출
          if (typeof val === "string" && val.includes("T")) {
            return val.split("T")[0];
          }
          // Date 객체이면 변환
          if (val instanceof Date) {
            return val.toISOString().split("T")[0];
          }
          return String(val);
        };
        
        return (
          <Input
            type="date"
            value={formatDateValue(value)}
            onChange={(e) => handleCellEdit(rowIndex, column.field, e.target.value)}
            className="h-8 text-xs border-gray-200 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 rounded-none min-w-0 w-full"
          />
        );

      case "select":
        return (
          <Select
            value={value || ""}
            onValueChange={(newValue) =>
              handleCellEdit(rowIndex, column.field, newValue)
            }
          >
            <SelectTrigger className="h-8 text-xs border-gray-200 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 rounded-none min-w-0 w-full">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              {column.selectOptions?.map((option) => (
                <SelectItem key={option.value} value={option.value}>
                  {option.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        );

      default: // text
        return (
          <Input
            type="text"
            value={value || ""}
            onChange={(e) => handleCellEdit(rowIndex, column.field, e.target.value)}
            className="h-8 text-xs border-gray-200 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 rounded-none min-w-0 w-full"
          />
        );
    }
  };

  // 드래그 아이템 ID 목록
  const sortableItems = data.map((_, idx) => `row-${idx}`);

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <div ref={containerRef} className="border border-gray-200 bg-white">
        <div className="overflow-x-auto max-h-[400px] overflow-y-auto">
          <table 
            className={cn(
              "text-xs border-collapse",
              isEqualizedMode && "w-full"
            )}
            style={isEqualizedMode ? undefined : { minWidth: "max-content" }}
          >
            <thead className="bg-gray-50 sticky top-0 z-10">
              <tr>
                {/* 드래그 핸들 헤더 */}
                <th className="px-1 py-2 text-center font-medium text-gray-700 border-b border-r border-gray-200 w-8">
                  <span className="sr-only">순서</span>
                </th>
                {/* 체크박스 헤더 */}
                <th className="px-3 py-2 text-center font-medium text-gray-700 border-b border-r border-gray-200 w-10">
                  <Checkbox
                    checked={isAllSelected}
                    // @ts-ignore - indeterminate는 HTML 속성
                    data-indeterminate={isIndeterminate}
                    onCheckedChange={handleSelectAll}
                    className={cn(
                      "border-gray-400",
                      isIndeterminate && "data-[state=checked]:bg-primary"
                    )}
                  />
                </th>
              {columns.map((col) => {
                const hasDynamicSource = col.dynamicDataSource?.enabled && col.dynamicDataSource.options.length > 0;
                const activeOptionId = activeDataSources[col.field] || col.dynamicDataSource?.defaultOptionId;
                const activeOption = hasDynamicSource 
                  ? col.dynamicDataSource!.options.find(opt => opt.id === activeOptionId) || col.dynamicDataSource!.options[0]
                  : null;
                
                const isExpanded = expandedColumns.has(col.field);
                
                return (
                <th
                  key={col.field}
                  className="px-3 py-2 text-left font-medium text-gray-700 border-b border-r border-gray-200 relative group cursor-pointer select-none"
                  style={{ width: `${columnWidths[col.field]}px` }}
                  onDoubleClick={() => handleDoubleClick(col.field)}
                  title={isExpanded ? "더블클릭하여 기본 너비로 복구" : "더블클릭하여 내용에 맞게 확장"}
                >
                    <div className="flex items-center justify-between pointer-events-none">
                      <div className="flex items-center gap-1 pointer-events-auto">
                        {hasDynamicSource ? (
                          <Popover 
                            open={openPopover === col.field} 
                            onOpenChange={(open) => setOpenPopover(open ? col.field : null)}
                          >
                            <PopoverTrigger asChild>
                              <button
                                type="button"
                                className={cn(
                                  "inline-flex items-center gap-1 hover:text-blue-600 transition-colors",
                                  "focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 rounded px-1 -mx-1"
                                )}
                              >
                                <span>{col.label}</span>
                                <ChevronDown className="h-3 w-3 opacity-60" />
                              </button>
                            </PopoverTrigger>
                            <PopoverContent 
                              className="w-auto min-w-[160px] p-1" 
                              align="start"
                              sideOffset={4}
                            >
                              <div className="text-[10px] text-muted-foreground px-2 py-1 border-b mb-1">
                                데이터 소스 선택
                              </div>
                              {col.dynamicDataSource!.options.map((option) => (
                                <button
                                  key={option.id}
                                  type="button"
                                  onClick={() => {
                                    onDataSourceChange?.(col.field, option.id);
                                    setOpenPopover(null);
                                  }}
                                  className={cn(
                                    "w-full flex items-center gap-2 px-2 py-1.5 text-xs rounded-sm",
                                    "hover:bg-accent hover:text-accent-foreground transition-colors",
                                    "focus:outline-none focus-visible:bg-accent",
                                    activeOption?.id === option.id && "bg-accent/50"
                                  )}
                                >
                                  <Check 
                                    className={cn(
                                      "h-3 w-3",
                                      activeOption?.id === option.id ? "opacity-100" : "opacity-0"
                                    )} 
                                  />
                                  <span>{option.label}</span>
                                </button>
                              ))}
                            </PopoverContent>
                          </Popover>
                        ) : (
                          <>
                            {col.label}
                            {col.required && <span className="text-red-500 ml-1">*</span>}
                          </>
                        )}
                      </div>
                      {/* 리사이즈 핸들 */}
                      <div
                        className="absolute right-0 top-0 bottom-0 w-1 cursor-col-resize hover:bg-blue-500 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-auto"
                        onMouseDown={(e) => handleMouseDown(e, col.field)}
                        title="드래그하여 너비 조정"
                      />
                    </div>
                  </th>
                );
              })}
              </tr>
            </thead>
            <SortableContext items={sortableItems} strategy={verticalListSortingStrategy}>
              <tbody className="bg-white">
                {data.length === 0 ? (
                  <tr>
                    <td
                      colSpan={columns.length + 2}
                      className="px-4 py-8 text-center text-gray-500 border-b border-gray-200"
                    >
                      추가된 항목이 없습니다
                    </td>
                  </tr>
                ) : (
                  data.map((row, rowIndex) => (
                    <SortableRow
                      key={`row-${rowIndex}`}
                      id={`row-${rowIndex}`}
                      className={cn(
                        "hover:bg-blue-50/50 transition-colors",
                        selectedRows.has(rowIndex) && "bg-blue-50"
                      )}
                    >
                      {({ attributes, listeners, isDragging }) => (
                        <>
                          {/* 드래그 핸들 */}
                          <td className="px-1 py-1 text-center border-b border-r border-gray-200">
                            <button
                              type="button"
                              className={cn(
                                "cursor-grab p-1 rounded hover:bg-gray-100 transition-colors",
                                isDragging && "cursor-grabbing"
                              )}
                              {...attributes}
                              {...listeners}
                            >
                              <GripVertical className="h-4 w-4 text-gray-400" />
                            </button>
                          </td>
                          {/* 체크박스 */}
                          <td className="px-3 py-1 text-center border-b border-r border-gray-200">
                            <Checkbox
                              checked={selectedRows.has(rowIndex)}
                              onCheckedChange={(checked) => handleRowSelect(rowIndex, !!checked)}
                              className="border-gray-400"
                            />
                          </td>
                          {/* 데이터 컬럼들 */}
                          {columns.map((col) => (
                            <td 
                              key={col.field} 
                              className="px-1 py-1 border-b border-r border-gray-200 overflow-hidden"
                              style={{ width: `${columnWidths[col.field]}px`, maxWidth: `${columnWidths[col.field]}px` }}
                            >
                              {renderCell(row, col, rowIndex)}
                            </td>
                          ))}
                        </>
                      )}
                    </SortableRow>
                  ))
                )}
              </tbody>
            </SortableContext>
          </table>
        </div>
      </div>
    </DndContext>
  );
}

