"use client";

/**
 * 카테고리 값 관리 - 트리 구조 버전
 * - 3단계 트리 구조 지원 (대분류/중분류/소분류)
 * - 체크박스를 통한 다중 선택 및 일괄 삭제 지원
 */

import React, { useState, useEffect, useCallback, useMemo, useRef } from "react";
import {
  ChevronRight,
  ChevronDown,
  Plus,
  Pencil,
  Trash2,
  Folder,
  FolderOpen,
  Tag,
  Search,
  RefreshCw,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";
import { cn } from "@/lib/utils";
import {
  CategoryValue,
  getCategoryTree,
  createCategoryValue,
  updateCategoryValue,
  deleteCategoryValue,
  checkCanDeleteCategoryValue,
  CreateCategoryValueInput,
} from "@/lib/api/categoryTree";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
  DialogDescription,
} from "@/components/ui/dialog";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Label } from "@/components/ui/label";
import { toast } from "sonner";
import { Switch } from "@/components/ui/switch";

interface CategoryValueManagerTreeProps {
  tableName: string;
  columnName: string;
  columnLabel: string;
  onValueCountChange?: (count: number) => void;
}

// 트리 노드 컴포넌트
interface TreeNodeProps {
  node: CategoryValue;
  level: number;
  expandedNodes: Set<number>;
  selectedValueId?: number;
  searchQuery: string;
  checkedIds: Set<number>;
  onToggle: (valueId: number) => void;
  onSelect: (value: CategoryValue) => void;
  onAdd: (parentValue: CategoryValue | null) => void;
  onEdit: (value: CategoryValue) => void;
  onDelete: (value: CategoryValue) => void;
  onCheck: (valueId: number, checked: boolean) => void;
}

// 검색어가 노드 또는 하위에 매칭되는지 확인
const nodeMatchesSearch = (node: CategoryValue, query: string): boolean => {
  if (!query) return true;
  const lowerQuery = query.toLowerCase();
  if (node.valueLabel.toLowerCase().includes(lowerQuery)) return true;
  if (node.valueCode.toLowerCase().includes(lowerQuery)) return true;
  if (node.children) {
    return node.children.some((child) => nodeMatchesSearch(child, query));
  }
  return false;
};

const TreeNode: React.FC<TreeNodeProps> = ({
  node,
  level,
  expandedNodes,
  selectedValueId,
  searchQuery,
  checkedIds,
  onToggle,
  onSelect,
  onAdd,
  onEdit,
  onDelete,
  onCheck,
}) => {
  const hasChildren = node.children && node.children.length > 0;
  const isExpanded = expandedNodes.has(node.valueId);
  const isSelected = selectedValueId === node.valueId;
  const isChecked = checkedIds.has(node.valueId);
  const canAddChild = node.depth < 3;

  // 검색 필터링
  if (searchQuery && !nodeMatchesSearch(node, searchQuery)) {
    return null;
  }

  // 깊이별 아이콘
  const getIcon = () => {
    if (hasChildren) {
      return isExpanded ? (
        <FolderOpen className="h-4 w-4 text-amber-500" />
      ) : (
        <Folder className="h-4 w-4 text-amber-500" />
      );
    }
    return <Tag className="h-4 w-4 text-primary" />;
  };

  // 깊이별 라벨
  const getDepthLabel = () => {
    switch (node.depth) {
      case 1:
        return "대분류";
      case 2:
        return "중분류";
      case 3:
        return "소분류";
      default:
        return "";
    }
  };

  return (
    <div>
      <div
        className={cn(
          "group flex items-center gap-1 rounded-md px-2 py-2 transition-colors",
          isSelected ? "border-primary bg-primary/10 border-l-2" : "hover:bg-muted/50",
          isChecked && "bg-primary/5",
          "cursor-pointer",
        )}
        style={{ paddingLeft: `${level * 20 + 8}px` }}
        onClick={() => onSelect(node)}
      >
        {/* 체크박스 */}
        <Checkbox
          checked={isChecked}
          onCheckedChange={(checked) => {
            onCheck(node.valueId, checked as boolean);
          }}
          onClick={(e) => e.stopPropagation()}
          className="mr-1"
        />

        {/* 확장 토글 */}
        <button
          type="button"
          className="hover:bg-muted flex h-6 w-6 items-center justify-center rounded"
          onClick={(e) => {
            e.stopPropagation();
            if (hasChildren) {
              onToggle(node.valueId);
            }
          }}
        >
          {hasChildren ? (
            isExpanded ? (
              <ChevronDown className="text-muted-foreground h-4 w-4" />
            ) : (
              <ChevronRight className="text-muted-foreground h-4 w-4" />
            )
          ) : (
            <span className="h-4 w-4" />
          )}
        </button>

        {/* 아이콘 */}
        {getIcon()}

        {/* 라벨 */}
        <div className="flex flex-1 items-center gap-2">
          <span className={cn("text-sm", node.depth === 1 && "font-medium")}>{node.valueLabel}</span>
          <span className="bg-muted text-muted-foreground rounded px-1.5 py-0.5 text-[10px]">{getDepthLabel()}</span>
        </div>

        {/* 비활성 표시 */}
        {!node.isActive && (
          <span className="bg-destructive/10 text-destructive rounded px-1.5 py-0.5 text-[10px]">비활성</span>
        )}

        {/* 액션 버튼 */}
        <div className="flex items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100">
          {canAddChild && (
            <Button
              variant="ghost"
              size="icon"
              className="h-7 w-7"
              onClick={(e) => {
                e.stopPropagation();
                onAdd(node);
              }}
              title="하위 추가"
            >
              <Plus className="h-3.5 w-3.5" />
            </Button>
          )}
          <Button
            variant="ghost"
            size="icon"
            className="h-7 w-7"
            onClick={(e) => {
              e.stopPropagation();
              onEdit(node);
            }}
            title="수정"
          >
            <Pencil className="h-3.5 w-3.5" />
          </Button>
          <Button
            variant="ghost"
            size="icon"
            className="text-destructive hover:text-destructive h-7 w-7"
            onClick={(e) => {
              e.stopPropagation();
              onDelete(node);
            }}
            title="삭제"
          >
            <Trash2 className="h-3.5 w-3.5" />
          </Button>
        </div>
      </div>

      {/* 자식 노드 */}
      {hasChildren && isExpanded && (
        <div>
          {node.children!.map((child) => (
            <TreeNode
              key={child.valueId}
              node={child}
              level={level + 1}
              expandedNodes={expandedNodes}
              selectedValueId={selectedValueId}
              searchQuery={searchQuery}
              checkedIds={checkedIds}
              onToggle={onToggle}
              onSelect={onSelect}
              onAdd={onAdd}
              onEdit={onEdit}
              onDelete={onDelete}
              onCheck={onCheck}
            />
          ))}
        </div>
      )}
    </div>
  );
};

export const CategoryValueManagerTree: React.FC<CategoryValueManagerTreeProps> = ({
  tableName,
  columnName,
  columnLabel,
  onValueCountChange,
}) => {
  // 상태
  const [tree, setTree] = useState<CategoryValue[]>([]);
  const [loading, setLoading] = useState(false);
  const [expandedNodes, setExpandedNodes] = useState<Set<number>>(new Set());
  const [selectedValue, setSelectedValue] = useState<CategoryValue | null>(null);
  const [searchQuery, setSearchQuery] = useState("");
  const [showInactive, setShowInactive] = useState(false);
  const [checkedIds, setCheckedIds] = useState<Set<number>>(new Set());

  // 모달 상태
  const [isAddModalOpen, setIsAddModalOpen] = useState(false);
  const [isEditModalOpen, setIsEditModalOpen] = useState(false);
  const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
  const [isBulkDeleteDialogOpen, setIsBulkDeleteDialogOpen] = useState(false);
  const [parentValue, setParentValue] = useState<CategoryValue | null>(null);
  const [editingValue, setEditingValue] = useState<CategoryValue | null>(null);
  const [deletingValue, setDeletingValue] = useState<CategoryValue | null>(null);

  // 추가 모달 input ref
  const addNameRef = useRef<HTMLInputElement>(null);
  const addDescRef = useRef<HTMLInputElement>(null);

  // 폼 상태
  const [formData, setFormData] = useState({
    valueCode: "",
    valueLabel: "",
    description: "",
    color: "",
    isActive: true,
  });

  // 전체 값 개수 계산
  const countAllValues = useCallback((nodes: CategoryValue[]): number => {
    let count = nodes.length;
    for (const node of nodes) {
      if (node.children) {
        count += countAllValues(node.children);
      }
    }
    return count;
  }, []);


  // 활성 노드만 필터링
  const filterActiveNodes = useCallback((nodes: CategoryValue[]): CategoryValue[] => {
    return nodes
      .filter((node) => node.isActive !== false)
      .map((node) => ({
        ...node,
        children: node.children ? filterActiveNodes(node.children) : undefined,
      }));
  }, []);

  // 데이터 로드 (keepExpanded: true면 기존 펼침 상태 유지)
  const loadTree = useCallback(
    async (keepExpanded = false) => {
      if (!tableName || !columnName) return;

      setLoading(true);
      try {
        const response = await getCategoryTree(tableName, columnName);
        if (response.success && response.data) {
          let filteredTree = response.data;

          // 비활성 필터링
          if (!showInactive) {
            filteredTree = filterActiveNodes(response.data);
          }

          setTree(filteredTree);

          // 기존 펼침 상태 유지하지 않으면 모두 접기 (대분류만 표시)
          if (!keepExpanded) {
            setExpandedNodes(new Set());
          }

          // 전체 개수 업데이트
          const totalCount = countAllValues(response.data);
          onValueCountChange?.(totalCount);
        }
      } catch (error) {
        console.error("카테고리 트리 로드 오류:", error);
      } finally {
        setLoading(false);
      }
    },
    [tableName, columnName, showInactive, countAllValues, filterActiveNodes, onValueCountChange],
  );

  useEffect(() => {
    loadTree();
  }, [loadTree]);

  // 모든 노드 펼치기
  const expandAll = () => {
    const allIds = new Set<number>();
    const collectIds = (nodes: CategoryValue[]) => {
      for (const node of nodes) {
        allIds.add(node.valueId);
        if (node.children) {
          collectIds(node.children);
        }
      }
    };
    collectIds(tree);
    setExpandedNodes(allIds);
  };

  // 모든 노드 접기
  const collapseAll = () => {
    setExpandedNodes(new Set());
  };

  // 토글 핸들러
  const handleToggle = (valueId: number) => {
    setExpandedNodes((prev) => {
      const next = new Set(prev);
      if (next.has(valueId)) {
        next.delete(valueId);
      } else {
        next.add(valueId);
      }
      return next;
    });
  };

  // 체크박스 핸들러
  const handleCheck = useCallback((valueId: number, checked: boolean) => {
    setCheckedIds((prev) => {
      const next = new Set(prev);
      if (checked) {
        next.add(valueId);
      } else {
        next.delete(valueId);
      }
      return next;
    });
  }, []);

  // 전체 선택/해제
  const handleSelectAll = useCallback(() => {
    if (checkedIds.size === countAllValues(tree)) {
      setCheckedIds(new Set());
    } else {
      const allIds = new Set<number>();
      const collectAllIds = (nodes: CategoryValue[]) => {
        for (const node of nodes) {
          allIds.add(node.valueId);
          if (node.children) {
            collectAllIds(node.children);
          }
        }
      };
      collectAllIds(tree);
      setCheckedIds(allIds);
    }
  }, [checkedIds.size, tree, countAllValues]);

  // 선택 해제
  const handleClearSelection = useCallback(() => {
    setCheckedIds(new Set());
  }, []);

  // 추가 모달 열기
  const handleOpenAddModal = (parent: CategoryValue | null) => {
    setParentValue(parent);
    setFormData({
      valueCode: "",
      valueLabel: "",
      description: "",
      color: "",
      isActive: true,
    });
    setIsAddModalOpen(true);
  };

  // 수정 모달 열기
  const handleOpenEditModal = (value: CategoryValue) => {
    setEditingValue(value);
    setFormData({
      valueCode: value.valueCode,
      valueLabel: value.valueLabel,
      description: value.description || "",
      color: value.color || "",
      isActive: value.isActive,
    });
    setIsEditModalOpen(true);
  };

  // 삭제 다이얼로그 열기 (사전 확인 후)
  const handleOpenDeleteDialog = async (value: CategoryValue) => {
    try {
      const response = await checkCanDeleteCategoryValue(value.valueId);
      if (response.success && response.data) {
        if (!response.data.canDelete) {
          toast.error(response.data.reason || "이 카테고리는 삭제할 수 없습니다");
          return;
        }
      }
    } catch {
      // 사전 확인 실패 시에도 다이얼로그는 열어줌 (삭제 시 백엔드에서 재검증)
    }

    setDeletingValue(value);
    setIsDeleteDialogOpen(true);
  };

  // 코드 자동 생성 함수
  const generateCode = () => {
    const timestamp = Date.now().toString(36).toUpperCase();
    const random = Math.random().toString(36).substring(2, 6).toUpperCase();
    return `CAT_${timestamp}_${random}`;
  };

  // 추가 처리
  const handleAdd = async () => {
    if (!formData.valueLabel) {
      toast.error("이름은 필수입니다");
      return;
    }

    try {
      // 코드 자동 생성
      const autoCode = generateCode();

      const input: CreateCategoryValueInput = {
        tableName,
        columnName,
        valueCode: autoCode,
        valueLabel: formData.valueLabel,
        parentValueId: parentValue?.valueId || null,
        description: formData.description || undefined,
        color: formData.color || undefined,
        isActive: formData.isActive,
      };

      const response = await createCategoryValue(input);
      if (response.success) {
        toast.success("카테고리가 추가되었습니다");
        // 폼 초기화 (모달은 닫지 않고 연속 입력)
        setFormData((prev) => ({
          ...prev,
          valueCode: "",
          valueLabel: "",
          description: "",
          color: "",
        }));
        setTimeout(() => addNameRef.current?.focus(), 50);
        // 기존 펼침 상태 유지하면서 데이터 새로고침
        await loadTree(true);
        // 부모 노드만 펼치기 (하위 추가 시)
        if (parentValue) {
          setExpandedNodes((prev) => new Set([...prev, parentValue.valueId]));
        }
      } else {
        toast.error(response.error || "추가 실패");
      }
    } catch (error) {
      console.error("카테고리 추가 오류:", error);
      toast.error("카테고리 추가 중 오류가 발생했습니다");
    }
  };

  // 수정 처리
  const handleEdit = async () => {
    if (!editingValue) return;

    try {
      // 코드는 변경하지 않음 (기존 코드 유지)
      const response = await updateCategoryValue(editingValue.valueId, {
        valueLabel: formData.valueLabel,
        description: formData.description || undefined,
        color: formData.color || undefined,
        isActive: formData.isActive,
      });

      if (response.success) {
        toast.success("카테고리가 수정되었습니다");
        setIsEditModalOpen(false);
        loadTree(true); // 기존 펼침 상태 유지
      } else {
        toast.error(response.error || "수정 실패");
      }
    } catch (error) {
      console.error("카테고리 수정 오류:", error);
      toast.error("카테고리 수정 중 오류가 발생했습니다");
    }
  };

  // 삭제 처리
  const handleDelete = async () => {
    if (!deletingValue) return;

    try {
      const response = await deleteCategoryValue(deletingValue.valueId);
      if (response.success) {
        toast.success("카테고리가 삭제되었습니다");
        setIsDeleteDialogOpen(false);
        setSelectedValue(null);
        setCheckedIds((prev) => {
          const next = new Set(prev);
          next.delete(deletingValue.valueId);
          return next;
        });
        loadTree(true); // 기존 펼침 상태 유지
      } else {
        toast.error(response.error || "삭제 실패");
      }
    } catch (error) {
      console.error("카테고리 삭제 오류:", error);
      toast.error("카테고리 삭제 중 오류가 발생했습니다");
    }
  };

  // 다중 삭제 처리
  const handleBulkDelete = async () => {
    if (checkedIds.size === 0) return;

    try {
      let successCount = 0;
      let failCount = 0;
      const failMessages: string[] = [];

      for (const valueId of Array.from(checkedIds)) {
        try {
          const response = await deleteCategoryValue(valueId);
          if (response.success) {
            successCount++;
          } else {
            failCount++;
            if (response.error) failMessages.push(response.error);
          }
        } catch {
          failCount++;
        }
      }

      setIsBulkDeleteDialogOpen(false);
      setCheckedIds(new Set());
      setSelectedValue(null);
      loadTree(true);

      if (failCount === 0) {
        toast.success(`${successCount}개 카테고리가 삭제되었습니다`);
      } else if (successCount === 0) {
        toast.error(`삭제할 수 없습니다: ${failMessages[0] || "삭제 실패"}`);
      } else {
        toast.warning(`${successCount}개 삭제 성공, ${failCount}개 삭제 실패 (사용 중이거나 하위 항목 존재)`);
      }
    } catch (error) {
      console.error("카테고리 일괄 삭제 오류:", error);
      toast.error("카테고리 일괄 삭제 중 오류가 발생했습니다");
    }
  };

  return (
    <div className="flex h-full flex-col">
      {/* 헤더 */}
      <div className="mb-3 flex items-center justify-between border-b pb-3">
        <div className="flex items-center gap-2">
          <h3 className="text-base font-semibold">{columnLabel} 카테고리</h3>
          {checkedIds.size > 0 && (
            <span className="bg-primary/10 text-primary rounded-full px-2 py-0.5 text-xs">
              {checkedIds.size}개 선택
            </span>
          )}
        </div>
        <div className="flex items-center gap-2">
          {checkedIds.size > 0 && (
            <>
              <Button variant="outline" size="sm" className="h-8 text-xs" onClick={handleClearSelection}>
                선택 해제
              </Button>
              <Button
                variant="destructive"
                size="sm"
                className="h-8 gap-1.5 text-xs"
                onClick={() => setIsBulkDeleteDialogOpen(true)}
              >
                <Trash2 className="h-3.5 w-3.5" />
                선택 삭제
              </Button>
            </>
          )}
          <Button variant="default" size="sm" className="h-8 gap-1.5 text-xs" onClick={() => handleOpenAddModal(null)}>
            <Plus className="h-3.5 w-3.5" />
            대분류 추가
          </Button>
        </div>
      </div>

      {/* 툴바 */}
      <div className="mb-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
        {/* 검색 */}
        <div className="relative max-w-xs flex-1">
          <Search className="text-muted-foreground absolute top-1/2 left-2.5 h-4 w-4 -translate-y-1/2" />
          <Input
            placeholder="검색..."
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            className="h-8 pl-8 text-sm"
          />
        </div>

        {/* 옵션 */}
        <div className="flex items-center gap-3">
          <div className="flex items-center gap-2">
            <Switch id="showInactive" checked={showInactive} onCheckedChange={setShowInactive} />
            <Label htmlFor="showInactive" className="cursor-pointer text-xs">
              비활성 표시
            </Label>
          </div>

          <div className="flex items-center gap-1">
            <Button variant="ghost" size="sm" className="h-7 text-xs" onClick={handleSelectAll}>
              {checkedIds.size === countAllValues(tree) && tree.length > 0 ? "전체 해제" : "전체 선택"}
            </Button>
            <Button variant="ghost" size="sm" className="h-7 text-xs" onClick={expandAll}>
              전체 펼침
            </Button>
            <Button variant="ghost" size="sm" className="h-7 text-xs" onClick={collapseAll}>
              전체 접기
            </Button>
            <Button variant="ghost" size="icon" className="h-7 w-7" onClick={() => loadTree()} title="새로고침">
              <RefreshCw className="h-3.5 w-3.5" />
            </Button>
          </div>
        </div>
      </div>

      {/* 트리 */}
      <div className="bg-card min-h-[300px] flex-1 overflow-y-auto rounded-md border">
        {loading ? (
          <div className="flex h-full items-center justify-center">
            <div className="text-muted-foreground text-sm">로딩 중...</div>
          </div>
        ) : tree.length === 0 ? (
          <div className="flex h-full flex-col items-center justify-center p-6 text-center">
            <Folder className="text-muted-foreground/30 mb-3 h-12 w-12" />
            <p className="text-muted-foreground text-sm">카테고리가 없습니다</p>
            <p className="text-muted-foreground mt-1 text-xs">상단의 대분류 추가 버튼을 클릭하여 시작하세요</p>
          </div>
        ) : (
          <div className="p-2">
            {tree.map((node) => (
              <TreeNode
                key={node.valueId}
                node={node}
                level={0}
                expandedNodes={expandedNodes}
                selectedValueId={selectedValue?.valueId}
                searchQuery={searchQuery}
                checkedIds={checkedIds}
                onToggle={handleToggle}
                onSelect={setSelectedValue}
                onAdd={handleOpenAddModal}
                onEdit={handleOpenEditModal}
                onDelete={handleOpenDeleteDialog}
                onCheck={handleCheck}
              />
            ))}
          </div>
        )}
      </div>

      {/* 추가 모달 */}
      <Dialog open={isAddModalOpen} onOpenChange={setIsAddModalOpen}>
        <DialogContent className="max-w-[95vw] sm:max-w-[450px]">
          <DialogHeader>
            <DialogTitle className="text-base sm:text-lg">
              {parentValue ? `"${parentValue.valueLabel}" 하위 추가` : "대분류 추가"}
            </DialogTitle>
            <DialogDescription className="text-xs sm:text-sm">
              {parentValue
                ? `${parentValue.depth + 1}단계 카테고리를 추가합니다`
                : "1단계 대분류 카테고리를 추가합니다"}
            </DialogDescription>
          </DialogHeader>

          <div className="space-y-4">
            <div>
              <Label htmlFor="valueLabel" className="text-xs sm:text-sm">
                이름 <span className="text-destructive">*</span>
              </Label>
              <Input
                ref={addNameRef}
                id="valueLabel"
                value={formData.valueLabel}
                onChange={(e) => setFormData({ ...formData, valueLabel: e.target.value })}
                onKeyDown={(e) => {
                  if (e.key === "Enter") {
                    e.preventDefault();
                    e.stopPropagation();
                    addDescRef.current?.focus();
                  }
                }}
                placeholder="카테고리 이름을 입력하세요"
                className="h-9 text-sm"
              />
              <p className="text-muted-foreground mt-1 text-[10px]">코드는 자동으로 생성됩니다</p>
            </div>
            <div>
              <Label htmlFor="description" className="text-xs sm:text-sm">
                설명
              </Label>
              <Input
                ref={addDescRef}
                id="description"
                value={formData.description}
                onChange={(e) => setFormData({ ...formData, description: e.target.value })}
                onKeyDown={(e) => {
                  if (e.key === "Enter") {
                    e.preventDefault();
                    e.stopPropagation();
                    handleAdd();
                  }
                }}
                placeholder="선택 사항"
                className="h-9 text-sm"
              />
            </div>
            <div className="flex items-center gap-2">
              <Switch
                id="isActive"
                checked={formData.isActive}
                onCheckedChange={(checked) => setFormData({ ...formData, isActive: checked })}
              />
              <Label htmlFor="isActive" className="cursor-pointer text-sm">
                활성 상태
              </Label>
            </div>
          </div>

          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              variant="outline"
              onClick={() => setIsAddModalOpen(false)}
              className="h-9 flex-1 text-sm sm:flex-none"
            >
              닫기
            </Button>
            <Button onClick={handleAdd} className="h-9 flex-1 text-sm sm:flex-none">
              추가
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 수정 모달 */}
      <Dialog open={isEditModalOpen} onOpenChange={setIsEditModalOpen}>
        <DialogContent className="max-w-[95vw] sm:max-w-[450px]">
          <DialogHeader>
            <DialogTitle className="text-base sm:text-lg">카테고리 수정</DialogTitle>
            <DialogDescription className="text-xs sm:text-sm">카테고리 정보를 수정합니다</DialogDescription>
          </DialogHeader>

          <div className="space-y-4">
            <div>
              <Label htmlFor="editValueLabel" className="text-xs sm:text-sm">
                이름 <span className="text-destructive">*</span>
              </Label>
              <Input
                id="editValueLabel"
                value={formData.valueLabel}
                onChange={(e) => setFormData({ ...formData, valueLabel: e.target.value })}
                className="h-9 text-sm"
              />
            </div>
            <div>
              <Label htmlFor="editDescription" className="text-xs sm:text-sm">
                설명
              </Label>
              <Input
                id="editDescription"
                value={formData.description}
                onChange={(e) => setFormData({ ...formData, description: e.target.value })}
                className="h-9 text-sm"
              />
            </div>
            <div className="flex items-center gap-2">
              <Switch
                id="editIsActive"
                checked={formData.isActive}
                onCheckedChange={(checked) => setFormData({ ...formData, isActive: checked })}
              />
              <Label htmlFor="editIsActive" className="cursor-pointer text-sm">
                활성 상태
              </Label>
            </div>
          </div>

          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              variant="outline"
              onClick={() => setIsEditModalOpen(false)}
              className="h-9 flex-1 text-sm sm:flex-none"
            >
              취소
            </Button>
            <Button onClick={handleEdit} className="h-9 flex-1 text-sm sm:flex-none">
              저장
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 삭제 확인 다이얼로그 */}
      <AlertDialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>카테고리 삭제</AlertDialogTitle>
            <AlertDialogDescription>
              <strong>{deletingValue?.valueLabel}</strong>을(를) 삭제하시겠습니까?
              <br />
              <span className="text-muted-foreground text-xs">삭제된 카테고리는 복구할 수 없습니다.</span>
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>취소</AlertDialogCancel>
            <AlertDialogAction
              onClick={handleDelete}
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
            >
              삭제
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {/* 다중 삭제 확인 다이얼로그 */}
      <AlertDialog open={isBulkDeleteDialogOpen} onOpenChange={setIsBulkDeleteDialogOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>카테고리 일괄 삭제</AlertDialogTitle>
            <AlertDialogDescription>
              선택한 <strong>{checkedIds.size}개</strong> 카테고리를 삭제하시겠습니까?
              <br />
              <span className="text-muted-foreground text-xs">삭제된 카테고리는 복구할 수 없습니다.</span>
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>취소</AlertDialogCancel>
            <AlertDialogAction
              onClick={handleBulkDelete}
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
            >
              {checkedIds.size}개 삭제
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
};

export default CategoryValueManagerTree;
