"use client";

import React, { useState, useEffect } from "react";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command";
import { Loader2, Copy, Link as LinkIcon, Trash2, AlertCircle, AlertTriangle, Check, ChevronsUpDown, FolderTree, Hash, Table, Settings } from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox";
import { ScreenDefinition } from "@/types/screen";
import { screenApi, updateTabScreenReferences } from "@/lib/api/screen";
import { ScreenGroup, addScreenToGroup, createScreenGroup } from "@/lib/api/screenGroup";
import { apiClient } from "@/lib/api/client";
import { toast } from "sonner";
import { useAuth } from "@/hooks/useAuth";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { cn } from "@/lib/utils";

// 정규식 특수문자 이스케이프 헬퍼 함수
const escapeRegExp = (str: string): string => {
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
};

interface LinkedModalScreen {
  screenId: number;
  screenName: string;
  screenCode: string;
  newScreenName?: string;
  newScreenCode?: string;
}

interface CompanyInfo {
  companyCode: string;
  companyName: string;
}

interface CopyScreenModalProps {
  isOpen: boolean;
  onClose: () => void;
  sourceScreen: ScreenDefinition | null;
  onCopySuccess: () => void | Promise<void>;
  // 트리 구조 지원용 추가 props
  mode?: "screen" | "group"; // 단일 화면 복제 또는 그룹 복제
  sourceGroup?: ScreenGroup | null; // 그룹 복제 시 원본 그룹
  groups?: ScreenGroup[]; // 대상 그룹 목록
  targetGroupId?: number | null; // 초기 선택된 대상 그룹
  allScreens?: ScreenDefinition[]; // 그룹 복제 시 사용할 전체 화면 목록
}

export default function CopyScreenModal({
  isOpen,
  onClose,
  sourceScreen,
  onCopySuccess,
  mode = "screen",
  sourceGroup,
  groups = [],
  targetGroupId: initialTargetGroupId,
  allScreens = [],
}: CopyScreenModalProps) {
  const { user } = useAuth();
  // 최고 관리자 판별: userType이 "SUPER_ADMIN" 또는 companyCode가 "*"
  const isSuperAdmin = user?.userType === "SUPER_ADMIN" || user?.companyCode === "*";

  // 디버깅: 사용자 정보 확인
  useEffect(() => {
    console.log("🔍 CopyScreenModal - User Info:", {
      user,
      isSuperAdmin,
      userType: user?.userType,
      companyCode: user?.companyCode,
      조건1: user?.userType === "SUPER_ADMIN",
      조건2: user?.companyCode === "*",
      최종판별: user?.userType === "SUPER_ADMIN" || user?.companyCode === "*",
    });
  }, [user, isSuperAdmin]);

  // 메인 화면 복사 정보
  const [screenName, setScreenName] = useState("");
  const [screenCode, setScreenCode] = useState("");
  const [description, setDescription] = useState("");

  // 대상 그룹 선택 (트리 구조용)
  const [selectedTargetGroupId, setSelectedTargetGroupId] = useState<number | null>(null);
  const [isGroupSelectOpen, setIsGroupSelectOpen] = useState(false);

  // 그룹 복제용 상태
  const [newGroupName, setNewGroupName] = useState("");
  const [groupParentId, setGroupParentId] = useState<number | null>(null);
  const [isParentGroupSelectOpen, setIsParentGroupSelectOpen] = useState(false);
  const [groupDisplayOrder, setGroupDisplayOrder] = useState<number>(0);

  // 그룹 일괄 이름 변경 (고급 옵션) - 찾기/대체 방식
  const [useGroupBulkRename, setUseGroupBulkRename] = useState(false);
  const [groupFindText, setGroupFindText] = useState(""); // 찾을 텍스트
  const [groupReplaceText, setGroupReplaceText] = useState(""); // 대체할 텍스트

  // 대상 회사 선택 (최고 관리자 전용)
  const [targetCompanyCode, setTargetCompanyCode] = useState<string>("");
  const [companies, setCompanies] = useState<CompanyInfo[]>([]);
  const [loadingCompanies, setLoadingCompanies] = useState(false);

  // 연결된 모달 화면들
  const [linkedScreens, setLinkedScreens] = useState<LinkedModalScreen[]>([]);
  const [loadingLinkedScreens, setLoadingLinkedScreens] = useState(false);

  // 화면명 일괄 수정 기능
  const [useBulkRename, setUseBulkRename] = useState(false);
  const [removeText, setRemoveText] = useState("");
  const [addPrefix, setAddPrefix] = useState("");

  // 그룹 복제 모드: "all" (전체), "folder_only" (폴더만), "screen_only" (화면만)
  const [groupCopyMode, setGroupCopyMode] = useState<"all" | "folder_only" | "screen_only">("all");

  // 채번규칙 복제 옵션 (체크 시: 복제 → 메뉴 동기화 → 채번규칙 복제 순서로 실행)
  const [copyNumberingRules, setCopyNumberingRules] = useState(false);
  
  // 추가 복사 옵션들
  const [copyCategoryValues, setCopyCategoryValues] = useState(false); // 카테고리 값 복사
  const [copyTableTypeColumns, setCopyTableTypeColumns] = useState(false); // 테이블 타입관리 입력타입 설정 복사

  // 복사 중 상태
  const [isCopying, setIsCopying] = useState(false);
  const [copyProgress, setCopyProgress] = useState({ current: 0, total: 0, message: "" });

  // 최고 관리자인 경우 회사 목록 조회
  useEffect(() => {
    console.log("🔍 회사 목록 조회 체크:", { isSuperAdmin, isOpen });
    if (isSuperAdmin && isOpen) {
      console.log("✅ 회사 목록 조회 시작");
      loadCompanies();
    }
  }, [isSuperAdmin, isOpen]);

  // 모달이 열릴 때 초기값 설정 및 연결된 화면 감지
  useEffect(() => {
    console.log("🔍 모달 초기화:", { isOpen, sourceScreen, sourceGroup, mode, isSuperAdmin });
    
    if (isOpen && mode === "screen" && sourceScreen) {
      // 단일 화면 복제 모드
      setScreenName(`${sourceScreen.screenName} (복사본)`);
      setDescription(sourceScreen.description || "");

      // 대상 회사 코드 설정
      if (isSuperAdmin) {
        setTargetCompanyCode(sourceScreen.companyCode);
      } else {
        setTargetCompanyCode(sourceScreen.companyCode);
      }

      // 대상 그룹 초기화 (전달받은 값 또는 null)
      setSelectedTargetGroupId(initialTargetGroupId ?? null);

      // 연결된 모달 화면 감지
      console.log("✅ 연결된 모달 화면 감지 시작");
      detectLinkedModals();
    } else if (isOpen && mode === "group" && sourceGroup) {
      // 그룹 복제 모드
      
      // 1. 그룹명 중복 체크 - 같은 부모 그룹 내에 동일한 이름이 있는지 확인
      const parentId = sourceGroup.parent_group_id;
      const siblingGroups = groups.filter(g => g.parent_group_id === parentId);
      const existingNames = siblingGroups.map(g => g.group_name);
      
      let newName = sourceGroup.group_name;
      if (existingNames.includes(newName)) {
        // 겹치는 이름이 있으면 "(복제)" 추가
        newName = `${sourceGroup.group_name} (복제)`;
        // "(복제)"도 겹치면 숫자 추가
        let copyNum = 2;
        while (existingNames.includes(newName)) {
          newName = `${sourceGroup.group_name} (복제 ${copyNum})`;
          copyNum++;
        }
      }
      setNewGroupName(newName);
      
      setGroupParentId(sourceGroup.parent_group_id ?? null);
      
      // 2. 상위 그룹의 회사 코드로 대상 회사 자동 설정
      let autoCompanyCode = sourceGroup.company_code || "";
      if (sourceGroup.parent_group_id) {
        const parentGroup = groups.find(g => g.id === sourceGroup.parent_group_id);
        if (parentGroup?.company_code) {
          autoCompanyCode = parentGroup.company_code;
        }
      }
      setTargetCompanyCode(autoCompanyCode);
      
      setGroupDisplayOrder(sourceGroup.display_order ?? 0);
      setUseGroupBulkRename(false);
      setGroupFindText("");
      setGroupReplaceText("");
      setGroupCopyMode("all");
    }
  }, [isOpen, sourceScreen, sourceGroup, mode, isSuperAdmin, initialTargetGroupId]);

  // 일괄 변경 설정이 변경될 때 화면명 자동 업데이트
  useEffect(() => {
    if (!sourceScreen) return;

    if (useBulkRename) {
      // 일괄 수정 사용 시: (복사본) 텍스트 제거
      const newMainName = applyBulkRename(sourceScreen.screenName);
      setScreenName(newMainName);

      // 모달 화면명 업데이트
      setLinkedScreens((prev) =>
        prev.map((screen) => ({
          ...screen,
          newScreenName: applyBulkRename(screen.screenName),
        }))
      );
    } else {
      // 일괄 수정 미사용 시: (복사본) 텍스트 추가
      setScreenName(`${sourceScreen.screenName} (복사본)`);
      
      setLinkedScreens((prev) =>
        prev.map((screen) => ({
          ...screen,
          newScreenName: screen.screenName,
        }))
      );
    }
  }, [useBulkRename, removeText, addPrefix]);

  // 대상 회사 변경 시 기존 코드 초기화
  useEffect(() => {
    if (targetCompanyCode) {
      console.log("🔄 회사 변경 → 기존 코드 초기화:", targetCompanyCode);
      setScreenCode("");
      // 모달 화면들의 코드도 초기화
      setLinkedScreens((prev) =>
        prev.map((screen) => ({ ...screen, newScreenCode: undefined }))
      );
    }
  }, [targetCompanyCode]);

  // linkedScreens 로딩이 완료되면 화면 코드 생성
  useEffect(() => {
    // 모달 화면들의 코드가 모두 설정되었는지 확인
    const allModalCodesSet = linkedScreens.length === 0 || 
      linkedScreens.every(screen => screen.newScreenCode);
    
    console.log("🔍 코드 생성 조건 체크:", {
      targetCompanyCode,
      loadingLinkedScreens,
      screenCode,
      linkedScreensCount: linkedScreens.length,
      allModalCodesSet,
    });
    
    // 조건: 회사 코드가 있고, 로딩이 완료되고, (메인 코드가 없거나 모달 코드가 없을 때)
    const needsCodeGeneration = targetCompanyCode && 
      !loadingLinkedScreens && 
      (!screenCode || (linkedScreens.length > 0 && !allModalCodesSet));
    
    if (needsCodeGeneration) {
      console.log("✅ 화면 코드 생성 시작 (linkedScreens 개수:", linkedScreens.length, ")");
      generateScreenCodes();
    }
  }, [targetCompanyCode, loadingLinkedScreens, screenCode, linkedScreens]);

  // 회사 목록 조회
  const loadCompanies = async () => {
    try {
      setLoadingCompanies(true);
      const response = await apiClient.get("/admin/companies");
      console.log("📋 회사 목록 API 응답:", response.data);
      const data = response.data.data || response.data || [];
      console.log("📋 회사 목록 데이터:", data);
      const mappedCompanies = data.map((c: any) => ({
        companyCode: c.company_code || c.companyCode,
        companyName: c.company_name || c.companyName,
      }));
      console.log("📋 매핑된 회사 목록:", mappedCompanies);
      setCompanies(mappedCompanies);
    } catch (error) {
      console.error("회사 목록 조회 실패:", error);
      toast.error("회사 목록을 불러오는데 실패했습니다.");
    } finally {
      setLoadingCompanies(false);
    }
  };

  // 연결된 모달 화면 감지
  const detectLinkedModals = async () => {
    if (!sourceScreen) return;

    try {
      setLoadingLinkedScreens(true);
      console.log("📡 API 호출: detectLinkedModals", sourceScreen.screenId);
      const linked = await screenApi.detectLinkedModals(sourceScreen.screenId);
      console.log("✅ 연결된 모달 화면 감지 결과:", linked);
      
      // 초기 newScreenName 설정
      setLinkedScreens(
        linked.map((screen) => ({
          ...screen,
          newScreenName: `${screen.screenName} (복사본)`,
        }))
      );

      if (linked.length > 0) {
        toast.info(`${linked.length}개의 연결된 모달 화면을 감지했습니다.`);
        console.log("🎉 감지된 화면들:", linked);
      } else {
        console.log("ℹ️ 연결된 모달 화면이 없습니다.");
      }
    } catch (error) {
      console.error("❌ 연결된 화면 감지 실패:", error);
      // 에러가 나도 진행 가능하도록 무시
    } finally {
      setLoadingLinkedScreens(false);
    }
  };

  // 화면 코드 자동 생성 (메인 + 모달 화면들) - 일괄 생성으로 중복 방지
  const generateScreenCodes = async () => {
    if (!targetCompanyCode) {
      console.log("❌ targetCompanyCode가 없어서 화면 코드 생성 중단");
      return;
    }

    try {
      // 메인 화면 1개 + 연결된 모달 화면들 = 총 개수
      const totalCount = 1 + linkedScreens.length;
      console.log(`📡 화면 코드 일괄 생성 API 호출: ${targetCompanyCode}, 개수: ${totalCount}`);

      // 한 번에 모든 코드 생성 (중복 방지)
      const generatedCodes = await screenApi.generateMultipleScreenCodes(
        targetCompanyCode,
        totalCount
      );
      console.log("✅ 생성된 화면 코드들:", generatedCodes);

      // 첫 번째 코드는 메인 화면용
      setScreenCode(generatedCodes[0]);
      console.log("✅ 메인 화면 코드:", generatedCodes[0]);

      // 나머지 코드들은 모달 화면들에 순서대로 할당
      if (linkedScreens.length > 0) {
        const updatedLinkedScreens = linkedScreens.map((screen, index) => ({
          ...screen,
          newScreenCode: generatedCodes[index + 1], // 1번째부터 시작
        }));

        setLinkedScreens(updatedLinkedScreens);
        console.log("✅ 모달 화면 코드 할당 완료:", updatedLinkedScreens.map(s => ({
          name: s.screenName,
          code: s.newScreenCode
        })));
      }
    } catch (error) {
      console.error("❌ 화면 코드 일괄 생성 실패:", error);
      toast.error("화면 코드 생성에 실패했습니다.");
    }
  };

  // 연결된 화면 이름 변경
  const updateLinkedScreenName = (screenId: number, newName: string) => {
    setLinkedScreens((prev) =>
      prev.map((screen) =>
        screen.screenId === screenId ? { ...screen, newScreenName: newName } : screen
      )
    );
  };

  // 연결된 화면 제거 (복사하지 않음)
  const removeLinkedScreen = (screenId: number) => {
    setLinkedScreens((prev) => prev.filter((screen) => screen.screenId !== screenId));
  };

  // 화면명 일괄 변경 적용
  const applyBulkRename = (originalName: string): string => {
    if (!useBulkRename) return originalName;
    
    let newName = originalName;
    
    // 1. 제거할 텍스트 제거
    if (removeText.trim()) {
      newName = newName.replace(new RegExp(escapeRegExp(removeText.trim()), "g"), "");
      newName = newName.trim(); // 앞뒤 공백 제거
    }
    
    // 2. 접두사 추가
    if (addPrefix.trim()) {
      newName = addPrefix.trim() + " " + newName;
    }
    
    return newName;
  };

  // 미리보기: 변경될 화면명들
  const getPreviewNames = () => {
    if (!sourceScreen || !useBulkRename) return null;

    return {
      main: {
        original: sourceScreen.screenName,
        preview: applyBulkRename(sourceScreen.screenName), // (복사본) 없음
      },
      modals: linkedScreens.map((screen) => ({
        original: screen.screenName,
        preview: applyBulkRename(screen.screenName),
      })),
    };
  };

  // 그룹 경로 가져오기
  const getGroupPath = (groupId: number | null): string => {
    if (groupId === null) return "";
    const group = groups.find((g) => g.id === groupId);
    if (!group) return "";
    
    const path: string[] = [group.group_name];
    let currentParentId = group.parent_group_id;
    
    while (currentParentId) {
      const parent = groups.find((g) => g.id === currentParentId);
      if (parent) {
        path.unshift(parent.group_name);
        currentParentId = parent.parent_group_id;
      } else {
        break;
      }
    }
    
    return path.join(" > ");
  };

  // 그룹 레벨 가져오기 (들여쓰기용)
  const getGroupLevel = (groupId: number | null): number => {
    if (groupId === null) return 0;
    const group = groups.find((g) => g.id === groupId);
    if (!group) return 0;
    
    let level = 0;
    let currentParentId = group.parent_group_id;
    
    while (currentParentId) {
      level++;
      const parent = groups.find((g) => g.id === currentParentId);
      if (parent) {
        currentParentId = parent.parent_group_id;
      } else {
        break;
      }
    }
    
    return level;
  };

  // 그룹 정렬 (계층 구조 유지)
  const getSortedGroups = (): ScreenGroup[] => {
    if (!groups || groups.length === 0) return [];
    
    const result: ScreenGroup[] = [];
    
    const addChildren = (parentId: number | null | undefined) => {
      const children = groups.filter((g) => 
        (g.parent_group_id === parentId) || 
        (parentId === null && !g.parent_group_id)
      );
      for (const child of children) {
        result.push(child);
        addChildren(child.id);
      }
    };
    
    addChildren(null);
    
    // 정렬 결과가 비어있으면 원본 그룹 반환 (parent_group_id가 없는 경우)
    return result.length > 0 ? result : groups;
  };

  // 고유한 화면코드 생성 (중복 시 _COPY 추가)
  const generateUniqueScreenCode = (baseCode: string, existingCodes: Set<string>): string => {
    let newCode = `${baseCode}_COPY`;
    while (existingCodes.has(newCode)) {
      newCode = `${newCode}_COPY`;
    }
    return newCode;
  };

  // 화면 복사 실행
  const handleCopy = async () => {
    if (!sourceScreen) return;

    // 입력값 검증
    if (!screenName.trim()) {
      toast.error("화면명을 입력해주세요.");
      return;
    }

    if (!screenCode.trim()) {
      toast.error("화면 코드 생성에 실패했습니다. 잠시 후 다시 시도해주세요.");
      return;
    }

    // 연결된 화면들의 이름 검증
    for (const linked of linkedScreens) {
      if (!linked.newScreenName?.trim()) {
        toast.error(`"${linked.screenName}" 모달 화면의 새 이름을 입력해주세요.`);
        return;
      }
      if (!linked.newScreenCode?.trim()) {
        toast.error(`"${linked.screenName}" 모달 화면의 코드가 생성되지 않았습니다.`);
        return;
      }
    }

    try {
      setIsCopying(true);

      // 화면명 중복 체크
      const companyCode = targetCompanyCode || sourceScreen.companyCode;
      
      // 메인 화면명 중복 체크
      const isMainDuplicate = await screenApi.checkDuplicateScreenName(
        companyCode,
        screenName.trim()
      );
      
      if (isMainDuplicate) {
        toast.error(`"${screenName}" 화면명이 이미 존재합니다. 다른 이름을 입력해주세요.`);
        setIsCopying(false);
        return;
      }

      // 모달 화면명 중복 체크
      for (const linked of linkedScreens) {
        const isModalDuplicate = await screenApi.checkDuplicateScreenName(
          companyCode,
          linked.newScreenName!.trim()
        );
        if (isModalDuplicate) {
          toast.error(
            `"${linked.newScreenName}" 화면명이 이미 존재합니다. 모달 화면의 이름을 변경해주세요.`
          );
          setIsCopying(false);
          return;
        }
      }

      // 메인 화면 + 모달 화면들 일괄 복사
      const result = await screenApi.copyScreenWithModals(sourceScreen.screenId, {
        targetCompanyCode: targetCompanyCode || undefined, // 최고 관리자: 대상 회사 전달
        mainScreen: {
          screenName: screenName.trim(),
          screenCode: screenCode.trim(),
          description: description.trim(),
        },
        modalScreens: linkedScreens.map((screen) => ({
          sourceScreenId: screen.screenId,
          screenName: screen.newScreenName!.trim(),
          screenCode: screen.newScreenCode!.trim(),
        })),
      });

      console.log("✅ 복사 완료:", result);

      // 대상 그룹이 선택된 경우 복제된 메인 화면을 그룹에 추가
      if (selectedTargetGroupId && result.mainScreen?.screenId) {
        try {
          await addScreenToGroup({
            group_id: selectedTargetGroupId,
            screen_id: result.mainScreen.screenId,
            screen_role: "MAIN",
            display_order: 1,
            target_company_code: finalCompanyCode, // 대상 회사 코드 전달
          });
          console.log(`✅ 복제된 화면을 그룹(${selectedTargetGroupId})에 추가 완료`);
        } catch (groupError) {
          console.error("그룹에 화면 추가 실패:", groupError);
          // 그룹 추가 실패해도 복제는 성공했으므로 계속 진행
        }
      }

      toast.success(
        `화면 복사가 완료되었습니다! (메인 1개 + 모달 ${result.modalScreens.length}개)`
      );
      
      // 새로고침 완료 후 모달 닫기
      await onCopySuccess();
      handleClose();
    } catch (error: any) {
      console.error("화면 복사 실패:", error);
      const errorMessage = error.response?.data?.message || error.message || "화면 복사에 실패했습니다.";
      toast.error(errorMessage);
    } finally {
      setIsCopying(false);
    }
  };

  // 이름 변환 헬퍼 함수 (일괄 이름 변경 적용)
  const transformName = (originalName: string, isRootGroup: boolean = false, sourceCompanyCode?: string): string => {
    // 루트 그룹은 사용자가 직접 입력한 이름 사용
    if (isRootGroup) {
      return newGroupName.trim();
    }
    
    // 일괄 이름 변경이 활성화된 경우 (찾기/대체 방식)
    if (useGroupBulkRename && groupFindText) {
      // 찾을 텍스트를 대체할 텍스트로 변경
      return originalName.replace(new RegExp(escapeRegExp(groupFindText), "g"), groupReplaceText);
    }
    
    // 다른 회사로 복제하는 경우: 원본 이름 그대로 사용 (중복될 일 없음)
    if (sourceCompanyCode && sourceCompanyCode !== targetCompanyCode) {
      return originalName;
    }
    
    // 같은 회사 내 복제: "(복제)" 붙이기 (중복 방지)
    return `${originalName} (복제)`;
  };

  // 재귀적 그룹 복제 함수 (하위 그룹 + 화면 전부 복제)
  const copyGroupRecursively = async (
    sourceGroupData: ScreenGroup,
    parentGroupId: number | null,
    targetCompany: string,
    screenCodes: string[], // 미리 생성된 화면 코드 배열
    codeIndex: { current: number }, // 현재 사용할 코드 인덱스 (참조로 전달)
    stats: { groups: number; screens: number },
    totalScreenCount: number, // 전체 화면 수 (진행률 표시용)
    screenIdMap: { [key: number]: number } // 원본 화면 ID -> 새 화면 ID 매핑
  ): Promise<void> => {
    // 1. 현재 그룹 생성 (원본 display_order 유지)
    const timestamp = Date.now();
    const randomSuffix = Math.floor(Math.random() * 1000);
    const newGroupCode = `${targetCompany}_GROUP_${timestamp}_${randomSuffix}`;
    
    const transformedGroupName = transformName(sourceGroupData.group_name, false, sourceGroupData.company_code);
    console.log(`📁 그룹 생성: ${transformedGroupName}`);
    
    const newGroupResponse = await createScreenGroup({
      group_name: transformedGroupName, // 일괄 이름 변경 적용
      group_code: newGroupCode,
      parent_group_id: parentGroupId,
      target_company_code: targetCompany,
      display_order: sourceGroupData.display_order, // 원본 정렬순서 유지
    });

    if (!newGroupResponse.success || !newGroupResponse.data) {
      throw new Error(newGroupResponse.error || `그룹 생성 실패: ${sourceGroupData.group_name}`);
    }

    const newGroup = newGroupResponse.data;
    stats.groups++;
    console.log(`✅ 그룹 생성 완료: ${newGroup.group_name} (id: ${newGroup.id})`);

    // 2. 현재 그룹의 화면들 복제 (원본 display_order 유지) - folder_only 모드가 아닌 경우만
    if (groupCopyMode !== "folder_only") {
      const sourceScreensInfo = sourceGroupData.screens || [];
      
      // 화면 정보와 display_order를 함께 매핑
      // allScreens에서 못 찾으면 그룹의 screens 정보를 직접 사용 (다른 회사 폴더 복사 시)
      const screensWithOrder = sourceScreensInfo.map((s: any) => {
        const screenId = typeof s === 'object' ? s.screen_id : s;
        const displayOrder = typeof s === 'object' ? s.display_order : 0;
        const screenRole = typeof s === 'object' ? s.screen_role : 'MAIN';
        const screenName = typeof s === 'object' ? s.screen_name : '';
        const tableName = typeof s === 'object' ? s.table_name : '';
        
        // allScreens에서 먼저 찾고, 없으면 그룹의 screens 정보로 대체
        let screenData = allScreens.find((sc) => sc.screenId === screenId);
        if (!screenData && screenId && screenName) {
          // allScreens에 없는 경우 (다른 회사 화면) - 그룹의 screens 정보로 최소한의 데이터 구성
          screenData = {
            screenId: screenId,
            screenName: screenName,
            screenCode: `SCREEN_${screenId}`, // 임시 코드 (실제 복사 시 새 코드 생성)
            tableName: tableName || '',
            description: '',
            companyCode: sourceGroupData.company_code || '',
          } as any;
        }
        return { screenId, displayOrder, screenRole, screenData };
      }).filter(item => item.screenData && item.screenId); // screenId가 유효한 것만

      // display_order 순으로 정렬
      screensWithOrder.sort((a, b) => (a.displayOrder || 0) - (b.displayOrder || 0));

    for (const { screenData: screen, displayOrder, screenRole } of screensWithOrder) {
      try {
        // 미리 생성된 화면 코드 사용
        const newScreenCode = screenCodes[codeIndex.current];
        codeIndex.current++;

        // 진행률 업데이트
        setCopyProgress({ 
          current: stats.screens + 1, 
          total: totalScreenCount, 
          message: `화면 복제 중: ${screen.screenName}` 
        });

        const transformedScreenName = transformName(screen.screenName, false, sourceGroupData.company_code);
        console.log(`  📄 화면 복제: ${screen.screenName} → ${transformedScreenName}`);

        const result = await screenApi.copyScreenWithModals(screen.screenId, {
          targetCompanyCode: targetCompany,
          mainScreen: {
            screenName: transformedScreenName, // 일괄 이름 변경 적용
            screenCode: newScreenCode,
            description: screen.description || "",
          },
          modalScreens: [],
        });

        if (result.mainScreen?.screenId) {
          // 원본 화면 ID -> 새 화면 ID 매핑 기록
          screenIdMap[screen.screenId] = result.mainScreen.screenId;
          
          await addScreenToGroup({
            group_id: newGroup.id,
            screen_id: result.mainScreen.screenId,
            screen_role: screenRole || "MAIN",
            display_order: displayOrder, // 원본 정렬순서 유지
            target_company_code: targetCompany, // 대상 회사 코드 전달
          });
          stats.screens++;
          console.log(`  ✅ 화면 복제 완료: ${result.mainScreen.screenName} (${screen.screenId} → ${result.mainScreen.screenId})`);
        }
        } catch (screenError) {
          console.error(`  ❌ 화면 복제 실패 (${screen.screenCode}):`, screenError);
        }
      }
    }

    // 3. 하위 그룹들 재귀 복제 (display_order 순으로 정렬) - screen_only 모드가 아닌 경우만
    if (groupCopyMode !== "screen_only") {
      const childGroups = groups
        .filter(g => g.parent_group_id === sourceGroupData.id)
        .sort((a, b) => (a.display_order || 0) - (b.display_order || 0));
      console.log(`📂 하위 그룹 ${childGroups.length}개 발견:`, childGroups.map(g => g.group_name));
      
      for (const childGroup of childGroups) {
        await copyGroupRecursively(
          childGroup,
          newGroup.id,
          targetCompany,
          screenCodes,
          codeIndex,
          stats,
          totalScreenCount,
          screenIdMap // screenIdMap 전달
        );
      }
    }
  };

  // 그룹 내 모든 화면 수 계산 (재귀적)
  const countAllScreensInGroup = (groupId: number): number => {
    const group = groups.find(g => g.id === groupId);
    if (!group) return 0;
    
    const directScreens = group.screens?.length || 0;
    const childGroups = groups.filter(g => g.parent_group_id === groupId);
    const childScreens = childGroups.reduce((sum, child) => sum + countAllScreensInGroup(child.id), 0);
    
    return directScreens + childScreens;
  };

  // 그룹 복제 실행
  const handleCopyGroup = async () => {
    if (!sourceGroup) return;

    if (!newGroupName.trim()) {
      toast.error("그룹명을 입력해주세요.");
      return;
    }

    // 최고 관리자인 경우 대상 회사 필수
    if (isSuperAdmin && !targetCompanyCode) {
      toast.error("대상 회사를 선택해주세요.");
      return;
    }

    try {
      setIsCopying(true);
      setCopyProgress({ current: 0, total: 0, message: "복제 준비 중..." });

      const finalCompanyCode = targetCompanyCode || sourceGroup.company_code;
      const stats = { groups: 0, screens: 0 };
      const screenIdMap: { [key: number]: number } = {}; // 원본 화면 ID -> 새 화면 ID 매핑
      
      console.log("🔄 그룹 복제 시작 (재귀적):", { 
        sourceGroup: sourceGroup.group_name, 
        targetCompany: finalCompanyCode,
      });

      // 1. 복제할 전체 화면 수 계산 (folder_only 모드가 아닌 경우만)
      const totalScreenCount = groupCopyMode === "folder_only" ? 0 : countAllScreensInGroup(sourceGroup.id);
      setCopyProgress({ current: 0, total: totalScreenCount, message: "화면 코드 생성 중..." });
      console.log(`📊 복제할 총 화면 수: ${totalScreenCount}개 (모드: ${groupCopyMode})`);

      // 2. 필요한 화면 코드들을 API로 미리 생성 (DB에서 고유 코드 보장)
      let screenCodes: string[] = [];
      if (totalScreenCount > 0) {
        console.log(`🔧 화면 코드 ${totalScreenCount}개 생성 중...`);
        screenCodes = await screenApi.generateMultipleScreenCodes(finalCompanyCode, totalScreenCount);
        console.log(`✅ 화면 코드 생성 완료:`, screenCodes);
      }
      const codeIndex = { current: 0 }; // 참조로 전달해서 재귀 호출간 공유

      // 3. 루트 그룹 생성 (일괄 변경 활성화 시 transformName 적용)
      const timestamp = Date.now();
      const newGroupCode = `${finalCompanyCode}_GROUP_${timestamp}`;
      
      // 일괄 이름 변경이 활성화된 경우 원본 이름에 변환 적용
      const rootGroupName = useGroupBulkRename && groupFindText
        ? transformName(sourceGroup.group_name, false, sourceGroup.company_code)
        : newGroupName.trim();
      
      const newGroupResponse = await createScreenGroup({
        group_name: rootGroupName,
        group_code: newGroupCode,
        parent_group_id: groupParentId,
        target_company_code: finalCompanyCode,
        display_order: groupDisplayOrder, // 사용자가 입력한 정렬 순서
      });

      if (!newGroupResponse.success || !newGroupResponse.data) {
        throw new Error(newGroupResponse.error || "그룹 생성 실패");
      }

      const newRootGroup = newGroupResponse.data;
      stats.groups++;
      console.log("✅ 루트 그룹 생성 완료:", newRootGroup.group_name);

      // 4. 원본 그룹의 화면들 복제 (루트 레벨, 원본 display_order 유지) - folder_only 모드가 아닌 경우만
      if (groupCopyMode !== "folder_only") {
        const sourceScreensInfo = sourceGroup.screens || [];
        
      // 화면 정보와 display_order를 함께 매핑
      // allScreens에서 못 찾으면 그룹의 screens 정보를 직접 사용 (다른 회사 폴더 복사 시)
      console.log(`🔍 루트 그룹 화면 매핑 시작: ${sourceScreensInfo.length}개 화면, allScreens: ${allScreens.length}개`);
      const screensWithOrder = sourceScreensInfo.map((s: any) => {
        const screenId = typeof s === 'object' ? s.screen_id : s;
        const displayOrder = typeof s === 'object' ? s.display_order : 0;
        const screenRole = typeof s === 'object' ? s.screen_role : 'MAIN';
        const screenName = typeof s === 'object' ? s.screen_name : '';
        const tableName = typeof s === 'object' ? s.table_name : '';
        
        // allScreens에서 먼저 찾고, 없으면 그룹의 screens 정보로 대체
        let screenData = allScreens.find((sc) => sc.screenId === screenId);
        const foundInAllScreens = !!screenData;
        
        if (!screenData && screenId && screenName) {
          // allScreens에 없는 경우 (다른 회사 화면) - 그룹의 screens 정보로 최소한의 데이터 구성
          console.log(`  ⚠️ allScreens에서 못 찾음, 그룹 정보 사용: ${screenId} - ${screenName}`);
          screenData = {
            screenId: screenId,
            screenName: screenName,
            screenCode: `SCREEN_${screenId}`, // 임시 코드 (실제 복사 시 새 코드 생성)
            tableName: tableName || '',
            description: '',
            companyCode: sourceGroup.company_code || '',
          } as any;
        } else if (screenData) {
          console.log(`  ✅ allScreens에서 찾음: ${screenId} - ${screenData.screenName}`);
        } else {
          console.log(`  ❌ 화면 정보 없음: screenId=${screenId}, screenName=${screenName}`);
        }
        return { screenId, displayOrder, screenRole, screenData };
      }).filter(item => item.screenData && item.screenId); // screenId가 유효한 것만
      
      console.log(`🔍 매핑 완료: ${screensWithOrder.length}개 화면 복사 예정`);
      screensWithOrder.forEach(item => console.log(`  - ${item.screenId}: ${item.screenData?.screenName}`));

      // display_order 순으로 정렬
      screensWithOrder.sort((a, b) => (a.displayOrder || 0) - (b.displayOrder || 0));

      for (const { screenData: screen, displayOrder, screenRole } of screensWithOrder) {
        try {
          // 미리 생성된 화면 코드 사용
          const newScreenCode = screenCodes[codeIndex.current];
          codeIndex.current++;

          // 진행률 업데이트
          setCopyProgress({ 
            current: stats.screens + 1, 
            total: totalScreenCount, 
            message: `화면 복제 중: ${screen.screenName}` 
          });

          const transformedScreenName = transformName(screen.screenName, false, sourceGroup.company_code);
          console.log(`📄 화면 복제: ${screen.screenName} → ${transformedScreenName}`);

          const result = await screenApi.copyScreenWithModals(screen.screenId, {
            targetCompanyCode: finalCompanyCode,
            mainScreen: {
              screenName: transformedScreenName, // 일괄 이름 변경 적용
              screenCode: newScreenCode,
              description: screen.description || "",
            },
            modalScreens: [],
          });

          if (result.mainScreen?.screenId) {
            // 원본 화면 ID -> 새 화면 ID 매핑 기록
            screenIdMap[screen.screenId] = result.mainScreen.screenId;
            
            await addScreenToGroup({
              group_id: newRootGroup.id,
              screen_id: result.mainScreen.screenId,
              screen_role: screenRole || "MAIN",
              display_order: displayOrder, // 원본 정렬순서 유지
              target_company_code: finalCompanyCode, // 대상 회사 코드 전달
            });
            stats.screens++;
            console.log(`✅ 화면 복제 완료: ${result.mainScreen.screenName} (${screen.screenId} → ${result.mainScreen.screenId})`);
          }
          } catch (screenError) {
            console.error(`화면 복제 실패 (${screen.screenCode}):`, screenError);
          }
        }
      }

      // 5. 하위 그룹들 재귀 복제 (display_order 순으로 정렬) - screen_only 모드가 아닌 경우만
      if (groupCopyMode !== "screen_only") {
        const childGroups = groups
          .filter(g => g.parent_group_id === sourceGroup.id)
          .sort((a, b) => (a.display_order || 0) - (b.display_order || 0));
        console.log(`📂 하위 그룹 ${childGroups.length}개 발견:`, childGroups.map(g => g.group_name));
        
        for (const childGroup of childGroups) {
          await copyGroupRecursively(
            childGroup,
            newRootGroup.id,
            finalCompanyCode,
            screenCodes,
            codeIndex,
            stats,
            totalScreenCount,
            screenIdMap // screenIdMap 전달
          );
        }
      }

      // 6. 탭 컴포넌트의 screenId 참조 일괄 업데이트
      console.log("🔍 screenIdMap 상태:", screenIdMap, "키 개수:", Object.keys(screenIdMap).length);
      if (Object.keys(screenIdMap).length > 0) {
        console.log("🔗 탭 screenId 참조 업데이트 중...", screenIdMap);
        setCopyProgress({ current: stats.screens, total: totalScreenCount, message: "탭 참조 업데이트 중..." });
        
        const targetScreenIds = Object.values(screenIdMap);
        try {
          const updateResult = await updateTabScreenReferences(targetScreenIds, screenIdMap);
          console.log(`✅ 탭 screenId 참조 업데이트 완료: ${updateResult.updated}개 레이아웃`);
        } catch (tabUpdateError) {
          console.warn("탭 screenId 참조 업데이트 실패 (무시):", tabUpdateError);
        }
      }

      // 7. 메뉴 동기화 및 화면-메뉴 할당 복제 (항상 실행 - 메뉴 연결 필수)
      try {
        setCopyProgress({ current: stats.screens, total: totalScreenCount, message: "메뉴 동기화 중..." });
        console.log("📋 메뉴 동기화 시작...");
        
        // 7-1. 메뉴 동기화 (화면 그룹 → 메뉴) - 항상 실행
        const syncResponse = await apiClient.post("/screen-groups/sync/screen-to-menu", {
          targetCompanyCode: finalCompanyCode,
        });
        
        if (syncResponse.data?.success) {
          console.log("✅ 메뉴 동기화 완료:", syncResponse.data.data);
          
          // 7-2. 화면-메뉴 할당 복제 (screen_menu_assignments) - 항상 실행
          setCopyProgress({ current: stats.screens, total: totalScreenCount, message: "화면-메뉴 할당 복제 중..." });
          console.log("📋 화면-메뉴 할당 복제 시작...");
          
          const menuAssignResponse = await apiClient.post("/screen-management/copy-menu-assignments", {
            sourceCompanyCode: sourceGroup.company_code,
            targetCompanyCode: finalCompanyCode,
            screenIdMap,
          });
          
          if (menuAssignResponse.data?.success) {
            console.log("✅ 화면-메뉴 할당 복제 완료:", menuAssignResponse.data.data);
          } else {
            console.warn("화면-메뉴 할당 복제 실패:", menuAssignResponse.data?.error);
          }
          
          // 7-3. 채번규칙 복제 (옵션이 선택된 경우에만)
          if (copyNumberingRules) {
            setCopyProgress({ current: stats.screens, total: totalScreenCount, message: "채번규칙 복제 중..." });
            console.log("📋 채번규칙 복제 시작...");
            
            const numberingResponse = await apiClient.post("/numbering-rules/copy-for-company", {
              sourceCompanyCode: sourceGroup.company_code,
              targetCompanyCode: finalCompanyCode,
            });
            
            if (numberingResponse.data?.success) {
              console.log("✅ 채번규칙 복제 완료:", numberingResponse.data.data);
              toast.success(`채번규칙 ${numberingResponse.data.data?.copiedCount || 0}개가 복제되었습니다.`);
            } else {
              console.warn("채번규칙 복제 실패:", numberingResponse.data?.error);
              toast.warning("채번규칙 복제에 실패했습니다. 수동으로 복제해주세요.");
            }
          }
        } else {
          console.warn("메뉴 동기화 실패:", syncResponse.data?.error);
          toast.warning("메뉴 동기화에 실패했습니다.");
        }
      } catch (menuSyncError) {
        console.error("메뉴 동기화 중 오류:", menuSyncError);
        toast.warning("메뉴 동기화 중 오류가 발생했습니다.");
      }

      // 8. 카테고리 값 복제
      if (copyCategoryValues) {
        try {
          setCopyProgress({ current: stats.screens, total: totalScreenCount, message: "카테고리 값 복제 중..." });
          console.log("📋 카테고리 값 복제 시작...");
          
          const response = await apiClient.post("/screen-management/copy-category-mapping", {
            sourceCompanyCode: sourceGroup.company_code,
            targetCompanyCode: finalCompanyCode,
          });
          
          if (response.data?.success) {
            console.log("✅ 카테고리 값 복제 완료:", response.data.data);
            toast.success(`카테고리 값 ${response.data.data?.copiedValues || 0}개가 복제되었습니다.`);
          } else {
            console.warn("카테고리 값 복제 실패:", response.data?.error);
            toast.warning("카테고리 값 복제에 실패했습니다.");
          }
        } catch (error) {
          console.error("카테고리 값 복제 중 오류:", error);
          toast.warning("카테고리 값 복제 중 오류가 발생했습니다.");
        }
      }

      // 9. 테이블 타입관리 입력타입 설정 복제
      if (copyTableTypeColumns) {
        try {
          setCopyProgress({ current: stats.screens, total: totalScreenCount, message: "테이블 타입 컬럼 복제 중..." });
          console.log("📋 테이블 타입 컬럼 복제 시작...");
          
          const response = await apiClient.post("/screen-management/copy-table-type-columns", {
            sourceCompanyCode: sourceGroup.company_code,
            targetCompanyCode: finalCompanyCode,
          });
          
          if (response.data?.success) {
            console.log("✅ 테이블 타입 컬럼 복제 완료:", response.data.data);
            toast.success(`테이블 타입 컬럼 ${response.data.data?.copiedCount || 0}개가 복제되었습니다.`);
          } else {
            console.warn("테이블 타입 컬럼 복제 실패:", response.data?.error);
            toast.warning("테이블 타입 컬럼 복제에 실패했습니다.");
          }
        } catch (error) {
          console.error("테이블 타입 컬럼 복제 중 오류:", error);
          toast.warning("테이블 타입 컬럼 복제 중 오류가 발생했습니다.");
        }
      }

      toast.success(
        `그룹 복제가 완료되었습니다! (그룹 ${stats.groups}개 + 화면 ${stats.screens}개)`
      );

      await onCopySuccess();
      handleClose();
    } catch (error: any) {
      console.error("그룹 복제 실패:", error);
      const errorMessage = error.response?.data?.message || "그룹 복제에 실패했습니다.";
      toast.error(errorMessage);
    } finally {
      setIsCopying(false);
    }
  };

  // 모달 닫기
  const handleClose = () => {
    setScreenName("");
    setScreenCode("");
    setDescription("");
    setTargetCompanyCode("");
    setLinkedScreens([]);
    setSelectedTargetGroupId(null);
    setNewGroupName("");
    setGroupParentId(null);
    setGroupDisplayOrder(0);
    setUseGroupBulkRename(false);
    setGroupFindText("");
    setGroupReplaceText("");
    onClose();
  };

  // 그룹 복제 모드 렌더링
  if (mode === "group") {
    return (
      <Dialog open={isOpen} onOpenChange={handleClose}>
        <DialogContent className="max-w-[95vw] sm:max-w-[500px] max-h-[90vh] overflow-y-auto">
          {/* 로딩 오버레이 */}
          {isCopying && (
            <div className="absolute inset-0 z-50 flex flex-col items-center justify-center rounded-lg bg-background/90 backdrop-blur-sm">
              <Loader2 className="h-10 w-10 animate-spin text-primary" />
              <p className="mt-4 text-sm font-medium">{copyProgress.message}</p>
              {copyProgress.total > 0 && (
                <>
                  <div className="mt-3 h-2 w-48 overflow-hidden rounded-full bg-secondary">
                    <div
                      className="h-full bg-primary transition-all duration-300"
                      style={{ width: `${Math.round((copyProgress.current / copyProgress.total) * 100)}%` }}
                    />
                  </div>
                  <p className="mt-2 text-xs text-muted-foreground">
                    {copyProgress.current} / {copyProgress.total} 화면
                  </p>
                </>
              )}
            </div>
          )}
          
          <DialogHeader>
            <DialogTitle className="flex items-center gap-2 text-base sm:text-lg">
              <FolderTree className="h-5 w-5" />
              그룹 복제
            </DialogTitle>
            <DialogDescription className="text-xs sm:text-sm">
              "{sourceGroup?.group_name}" 그룹을 복제합니다. 그룹 내 모든 화면도 함께 복제됩니다.
            </DialogDescription>
          </DialogHeader>

          <div className="space-y-3 sm:space-y-4">
            {/* 대분류 경고 (최상위 그룹인 경우) */}
            {sourceGroup && !sourceGroup.parent_group_id && (
              <div className="rounded-md border border-amber-300 bg-amber-50 p-3">
                <div className="flex items-start gap-2">
                  <AlertTriangle className="mt-0.5 h-4 w-4 flex-shrink-0 text-amber-600" />
                  <div>
                    <h4 className="text-sm font-medium text-amber-800">대분류 폴더 복제</h4>
                    <p className="mt-1 text-xs text-amber-700">
                      이 폴더는 최상위(대분류) 폴더입니다. 복제 시 모든 하위 폴더와 화면이 함께 복제됩니다.
                      데이터 양이 많을 경우 복제에 시간이 소요될 수 있습니다.
                    </p>
                  </div>
                </div>
              </div>
            )}

            {/* 원본 그룹 정보 */}
            <div className="rounded-md bg-gray-50 p-3">
              <h4 className="mb-2 text-sm font-medium text-gray-700">원본 그룹 정보</h4>
              <div className="space-y-1 text-sm text-muted-foreground">
                <div>
                  <span className="font-medium">그룹명:</span> {sourceGroup?.group_name}
                </div>
                <div>
                  <span className="font-medium">정렬 순서:</span> {sourceGroup?.display_order ?? 0}
                </div>
                <div>
                  <span className="font-medium">직접 포함 화면:</span> {sourceGroup?.screens?.length || 0}개
                </div>
                {(() => {
                  // 하위 그룹 수 계산
                  const childGroupCount = groups.filter(g => g.parent_group_id === sourceGroup?.id).length;
                  // 총 화면 수 계산 (현재 그룹 + 모든 하위 그룹)
                  const totalScreenCount = sourceGroup ? countAllScreensInGroup(sourceGroup.id) : 0;
                  return (
                    <>
                      <div>
                        <span className="font-medium">하위 그룹:</span> {childGroupCount}개
                      </div>
                      {childGroupCount > 0 && (
                        <div className="mt-1 border-t pt-1">
                          <span className="font-medium text-primary">복제될 총 화면:</span>{" "}
                          <span className="font-semibold text-primary">{totalScreenCount}개</span>
                        </div>
                      )}
                    </>
                  );
                })()}
              </div>
            </div>

            {/* 복제 모드 선택 */}
            <div className="space-y-2">
              <Label className="text-xs sm:text-sm">복제 범위</Label>
              <RadioGroup
                value={groupCopyMode}
                onValueChange={(value) => setGroupCopyMode(value as "all" | "folder_only" | "screen_only")}
                className="flex flex-wrap gap-4"
              >
                <div className="flex items-center space-x-2">
                  <RadioGroupItem value="all" id="copy-all" />
                  <Label htmlFor="copy-all" className="text-xs sm:text-sm font-normal cursor-pointer">
                    전체 (폴더+화면)
                  </Label>
                </div>
                <div className="flex items-center space-x-2">
                  <RadioGroupItem value="folder_only" id="copy-folder-only" />
                  <Label htmlFor="copy-folder-only" className="text-xs sm:text-sm font-normal cursor-pointer">
                    폴더만
                  </Label>
                </div>
                <div className="flex items-center space-x-2">
                  <RadioGroupItem value="screen_only" id="copy-screen-only" />
                  <Label htmlFor="copy-screen-only" className="text-xs sm:text-sm font-normal cursor-pointer">
                    화면만 (현재 폴더)
                  </Label>
                </div>
              </RadioGroup>
              <p className="text-[10px] sm:text-xs text-muted-foreground">
                {groupCopyMode === "all" && "하위 그룹과 모든 화면이 함께 복제됩니다"}
                {groupCopyMode === "folder_only" && "하위 그룹 구조만 복제하고 화면은 복제하지 않습니다"}
                {groupCopyMode === "screen_only" && "현재 그룹의 화면만 복제하고 하위 그룹은 복제하지 않습니다"}
              </p>
            </div>

            {/* 추가 복사 옵션 (선택사항) */}
            <div className="space-y-2">
              <Label className="text-xs sm:text-sm font-medium">추가 복사 옵션 (선택사항):</Label>
              
              {/* 채번규칙 복제 */}
              <div className="flex items-center space-x-2 p-2 bg-muted/30 rounded-md ml-2">
                <Checkbox
                  id="copyNumberingRules"
                  checked={copyNumberingRules}
                  onCheckedChange={(checked) => setCopyNumberingRules(checked === true)}
                />
                <Label htmlFor="copyNumberingRules" className="text-xs sm:text-sm cursor-pointer flex items-center gap-2">
                  <Hash className="h-4 w-4 text-muted-foreground" />
                  채번 규칙 복사
                </Label>
              </div>

              {/* 카테고리 값 복사 */}
              <div className="flex items-center space-x-2 p-2 bg-muted/30 rounded-md ml-2">
                <Checkbox
                  id="copyCategoryValues"
                  checked={copyCategoryValues}
                  onCheckedChange={(checked) => setCopyCategoryValues(checked === true)}
                />
                <Label htmlFor="copyCategoryValues" className="text-xs sm:text-sm cursor-pointer flex items-center gap-2">
                  <Table className="h-4 w-4 text-muted-foreground" />
                  카테고리 값 복사
                </Label>
              </div>

              {/* 테이블 타입관리 입력타입 설정 복사 */}
              <div className="flex items-center space-x-2 p-2 bg-muted/30 rounded-md ml-2">
                <Checkbox
                  id="copyTableTypeColumns"
                  checked={copyTableTypeColumns}
                  onCheckedChange={(checked) => setCopyTableTypeColumns(checked === true)}
                />
                <Label htmlFor="copyTableTypeColumns" className="text-xs sm:text-sm cursor-pointer flex items-center gap-2">
                  <Settings className="h-4 w-4 text-muted-foreground" />
                  테이블 타입관리 입력타입 설정 복사
                </Label>
              </div>
            </div>

            {/* 기본 복사 항목 안내 */}
            <div className="p-3 bg-muted/50 rounded-lg">
              <p className="text-xs font-medium mb-1">기본 복사 항목:</p>
              <ul className="text-[10px] sm:text-xs text-muted-foreground space-y-0.5 list-disc list-inside">
                <li>메뉴 구조 (하위 메뉴 포함)</li>
                <li>화면 + 레이아웃 (모달, 조건부 컨테이너)</li>
                <li>플로우 제어 (스텝, 연결)</li>
              </ul>
              <p className="text-[10px] text-muted-foreground mt-2 italic">
                * 채번규칙, 카테고리 값, 입력타입 설정은 위 옵션 선택 시 복사됩니다.
              </p>
            </div>

            {/* 새 그룹명 + 정렬 순서 */}
            <div className="flex gap-3">
              <div className="flex-1">
                <Label htmlFor="newGroupName" className="text-xs sm:text-sm">
                  새 그룹명 *
                </Label>
                <Input
                  id="newGroupName"
                  value={newGroupName}
                  onChange={(e) => setNewGroupName(e.target.value)}
                  placeholder="복제될 그룹의 이름을 입력하세요"
                  className="mt-1 h-8 text-xs sm:h-10 sm:text-sm"
                />
              </div>
              <div className="w-24">
                <Label htmlFor="groupDisplayOrder" className="text-xs sm:text-sm">
                  정렬 순서
                </Label>
                <Input
                  id="groupDisplayOrder"
                  type="number"
                  min={0}
                  value={groupDisplayOrder === 0 ? "" : groupDisplayOrder}
                  onChange={(e) => {
                    const val = e.target.value;
                    setGroupDisplayOrder(val === "" ? 0 : parseInt(val) || 0);
                  }}
                  onBlur={(e) => {
                    // 빈 값이면 0으로 설정
                    if (e.target.value === "") {
                      setGroupDisplayOrder(0);
                    }
                  }}
                  className="mt-1 h-8 text-xs sm:h-10 sm:text-sm"
                />
              </div>
            </div>

            {/* 상위 그룹 선택 */}
            {groups.length > 0 && (
              <div>
                <Label className="text-xs sm:text-sm">상위 그룹 (선택사항)</Label>
                <Popover open={isParentGroupSelectOpen} onOpenChange={setIsParentGroupSelectOpen}>
                  <PopoverTrigger asChild>
                    <Button
                      variant="outline"
                      role="combobox"
                      aria-expanded={isParentGroupSelectOpen}
                      className="mt-1 h-8 w-full justify-between text-xs sm:h-10 sm:text-sm"
                    >
                      {groupParentId
                        ? getGroupPath(groupParentId) || "그룹 선택"
                        : "상위 그룹 없음 (최상위)"}
                      <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
                    </Button>
                  </PopoverTrigger>
                  <PopoverContent className="w-full min-w-[300px] p-0" align="start">
                    <Command>
                      <CommandInput placeholder="그룹 검색..." className="text-xs sm:text-sm" />
                      <CommandList>
                        <CommandEmpty className="text-xs sm:text-sm">
                          그룹을 찾을 수 없습니다.
                        </CommandEmpty>
                        <CommandGroup>
                          <CommandItem
                            value="최상위 그룹"
                            onSelect={() => {
                              setGroupParentId(null);
                              setIsParentGroupSelectOpen(false);
                              // 최상위 선택 시 원본 그룹의 회사 코드 유지
                              if (sourceGroup?.company_code) {
                                setTargetCompanyCode(sourceGroup.company_code);
                              }
                            }}
                            className="text-xs sm:text-sm"
                          >
                            <Check
                              className={cn(
                                "mr-2 h-4 w-4",
                                groupParentId === null ? "opacity-100" : "opacity-0"
                              )}
                            />
                            최상위 그룹 (상위 없음)
                          </CommandItem>
                          {getSortedGroups()
                            .filter((g) => g.id !== sourceGroup?.id)
                            .map((group) => (
                              <CommandItem
                                key={group.id}
                                value={`${group.group_name} ${getGroupPath(group.id)}`}
                                onSelect={() => {
                                  setGroupParentId(group.id);
                                  setIsParentGroupSelectOpen(false);
                                  // 선택한 상위 그룹의 회사 코드로 자동 설정
                                  if (group.company_code) {
                                    setTargetCompanyCode(group.company_code);
                                  }
                                }}
                                className="text-xs sm:text-sm"
                              >
                                <Check
                                  className={cn(
                                    "mr-2 h-4 w-4",
                                    groupParentId === group.id ? "opacity-100" : "opacity-0"
                                  )}
                                />
                                <span style={{ paddingLeft: `${getGroupLevel(group.id) * 12}px` }}>
                                  {group.group_name}
                                </span>
                              </CommandItem>
                            ))}
                        </CommandGroup>
                      </CommandList>
                    </Command>
                  </PopoverContent>
                </Popover>
              </div>
            )}

            {/* 대상 회사 선택 (최고 관리자 전용) */}
            {isSuperAdmin && companies.length > 0 && (
              <div>
                <Label className="text-xs sm:text-sm">대상 회사 *</Label>
                <select
                  value={targetCompanyCode}
                  onChange={(e) => setTargetCompanyCode(e.target.value)}
                  className="mt-1 flex h-8 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
                >
                  {companies.map((company) => (
                    <option key={company.companyCode} value={company.companyCode}>
                      {company.companyName} ({company.companyCode})
                    </option>
                  ))}
                </select>
                <p className="mt-1 text-[10px] text-muted-foreground sm:text-xs">
                  복제된 그룹과 화면이 이 회사에 생성됩니다
                </p>
              </div>
            )}

            {/* 고급 옵션: 일괄 이름 변경 */}
            <details className="rounded-md border p-3">
              <summary className="cursor-pointer text-xs font-medium text-muted-foreground sm:text-sm">
                고급 옵션: 이름 일괄 변경
              </summary>
              <div className="mt-3 space-y-3">
                <div className="flex items-center gap-2">
                  <input
                    type="checkbox"
                    id="useGroupBulkRename"
                    checked={useGroupBulkRename}
                    onChange={(e) => setUseGroupBulkRename(e.target.checked)}
                    className="h-4 w-4 rounded border-gray-300"
                  />
                  <label htmlFor="useGroupBulkRename" className="text-xs sm:text-sm">
                    폴더/화면 이름 일괄 변경 사용
                  </label>
                </div>

                {useGroupBulkRename && (
                  <>
                    <div>
                      <Label className="text-xs sm:text-sm">찾을 텍스트</Label>
                      <Input
                        value={groupFindText}
                        onChange={(e) => setGroupFindText(e.target.value)}
                        placeholder="예: 테스트"
                        className="mt-1 h-8 text-xs sm:h-10 sm:text-sm"
                      />
                      <p className="mt-1 text-[10px] text-muted-foreground">
                        모든 폴더/화면 이름에서 이 텍스트를 찾습니다
                      </p>
                    </div>

                    <div>
                      <Label className="text-xs sm:text-sm">대체할 텍스트</Label>
                      <Input
                        value={groupReplaceText}
                        onChange={(e) => setGroupReplaceText(e.target.value)}
                        placeholder="예: TEST"
                        className="mt-1 h-8 text-xs sm:h-10 sm:text-sm"
                      />
                      <p className="mt-1 text-[10px] text-muted-foreground">
                        찾은 텍스트를 이 텍스트로 대체합니다
                      </p>
                    </div>

                    <div className="rounded-md bg-gray-50 p-2 text-xs text-muted-foreground">
                      <strong>미리보기:</strong>
                      <div className="mt-1">
                        "{sourceGroup?.group_name}" → "
                        {groupFindText
                          ? (sourceGroup?.group_name || "").replace(new RegExp(escapeRegExp(groupFindText), "g"), groupReplaceText)
                          : `${sourceGroup?.group_name} (복제)`}
                        "
                      </div>
                    </div>
                  </>
                )}
              </div>
            </details>
          </div>

          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              variant="outline"
              onClick={handleClose}
              disabled={isCopying}
              className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
            >
              취소
            </Button>
            <Button
              onClick={handleCopyGroup}
              disabled={isCopying || !newGroupName.trim() || (isSuperAdmin && !targetCompanyCode)}
              className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
            >
              {isCopying ? (
                <>
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  복제 중...
                </>
              ) : (
                <>
                  <FolderTree className="mr-2 h-4 w-4" />
                  복제하기
                </>
              )}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    );
  }

  // 화면 복제 모드 렌더링
  return (
    <Dialog open={isOpen} onOpenChange={handleClose}>
      <DialogContent className="max-w-[95vw] sm:max-w-[500px] max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle className="text-base sm:text-lg">화면 복제</DialogTitle>
          <DialogDescription className="text-xs sm:text-sm">
            "{sourceScreen?.screenName}" 화면을 복제합니다.
            {linkedScreens.length > 0 && ` (모달 ${linkedScreens.length}개 포함)`}
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4">
          {/* 새 화면명 */}
          <div>
            <Label htmlFor="screenName" className="text-sm">새 화면명 *</Label>
            <Input
              id="screenName"
              value={screenName}
              onChange={(e) => setScreenName(e.target.value)}
              placeholder="복제될 화면 이름"
              className="mt-1"
            />
          </div>

          {/* 새 화면코드 (자동생성) */}
          <div>
            <Label htmlFor="screenCode" className="text-sm">화면코드 (자동생성)</Label>
            <Input
              id="screenCode"
              value={screenCode}
              readOnly
              className="mt-1 bg-muted"
            />
          </div>

          {/* 대상 그룹 선택 */}
          {groups.length > 0 && (
            <div>
              <Label className="text-sm">복제할 그룹</Label>
              <Popover open={isGroupSelectOpen} onOpenChange={setIsGroupSelectOpen}>
                <PopoverTrigger asChild>
                  <Button
                    variant="outline"
                    role="combobox"
                    className="mt-1 h-10 w-full justify-between text-sm"
                  >
                    {selectedTargetGroupId
                      ? getGroupPath(selectedTargetGroupId)
                      : "미분류"}
                    <ChevronsUpDown className="ml-2 h-4 w-4 opacity-50" />
                  </Button>
                </PopoverTrigger>
                <PopoverContent className="w-full min-w-[280px] p-0" align="start">
                  <Command>
                    <CommandInput placeholder="그룹 검색..." />
                    <CommandList>
                      <CommandEmpty>그룹 없음</CommandEmpty>
                      <CommandGroup>
                        <CommandItem
                          value="미분류"
                          onSelect={() => {
                            setSelectedTargetGroupId(null);
                            setIsGroupSelectOpen(false);
                          }}
                        >
                          <Check className={cn("mr-2 h-4 w-4", selectedTargetGroupId === null ? "opacity-100" : "opacity-0")} />
                          미분류
                        </CommandItem>
                        {getSortedGroups().map((group) => (
                          <CommandItem
                            key={group.id}
                            value={group.group_name}
                            onSelect={() => {
                              setSelectedTargetGroupId(group.id);
                              setIsGroupSelectOpen(false);
                            }}
                          >
                            <Check className={cn("mr-2 h-4 w-4", selectedTargetGroupId === group.id ? "opacity-100" : "opacity-0")} />
                            <span style={{ paddingLeft: `${getGroupLevel(group.id) * 12}px` }}>
                              {group.group_name}
                            </span>
                          </CommandItem>
                        ))}
                      </CommandGroup>
                    </CommandList>
                  </Command>
                </PopoverContent>
              </Popover>
            </div>
          )}

          {/* 최고 관리자: 대상 회사 선택 */}
          {isSuperAdmin && (
            <div>
              <Label className="text-sm">대상 회사</Label>
              <Select value={targetCompanyCode} onValueChange={setTargetCompanyCode}>
                <SelectTrigger className="mt-1">
                  <SelectValue placeholder="회사 선택" />
                </SelectTrigger>
                <SelectContent>
                  {companies.map((company) => (
                    <SelectItem key={company.companyCode} value={company.companyCode}>
                      {company.companyName}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          )}

          {/* 연결된 모달 화면 (있을 경우만) */}
          {linkedScreens.length > 0 && (
            <div className="rounded-md border p-3">
              <div className="flex items-center justify-between mb-2">
                <span className="text-sm font-medium flex items-center gap-1">
                  <LinkIcon className="h-4 w-4" />
                  연결된 모달 ({linkedScreens.length}개)
                </span>
              </div>
              <div className="space-y-2 max-h-[150px] overflow-y-auto">
                {linkedScreens.map((linked) => (
                  <div key={linked.screenId} className="flex items-center justify-between text-xs bg-muted rounded p-2">
                    <div className="flex-1 min-w-0">
                      <Input
                        value={linked.newScreenName || ""}
                        onChange={(e) => updateLinkedScreenName(linked.screenId, e.target.value)}
                        className="h-7 text-xs"
                        placeholder="모달 화면명"
                      />
                    </div>
                    <Button
                      variant="ghost"
                      size="icon"
                      className="h-7 w-7 ml-1 text-destructive"
                      onClick={() => removeLinkedScreen(linked.screenId)}
                    >
                      <Trash2 className="h-3 w-3" />
                    </Button>
                  </div>
                ))}
              </div>
            </div>
          )}

          {/* 화면명 일괄 수정 (접히는 옵션) */}
          <details className="text-sm">
            <summary className="cursor-pointer text-muted-foreground hover:text-foreground">
              고급 옵션
            </summary>
            <div className="mt-3 space-y-3 rounded-md border p-3">
              <div className="grid grid-cols-2 gap-2">
                <div>
                  <Label className="text-xs">제거할 텍스트</Label>
                  <Input
                    value={removeText}
                    onChange={(e) => {
                      setRemoveText(e.target.value);
                      setUseBulkRename(true);
                    }}
                    placeholder="예: 탑씰"
                    className="mt-1 h-8 text-xs"
                  />
                </div>
                <div>
                  <Label className="text-xs">추가할 접두사</Label>
                  <Input
                    value={addPrefix}
                    onChange={(e) => {
                      setAddPrefix(e.target.value);
                      setUseBulkRename(true);
                    }}
                    placeholder="예: 대진"
                    className="mt-1 h-8 text-xs"
                  />
                </div>
              </div>
              {(removeText || addPrefix) && getPreviewNames() && (
                <div className="text-xs text-muted-foreground">
                  미리보기: {getPreviewNames()?.main.preview}
                </div>
              )}
            </div>
          </details>
        </div>

        <DialogFooter className="gap-2 sm:gap-0">
          <Button variant="outline" onClick={handleClose} disabled={isCopying}>
            취소
          </Button>
          <Button onClick={handleCopy} disabled={isCopying || !screenName.trim() || !screenCode}>
            {isCopying ? (
              <>
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                복제 중...
              </>
            ) : (
              "복제"
            )}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

