"use client";

import React, { useState, useEffect, useMemo, useCallback, useRef } from "react";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command";
import {
  ChevronRight,
  ChevronDown,
  Search,
  Check,
  X,
  Languages,
  Table2,
  LayoutPanelLeft,
  Type,
  MousePointer,
  Filter,
  FormInput,
  ChevronsUpDown,
  Loader2,
  Circle,
  CircleDot,
  CheckCircle2,
} from "lucide-react";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Progress } from "@/components/ui/progress";
import { ComponentData } from "@/types/screen";
import { cn } from "@/lib/utils";
import { apiClient } from "@/lib/api/client";

// 다국어 키 타입
interface LangKey {
  keyId: number;
  langKey: string;
  description?: string;
  categoryName?: string;
}

// 번역 텍스트 타입
interface LangText {
  langCode: string;
  langName: string;
  langNative: string;
  text: string;
}

// 입력 가능한 폼 컴포넌트 타입 목록
const INPUT_COMPONENT_TYPES = new Set([
  "text-input",
  "number-input",
  "date-input",
  "datetime-input",
  "select-input",
  "textarea-input",
  "checkbox-input",
  "radio-input",
  "file-input",
  "email-input",
  "phone-input",
  "entity-input",
  "code-input",
  // 위젯 타입도 포함
  "widget",
  "input",
  "field",
]);

// 입력 가능한 웹타입 목록
const INPUT_WEB_TYPES = new Set([
  "text",
  "number",
  "decimal",
  "date",
  "datetime",
  "select",
  "dropdown",
  "textarea",
  "boolean",
  "checkbox",
  "radio",
  "code",
  "entity",
  "file",
  "email",
  "tel",
]);

// 추출된 라벨 항목 타입
interface ExtractedLabel {
  id: string;
  componentId: string;
  label: string;
  type: "label" | "title" | "button" | "placeholder" | "column" | "filter" | "field" | "tab" | "action";
  parentType?: string;
  parentLabel?: string;
  langKeyId?: number;
  langKey?: string;
}

// 번역 상태 타입
type TranslationStatus = "complete" | "partial" | "none";

// 번역 필터 타입
type TranslationFilter = "all" | "complete" | "incomplete";

// 그룹화된 라벨 타입
interface LabelGroup {
  id: string;
  label: string;
  type: string;
  icon: React.ReactNode;
  items: ExtractedLabel[];
  isExpanded: boolean;
}

interface MultilangSettingsModalProps {
  isOpen: boolean;
  onClose: () => void;
  components: ComponentData[];
  onSave: (updates: Array<{ componentId: string; path?: string; langKeyId: number; langKey: string }>) => void;
}

// 타입별 아이콘 매핑
const getTypeIcon = (type: string) => {
  switch (type) {
    case "button":
      return <MousePointer className="h-4 w-4" />;
    case "table-list":
      return <Table2 className="h-4 w-4" />;
    case "split-panel-layout":
      return <LayoutPanelLeft className="h-4 w-4" />;
    case "filter":
      return <Filter className="h-4 w-4" />;
    case "field":
    case "input":
      return <FormInput className="h-4 w-4" />;
    default:
      return <Type className="h-4 w-4" />;
  }
};

// 타입별 한글 라벨
const getTypeLabel = (type: string) => {
  switch (type) {
    case "button":
      return "버튼";
    case "label":
      return "라벨";
    case "title":
      return "제목";
    case "column":
      return "컬럼";
    case "filter":
      return "필터";
    case "field":
      return "필드";
    case "placeholder":
      return "플레이스홀더";
    case "tab":
      return "탭";
    case "action":
      return "액션";
    default:
      return type;
  }
};

// 라벨 다국어 처리가 필요 없는 컴포넌트 타입 (테이블, 분할패널 등)
const NON_INPUT_COMPONENT_TYPES = new Set([
  "table-list",
  "split-panel-layout",
  "tab-panel",
  "container",
  "group",
  "layout",
  "panel",
  "card",
  "accordion",
  "modal",
  "drawer",
  "form-layout",
  "aggregation-widget",
]);

// 컴포넌트가 입력 폼인지 확인
const isInputComponent = (comp: any): boolean => {
  const compType = comp.componentType || comp.type;
  const webType = comp.webType || comp.componentConfig?.webType;

  // 명시적으로 제외되는 컴포넌트 타입
  if (NON_INPUT_COMPONENT_TYPES.has(compType)) {
    return false;
  }

  // 컴포넌트 타입으로 확인
  if (INPUT_COMPONENT_TYPES.has(compType)) {
    return true;
  }

  // 웹타입으로 확인
  if (webType && INPUT_WEB_TYPES.has(webType)) {
    return true;
  }

  return false;
};

// 키 선택 콤보박스 컴포넌트
interface KeySelectComboboxProps {
  value?: { keyId: number; langKey: string };
  onChange: (value: { keyId: number; langKey: string } | null) => void;
  langKeys: LangKey[];
  isLoading: boolean;
}

const KeySelectCombobox: React.FC<KeySelectComboboxProps> = ({
  value,
  onChange,
  langKeys,
  isLoading,
}) => {
  const [open, setOpen] = useState(false);

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          variant="outline"
          role="combobox"
          aria-expanded={open}
          className="h-7 w-[180px] justify-between text-xs"
          disabled={isLoading}
        >
          {isLoading ? (
            <Loader2 className="h-3 w-3 animate-spin" />
          ) : value ? (
            <span className="truncate">{value.langKey}</span>
          ) : (
            <span className="text-muted-foreground">키 선택...</span>
          )}
          <ChevronsUpDown className="ml-1 h-3 w-3 shrink-0 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-[300px] p-0" align="end">
        <Command>
          <CommandInput placeholder="키 검색..." className="h-9" />
          <CommandList>
            <CommandEmpty>검색 결과가 없습니다.</CommandEmpty>
            <CommandGroup>
              {/* 연결 해제 옵션 */}
              {value && (
                <CommandItem
                  onSelect={() => {
                    onChange(null);
                    setOpen(false);
                  }}
                  className="text-destructive"
                >
                  <X className="mr-2 h-4 w-4" />
                  연결 해제
                </CommandItem>
              )}
              {langKeys.map((key) => (
                <CommandItem
                  key={key.keyId}
                  value={key.langKey}
                  onSelect={() => {
                    onChange({ keyId: key.keyId, langKey: key.langKey });
                    setOpen(false);
                  }}
                >
                  <Check
                    className={cn(
                      "mr-2 h-4 w-4",
                      value?.keyId === key.keyId ? "opacity-100" : "opacity-0"
                    )}
                  />
                  <div className="flex flex-col">
                    <span className="text-sm font-medium">{key.langKey}</span>
                    {key.description && (
                      <span className="text-xs text-muted-foreground">{key.description}</span>
                    )}
                  </div>
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  );
};

export const MultilangSettingsModal: React.FC<MultilangSettingsModalProps> = ({
  isOpen,
  onClose,
  components,
  onSave,
}) => {
  const [searchText, setSearchText] = useState("");
  const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set());
  const [selectedItems, setSelectedItems] = useState<Map<string, { langKeyId?: number; langKey?: string }>>(new Map());
  const [extractedLabels, setExtractedLabels] = useState<ExtractedLabel[]>([]);
  const [langKeys, setLangKeys] = useState<LangKey[]>([]);
  const [isLoadingKeys, setIsLoadingKeys] = useState(false);
  // 테이블별 컬럼 라벨 매핑 (columnName -> displayName)
  const [columnLabelMap, setColumnLabelMap] = useState<Record<string, Record<string, string>>>({});
  // 번역 필터 상태
  const [translationFilter, setTranslationFilter] = useState<TranslationFilter>("all");
  // 항목별 번역 상태 캐시 (itemId -> status)
  const [translationStatusCache, setTranslationStatusCache] = useState<Record<string, TranslationStatus>>({});
  // 선택된 라벨 항목
  const [selectedLabelItem, setSelectedLabelItem] = useState<ExtractedLabel | null>(null);
  // 선택된 라벨의 번역 텍스트 로드
  const [isLoadingTranslations, setIsLoadingTranslations] = useState(false);
  // 모든 항목의 편집된 번역을 저장하는 맵 (itemId -> langCode -> text)
  const [allEditedTranslations, setAllEditedTranslations] = useState<Record<string, Record<string, string>>>({});
  // 저장 중 상태
  const [isSaving, setIsSaving] = useState(false);
  // 활성화된 언어 목록
  const [activeLanguages, setActiveLanguages] = useState<Array<{ langCode: string; langName: string; langNative: string }>>([]);

  // 컴포넌트에서 사용되는 테이블명 추출
  const getTableNamesFromComponents = useCallback((comps: ComponentData[]): Set<string> => {
    const tableNames = new Set<string>();
    
    const extractTableName = (comp: any) => {
      const config = comp.componentConfig;
      
      // 1. 최상위 tableName
      if (comp.tableName) tableNames.add(comp.tableName);
      
      // 2. componentConfig 직접 tableName
      if (config?.tableName) tableNames.add(config.tableName);
      
      // 3. 테이블 리스트 컴포넌트 - selectedTable (주요!)
      if (config?.selectedTable) tableNames.add(config.selectedTable);
      
      // 4. 테이블 리스트 컴포넌트 - table 속성
      if (config?.table) tableNames.add(config.table);
      
      // 5. 분할 패널의 leftPanel/rightPanel
      if (config?.leftPanel?.tableName) tableNames.add(config.leftPanel.tableName);
      if (config?.rightPanel?.tableName) tableNames.add(config.rightPanel.tableName);
      if (config?.leftPanel?.table) tableNames.add(config.leftPanel.table);
      if (config?.rightPanel?.table) tableNames.add(config.rightPanel.table);
      if (config?.leftPanel?.selectedTable) tableNames.add(config.leftPanel.selectedTable);
      if (config?.rightPanel?.selectedTable) tableNames.add(config.rightPanel.selectedTable);
      
      // 6. 검색 필터의 tableName
      if (config?.filter?.tableName) tableNames.add(config.filter.tableName);
      
      // 7. properties 안의 tableName
      if (comp.properties?.tableName) tableNames.add(comp.properties.tableName);
      if (comp.properties?.selectedTable) tableNames.add(comp.properties.selectedTable);
      
      // 자식 컴포넌트 탐색
      if (comp.children && Array.isArray(comp.children)) {
        comp.children.forEach(extractTableName);
      }
    };
    
    comps.forEach(extractTableName);
    return tableNames;
  }, []);

  // 이미 로드한 테이블 추적 (무한 루프 방지)
  const loadedTablesRef = useRef<Set<string>>(new Set());

  // 다국어 키 목록 로드 및 테이블별 컬럼 라벨 조회
  useEffect(() => {
    if (!isOpen) return;
    
    // 다국어 키 목록 로드
    const fetchLangKeys = async () => {
      setIsLoadingKeys(true);
      try {
        const response = await apiClient.get("/multilang/keys");
        if (response.data?.success && response.data?.data) {
          setLangKeys(response.data.data.map((k: any) => ({
            keyId: k.keyId,
            langKey: k.langKey,
            description: k.description,
            categoryName: k.categoryName,
          })));
        }
      } catch (error) {
        console.error("다국어 키 목록 로드 실패:", error);
      } finally {
        setIsLoadingKeys(false);
      }
    };
    fetchLangKeys();
    
    // 테이블별 컬럼 라벨 조회
    const tableNames = getTableNamesFromComponents(components);
    
    // 이미 로드한 테이블은 제외
    const tablesToLoad = Array.from(tableNames).filter((t) => !loadedTablesRef.current.has(t));
    
    if (tablesToLoad.length > 0) {
      const fetchColumnLabelsForTables = async () => {
        const newLabelMap: Record<string, Record<string, string>> = {};
        
        for (const tableName of tablesToLoad) {
          try {
            const response = await apiClient.get(`/table-management/tables/${tableName}/columns`);
            if (response.data?.success && response.data?.data) {
              const columns = response.data.data.columns || response.data.data;
              if (Array.isArray(columns)) {
                newLabelMap[tableName] = {};
                columns.forEach((col: any) => {
                  const colName = col.columnName || col.column_name || col.name;
                  const colLabel = col.displayName || col.columnLabel || col.column_label || colName;
                  if (colName) {
                    newLabelMap[tableName][colName] = colLabel;
                  }
                });
                loadedTablesRef.current.add(tableName);
              }
            }
          } catch (error) {
            console.error(`컬럼 라벨 조회 실패 (${tableName}):`, error);
          }
        }
        
        if (Object.keys(newLabelMap).length > 0) {
          setColumnLabelMap((prev) => ({ ...prev, ...newLabelMap }));
        }
      };
      fetchColumnLabelsForTables();
    }
  }, [isOpen, components, getTableNamesFromComponents]);

  // 컴포넌트에서 라벨 추출
  const extractLabelsFromComponents = useCallback((comps: ComponentData[]): ExtractedLabel[] => {
    const labels: ExtractedLabel[] = [];
    const addedLabels = new Set<string>();

    const addLabel = (
      componentId: string,
      label: string,
      type: ExtractedLabel["type"],
      parentType?: string,
      parentLabel?: string,
      langKeyId?: number,
      langKey?: string
    ) => {
      const key = `${componentId}_${type}_${label}`;
      if (label && label.trim() && !addedLabels.has(key)) {
        addedLabels.add(key);
        labels.push({
          id: key,
          componentId,
          label: label.trim(),
          type,
          parentType,
          parentLabel,
          langKeyId,
          langKey,
        });
      }
    };

    const extractFromComponent = (comp: ComponentData, parentType?: string, parentLabel?: string) => {
      const anyComp = comp as any;
      const config = anyComp.componentConfig || anyComp.config;
      const compType = anyComp.componentType || anyComp.type;
      const compLabel = anyComp.label || anyComp.title || compType;

      // 1. 기본 라벨 - 입력 폼 컴포넌트인 경우에만 추출
      if (isInputComponent(anyComp)) {
        if (anyComp.label && typeof anyComp.label === "string") {
          addLabel(comp.id, anyComp.label, "label", parentType, parentLabel, anyComp.langKeyId, anyComp.langKey);
        }
      }

      // 2. 제목
      if (anyComp.title && typeof anyComp.title === "string") {
        addLabel(comp.id, anyComp.title, "title", parentType, parentLabel);
      }

      // 3. 버튼 텍스트 (componentId에 _button 접미사 추가하여 라벨과 구분)
      if (config?.text && typeof config.text === "string") {
        addLabel(
          `${comp.id}_button`,
          config.text,
          "button",
          parentType,
          parentLabel,
          config.langKeyId,
          config.langKey
        );
      }

      // 4. placeholder
      if (anyComp.placeholder && typeof anyComp.placeholder === "string") {
        addLabel(comp.id, anyComp.placeholder, "placeholder", parentType, parentLabel);
      }

      // 5. 테이블 컬럼 - columnLabelMap에서 한글 라벨 조회
      const tableName = config?.selectedTable || config?.tableName || config?.table || anyComp.tableName;
      if (config?.columns && Array.isArray(config.columns)) {
        config.columns.forEach((col: any, index: number) => {
          const colName = col.columnName || col.field || col.name;
          // columnLabelMap에서 한글 라벨 조회, 없으면 displayName 사용
          let colLabel = columnLabelMap[tableName]?.[colName] || col.displayName || col.label || colName;
          
          if (colLabel && typeof colLabel === "string") {
            addLabel(
              `${comp.id}_col_${index}`,
              colLabel,
              "column",
              compType,
              compLabel,
              col.langKeyId,
              col.langKey
            );
          }
        });
      }

      // 6. 분할 패널 제목 및 컬럼 - columnLabelMap에서 한글 라벨 조회
      // 6-1. 좌측 패널 제목
      if (config?.leftPanel?.title && typeof config.leftPanel.title === "string") {
        addLabel(
          `${comp.id}_left_title`,
          config.leftPanel.title,
          "title",
          compType,
          `${compLabel} (좌측)`,
          config.leftPanel.langKeyId,
          config.leftPanel.langKey
        );
      }
      // 6-2. 우측 패널 제목
      if (config?.rightPanel?.title && typeof config.rightPanel.title === "string") {
        addLabel(
          `${comp.id}_right_title`,
          config.rightPanel.title,
          "title",
          compType,
          `${compLabel} (우측)`,
          config.rightPanel.langKeyId,
          config.rightPanel.langKey
        );
      }
      // 6-3. 좌측 패널 컬럼
      const leftTableName = config?.leftPanel?.selectedTable || config?.leftPanel?.tableName || tableName;
      if (config?.leftPanel?.columns && Array.isArray(config.leftPanel.columns)) {
        config.leftPanel.columns.forEach((col: any, index: number) => {
          const colName = col.columnName || col.field || col.name;
          const colLabel = columnLabelMap[leftTableName]?.[colName] || col.displayName || col.label || colName;
          if (colLabel && typeof colLabel === "string") {
            addLabel(
              `${comp.id}_left_col_${index}`,
              colLabel,
              "column",
              compType,
              `${compLabel} (좌측)`,
              col.langKeyId,
              col.langKey
            );
          }
        });
      }
      const rightTableName = config?.rightPanel?.selectedTable || config?.rightPanel?.tableName || tableName;
      if (config?.rightPanel?.columns && Array.isArray(config.rightPanel.columns)) {
        config.rightPanel.columns.forEach((col: any, index: number) => {
          const colName = col.columnName || col.field || col.name;
          const colLabel = columnLabelMap[rightTableName]?.[colName] || col.displayName || col.label || colName;
          if (colLabel && typeof colLabel === "string") {
            addLabel(
              `${comp.id}_right_col_${index}`,
              colLabel,
              "column",
              compType,
              `${compLabel} (우측)`,
              col.langKeyId,
              col.langKey
            );
          }
        });
      }

      // 6-5. 추가 탭 (additionalTabs) 제목 및 컬럼 - rightPanel.additionalTabs 확인
      const additionalTabs = config?.rightPanel?.additionalTabs || config?.additionalTabs;
      if (additionalTabs && Array.isArray(additionalTabs)) {
        additionalTabs.forEach((tab: any, tabIndex: number) => {
          // 탭 라벨
          if (tab.label && typeof tab.label === "string") {
            addLabel(
              `${comp.id}_addtab_${tabIndex}_label`,
              tab.label,
              "tab",
              compType,
              compLabel,
              tab.langKeyId,
              tab.langKey
            );
          }
          // 탭 제목
          if (tab.title && typeof tab.title === "string") {
            addLabel(
              `${comp.id}_addtab_${tabIndex}_title`,
              tab.title,
              "title",
              compType,
              `${compLabel} (탭: ${tab.label || tabIndex})`,
              tab.titleLangKeyId,
              tab.titleLangKey
            );
          }
          // 탭 컬럼
          const tabTableName = tab.tableName || tab.selectedTable || rightTableName;
          if (tab.columns && Array.isArray(tab.columns)) {
            tab.columns.forEach((col: any, colIndex: number) => {
              const colName = col.columnName || col.field || col.name;
              const colLabel = columnLabelMap[tabTableName]?.[colName] || col.displayName || col.label || colName;
              if (colLabel && typeof colLabel === "string") {
                addLabel(
                  `${comp.id}_addtab_${tabIndex}_col_${colIndex}`,
                  colLabel,
                  "column",
                  compType,
                  `${compLabel} (탭: ${tab.label || tabIndex})`,
                  col.langKeyId,
                  col.langKey
                );
              }
            });
          }
        });
      }

      // 7. 검색 필터
      if (config?.filter?.filters && Array.isArray(config.filter.filters)) {
        config.filter.filters.forEach((filter: any, index: number) => {
          if (filter.label && typeof filter.label === "string") {
            addLabel(
              `${comp.id}_filter_${index}`,
              filter.label,
              "filter",
              compType,
              compLabel,
              filter.langKeyId,
              filter.langKey
            );
          }
        });
      }

      // 8. 폼 필드
      if (config?.fields && Array.isArray(config.fields)) {
        config.fields.forEach((field: any, index: number) => {
          if (field.label && typeof field.label === "string") {
            addLabel(
              `${comp.id}_field_${index}`,
              field.label,
              "field",
              compType,
              compLabel,
              field.langKeyId,
              field.langKey
            );
          }
        });
      }

      // 9. 탭
      if (config?.tabs && Array.isArray(config.tabs)) {
        config.tabs.forEach((tab: any, index: number) => {
          if (tab.label && typeof tab.label === "string") {
            addLabel(
              `${comp.id}_tab_${index}`,
              tab.label,
              "tab",
              compType,
              compLabel,
              tab.langKeyId,
              tab.langKey
            );
          }
        });
      }

      // 10. 액션 버튼
      if (config?.actions?.actions && Array.isArray(config.actions.actions)) {
        config.actions.actions.forEach((action: any, index: number) => {
          if (action.label && typeof action.label === "string") {
            addLabel(
              `${comp.id}_action_${index}`,
              action.label,
              "action",
              compType,
              compLabel,
              action.langKeyId,
              action.langKey
            );
          }
        });
      }

      // 11. 집계 위젯 (aggregation-widget) 항목 라벨
      if (compType === "aggregation-widget" && config?.items && Array.isArray(config.items)) {
        config.items.forEach((item: any, index: number) => {
          if (item.columnLabel && typeof item.columnLabel === "string") {
            addLabel(
              `${comp.id}_agg_${item.id || index}`,
              item.columnLabel,
              "label",
              compType,
              compLabel,
              item.labelLangKeyId,
              item.labelLangKey
            );
          }
        });
      }

      // 자식 컴포넌트 재귀 탐색
      if (anyComp.children && Array.isArray(anyComp.children)) {
        anyComp.children.forEach((child: ComponentData) => {
          extractFromComponent(child, compType, compLabel);
        });
      }
    };

    comps.forEach((comp) => extractFromComponent(comp));
    return labels;
  }, [columnLabelMap]);

  // 컴포넌트 변경 시 또는 columnLabelMap 로드 후 라벨 재추출
  useEffect(() => {
    if (isOpen && Object.keys(columnLabelMap).length > 0) {
      const labels = extractLabelsFromComponents(components);
      setExtractedLabels(labels);

      // 기존 langKeyId가 있는 항목들 선택 상태로 초기화
      const initialSelected = new Map<string, { langKeyId?: number; langKey?: string }>();
      labels.forEach((label) => {
        if (label.langKeyId) {
          initialSelected.set(label.id, { langKeyId: label.langKeyId, langKey: label.langKey });
        }
      });
      setSelectedItems(initialSelected);

      // 기본적으로 모든 그룹 펼치기
      const groupIds = new Set<string>();
      labels.forEach((l) => groupIds.add(l.parentType || l.type));
      setExpandedGroups(groupIds);
    } else if (isOpen) {
      // columnLabelMap 로드 전이라도 일단 컴포넌트 라벨은 표시
      const labels = extractLabelsFromComponents(components);
      setExtractedLabels(labels);
      
      const initialSelected = new Map<string, { langKeyId?: number; langKey?: string }>();
      labels.forEach((label) => {
        if (label.langKeyId) {
          initialSelected.set(label.id, { langKeyId: label.langKeyId, langKey: label.langKey });
        }
      });
      setSelectedItems(initialSelected);

      const groupIds = new Set<string>();
      labels.forEach((l) => groupIds.add(l.parentType || l.type));
      setExpandedGroups(groupIds);
    }
  }, [isOpen, components, extractLabelsFromComponents, columnLabelMap]);

  // 모달 열릴 때 연결된 키들의 번역 상태 일괄 조회
  useEffect(() => {
    const loadAllTranslationStatuses = async () => {
      if (!isOpen || activeLanguages.length === 0 || extractedLabels.length === 0) return;

      // 연결된 키가 있는 항목들만 필터링
      const itemsWithKeys = extractedLabels.filter((label) => label.langKeyId);
      if (itemsWithKeys.length === 0) return;

      const newTranslations: Record<string, Record<string, string>> = {};
      const newStatusCache: Record<string, TranslationStatus> = {};

      // 각 키의 번역 상태 조회
      await Promise.all(
        itemsWithKeys.map(async (label) => {
          try {
            const response = await apiClient.get(`/multilang/keys/${label.langKeyId}/texts`);
            if (response.data?.success && response.data?.data) {
              const textsMap: Record<string, string> = {};
              response.data.data.forEach((t: any) => {
                textsMap[t.langCode || t.lang_code] = t.langText || t.lang_text || "";
              });

              // 모든 활성 언어에 대해 번역 텍스트 생성
              const loadedTranslations = activeLanguages.reduce((acc, lang) => {
                acc[lang.langCode] = textsMap[lang.langCode] || "";
                return acc;
              }, {} as Record<string, string>);

              newTranslations[label.id] = loadedTranslations;

              // 번역 상태 계산
              const filledCount = activeLanguages.filter(
                (lang) => loadedTranslations[lang.langCode] && loadedTranslations[lang.langCode].trim() !== ""
              ).length;

              if (filledCount === activeLanguages.length) {
                newStatusCache[label.id] = "complete";
              } else if (filledCount > 0) {
                newStatusCache[label.id] = "partial";
              } else {
                newStatusCache[label.id] = "none";
              }
            }
          } catch (error) {
            console.error(`번역 상태 조회 실패 (keyId: ${label.langKeyId}):`, error);
          }
        })
      );

      // 상태 업데이트
      if (Object.keys(newTranslations).length > 0) {
        setAllEditedTranslations((prev) => ({ ...prev, ...newTranslations }));
      }
      if (Object.keys(newStatusCache).length > 0) {
        setTranslationStatusCache((prev) => ({ ...prev, ...newStatusCache }));
      }
    };

    loadAllTranslationStatuses();
  }, [isOpen, activeLanguages, extractedLabels]);

  // 번역 상태 계산 함수
  const getTranslationStatus = useCallback(
    (itemId: string): TranslationStatus => {
      // 캐시에 있으면 반환
      if (translationStatusCache[itemId]) {
        return translationStatusCache[itemId];
      }

      const connectedKey = selectedItems.get(itemId);
      if (!connectedKey?.langKeyId) {
        return "none"; // 키 미연결
      }

      const translations = allEditedTranslations[itemId];
      if (!translations) {
        return "none"; // 번역 정보 없음
      }

      const filledCount = activeLanguages.filter(
        (lang) => translations[lang.langCode] && translations[lang.langCode].trim() !== ""
      ).length;

      if (filledCount === 0) {
        return "none";
      } else if (filledCount === activeLanguages.length) {
        return "complete";
      } else {
        return "partial";
      }
    },
    [selectedItems, allEditedTranslations, activeLanguages, translationStatusCache]
  );

  // 번역 상태 아이콘 컴포넌트
  const TranslationStatusIcon: React.FC<{ status: TranslationStatus }> = ({ status }) => {
    switch (status) {
      case "complete":
        return <CheckCircle2 className="h-4 w-4 text-emerald-500" />;
      case "partial":
        return <CircleDot className="h-4 w-4 text-amber-500" />;
      case "none":
      default:
        return <Circle className="h-4 w-4 text-muted-foreground/50" />;
    }
  };

  // 번역 상태별 통계 계산
  const translationStats = useMemo(() => {
    let complete = 0;
    let partial = 0;
    let none = 0;

    extractedLabels.forEach((label) => {
      const status = getTranslationStatus(label.id);
      if (status === "complete") complete++;
      else if (status === "partial") partial++;
      else none++;
    });

    return { complete, partial, none, total: extractedLabels.length };
  }, [extractedLabels, getTranslationStatus]);

  // 진행률 계산 (완료 + 부분완료*0.5)
  const progressPercentage = useMemo(() => {
    if (translationStats.total === 0) return 0;
    const score = translationStats.complete + translationStats.partial * 0.5;
    return Math.round((score / translationStats.total) * 100);
  }, [translationStats]);

  // 라벨을 부모 타입별로 그룹화
  const groupedLabels = useMemo(() => {
    const groups: LabelGroup[] = [];
    const groupMap = new Map<string, ExtractedLabel[]>();

    extractedLabels.forEach((label) => {
      const groupKey = label.parentType || label.type;
      if (!groupMap.has(groupKey)) {
        groupMap.set(groupKey, []);
      }
      groupMap.get(groupKey)!.push(label);
    });

    groupMap.forEach((items, key) => {
      // 검색 필터링
      let filteredItems = searchText
        ? items.filter(
            (item) =>
              item.label.toLowerCase().includes(searchText.toLowerCase()) ||
              item.langKey?.toLowerCase().includes(searchText.toLowerCase())
          )
        : items;

      // 번역 상태 필터링
      if (translationFilter !== "all") {
        filteredItems = filteredItems.filter((item) => {
          const status = getTranslationStatus(item.id);
          if (translationFilter === "complete") {
            return status === "complete";
          } else if (translationFilter === "incomplete") {
            return status === "partial" || status === "none";
          }
          return true;
        });
      }

      if (filteredItems.length > 0) {
        groups.push({
          id: key,
          label: items[0].parentLabel || getTypeLabel(key),
          type: key,
          icon: getTypeIcon(key),
          items: filteredItems,
          isExpanded: expandedGroups.has(key),
        });
      }
    });

    return groups;
  }, [extractedLabels, searchText, expandedGroups, translationFilter, getTranslationStatus]);

  // 그룹 펼침/접기 토글
  const toggleGroup = (groupId: string) => {
    setExpandedGroups((prev) => {
      const next = new Set(prev);
      if (next.has(groupId)) {
        next.delete(groupId);
      } else {
        next.add(groupId);
      }
      return next;
    });
  };

  // 키 선택 핸들러
  const handleKeySelect = (itemId: string, key: { keyId: number; langKey: string } | null) => {
    setSelectedItems((prev) => {
      const next = new Map(prev);
      if (key) {
        next.set(itemId, { langKeyId: key.keyId, langKey: key.langKey });
      } else {
        next.delete(itemId);
      }
      return next;
    });
  };

  // 연결된 키 개수
  const connectedCount = selectedItems.size;
  const totalCount = extractedLabels.length;

  // 현재 선택된 항목의 편집된 번역
  const currentTranslations = selectedLabelItem ? (allEditedTranslations[selectedLabelItem.id] || {}) : {};

  // 언어 목록 로드
  useEffect(() => {
    const loadLanguages = async () => {
      try {
        const response = await apiClient.get("/multilang/languages");
        if (response.data?.success && Array.isArray(response.data.data)) {
          const activeLangs = response.data.data
            .filter((lang: any) => (lang.isActive || lang.is_active) === "Y")
            .map((lang: any) => ({
              langCode: lang.langCode || lang.lang_code,
              langName: lang.langName || lang.lang_name,
              langNative: lang.langNative || lang.lang_native,
            }));
          setActiveLanguages(activeLangs);
        }
      } catch (error) {
        console.error("언어 목록 로드 실패:", error);
      }
    };
    if (isOpen) {
      loadLanguages();
    }
  }, [isOpen]);

  // 선택된 라벨의 번역 텍스트 로드
  useEffect(() => {
    const loadTranslations = async () => {
      if (!selectedLabelItem) {
        return;
      }

      // 언어 목록이 아직 로드되지 않았으면 대기
      if (activeLanguages.length === 0) {
        return;
      }

      // 이미 이 항목의 번역을 로드한 적이 있으면 스킵
      if (allEditedTranslations[selectedLabelItem.id]) {
        return;
      }

      const connectedKey = selectedItems.get(selectedLabelItem.id);
      if (!connectedKey?.langKeyId) {
        // 키가 연결되지 않은 경우 빈 번역으로 초기화
        const defaultTranslations = activeLanguages.reduce((acc, lang) => {
          acc[lang.langCode] = lang.langCode === "KR" ? selectedLabelItem.label : "";
          return acc;
        }, {} as Record<string, string>);
        
        setAllEditedTranslations((prev) => ({
          ...prev,
          [selectedLabelItem.id]: defaultTranslations,
        }));
        return;
      }

      setIsLoadingTranslations(true);
      try {
        const response = await apiClient.get(`/multilang/keys/${connectedKey.langKeyId}/texts`);
        if (response.data?.success && response.data?.data) {
          const textsMap: Record<string, string> = {};
          response.data.data.forEach((t: any) => {
            textsMap[t.langCode || t.lang_code] = t.langText || t.lang_text || "";
          });

          // 모든 활성 언어에 대해 번역 텍스트 생성
          const loadedTranslations = activeLanguages.reduce((acc, lang) => {
            acc[lang.langCode] = textsMap[lang.langCode] || "";
            return acc;
          }, {} as Record<string, string>);

          setAllEditedTranslations((prev) => ({
            ...prev,
            [selectedLabelItem.id]: loadedTranslations,
          }));

          // 번역 상태 캐시 업데이트
          const filledCount = activeLanguages.filter(
            (lang) => loadedTranslations[lang.langCode] && loadedTranslations[lang.langCode].trim() !== ""
          ).length;
          let status: TranslationStatus = "none";
          if (filledCount === activeLanguages.length) {
            status = "complete";
          } else if (filledCount > 0) {
            status = "partial";
          }
          setTranslationStatusCache((prev) => ({
            ...prev,
            [selectedLabelItem.id]: status,
          }));
        }
      } catch (error) {
        console.error("번역 텍스트 로드 실패:", error);
      } finally {
        setIsLoadingTranslations(false);
      }
    };

    loadTranslations();
  }, [selectedLabelItem, selectedItems, activeLanguages, allEditedTranslations]);

  // 현재 항목의 번역 텍스트 변경
  const handleTranslationChange = (langCode: string, text: string) => {
    if (!selectedLabelItem) return;
    
    const updatedTranslations = {
      ...(allEditedTranslations[selectedLabelItem.id] || {}),
      [langCode]: text,
    };
    
    setAllEditedTranslations((prev) => ({
      ...prev,
      [selectedLabelItem.id]: updatedTranslations,
    }));

    // 번역 상태 캐시 업데이트
    const filledCount = activeLanguages.filter(
      (lang) => {
        const val = lang.langCode === langCode ? text : updatedTranslations[lang.langCode];
        return val && val.trim() !== "";
      }
    ).length;
    
    let status: TranslationStatus = "none";
    if (filledCount === activeLanguages.length) {
      status = "complete";
    } else if (filledCount > 0) {
      status = "partial";
    }
    
    setTranslationStatusCache((prev) => ({
      ...prev,
      [selectedLabelItem.id]: status,
    }));
  };

  // 모든 번역 텍스트 저장 (최종 저장 시)
  const handleSaveAllTranslations = async () => {
    const savePromises: Promise<void>[] = [];
    
    // 키가 연결된 항목들의 번역만 저장
    for (const [itemId, translations] of Object.entries(allEditedTranslations)) {
      const connectedKey = selectedItems.get(itemId);
      if (!connectedKey?.langKeyId) continue;
      
      const texts = activeLanguages.map((lang) => ({
        langCode: lang.langCode,
        langText: translations[lang.langCode] || "",
      }));
      
      savePromises.push(
        apiClient.post(`/multilang/keys/${connectedKey.langKeyId}/texts`, { texts })
          .then(() => {})
          .catch((error) => {
            console.error(`번역 저장 실패 (keyId: ${connectedKey.langKeyId}):`, error);
          })
      );
    }
    
    await Promise.all(savePromises);
  };

  // 모달 닫힐 때 선택 초기화
  useEffect(() => {
    if (!isOpen) {
      setSelectedLabelItem(null);
      setAllEditedTranslations({});
      setTranslationFilter("all");
      setTranslationStatusCache({});
    }
  }, [isOpen]);

  return (
    <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
      <DialogContent className="max-h-[85vh] max-w-5xl">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <Languages className="h-5 w-5" />
            다국어 설정
            <Badge variant="secondary" className="ml-2">
              {connectedCount} / {totalCount} 연결됨
            </Badge>
          </DialogTitle>
        </DialogHeader>

        {/* 좌우 분할 레이아웃 */}
        <div className="flex gap-4" style={{ height: "500px" }}>
          {/* 왼쪽: 라벨 목록 */}
          <div className="flex w-1/2 flex-col overflow-hidden">
            {/* 검색 및 필터 */}
            <div className="mb-2 flex shrink-0 gap-2">
              <div className="relative flex-1">
                <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                <Input
                  placeholder="라벨 또는 키로 검색..."
                  value={searchText}
                  onChange={(e) => setSearchText(e.target.value)}
                  className="pl-10"
                />
              </div>
              <Select
                value={translationFilter}
                onValueChange={(value) => setTranslationFilter(value as TranslationFilter)}
              >
                <SelectTrigger className="w-[120px]">
                  <SelectValue placeholder="필터" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="all">전체</SelectItem>
                  <SelectItem value="complete">번역완료</SelectItem>
                  <SelectItem value="incomplete">번역필요</SelectItem>
                </SelectContent>
              </Select>
            </div>

            {/* 라벨 목록 */}
            <ScrollArea className="min-h-0 flex-1 rounded-md border">
              <div className="p-2">
                {groupedLabels.length === 0 ? (
                  <div className="flex h-32 items-center justify-center text-sm text-muted-foreground">
                    {searchText ? "검색 결과가 없습니다." : "다국어 대상이 없습니다."}
                  </div>
                ) : (
                  groupedLabels.map((group) => (
                    <div key={group.id} className="mb-2">
                      {/* 그룹 헤더 */}
                      <button
                        onClick={() => toggleGroup(group.id)}
                        className="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm font-medium hover:bg-muted"
                      >
                        {group.isExpanded ? (
                          <ChevronDown className="h-4 w-4" />
                        ) : (
                          <ChevronRight className="h-4 w-4" />
                        )}
                        {group.icon}
                        <span>{group.label}</span>
                        <Badge variant="outline" className="ml-auto">
                          {group.items.filter((i) => selectedItems.has(i.id)).length} / {group.items.length}
                        </Badge>
                      </button>

                      {/* 그룹 아이템 */}
                      {group.isExpanded && (
                        <div className="ml-6 mt-1 space-y-1">
                          {group.items.map((item) => {
                            const isConnected = selectedItems.has(item.id);
                            const isSelected = selectedLabelItem?.id === item.id;
                            const translationStatus = getTranslationStatus(item.id);

                            return (
                              <div
                                key={item.id}
                                onClick={() => setSelectedLabelItem(item)}
                                className={cn(
                                  "flex cursor-pointer items-center gap-2 rounded-md border px-3 py-2 text-sm transition-colors",
                                  isSelected
                                    ? "border-primary bg-primary/10 ring-1 ring-primary"
                                    : translationStatus === "complete"
                                      ? "border-emerald-200 bg-emerald-50 hover:bg-emerald-100"
                                      : translationStatus === "partial"
                                        ? "border-amber-200 bg-amber-50 hover:bg-amber-100"
                                        : "border-border bg-white hover:bg-muted"
                                )}
                              >
                                {/* 번역 상태 아이콘 */}
                                <div className="shrink-0">
                                  <TranslationStatusIcon status={translationStatus} />
                                </div>

                                {/* 타입 배지 */}
                                <Badge variant="outline" className="shrink-0 text-xs">
                                  {getTypeLabel(item.type)}
                                </Badge>

                                {/* 라벨 텍스트 */}
                                <span className="flex-1 truncate font-medium">{item.label}</span>
                              </div>
                            );
                          })}
                        </div>
                      )}
                    </div>
                  ))
                )}
              </div>
            </ScrollArea>
          </div>

          {/* 오른쪽: 선택된 항목 상세 및 번역 편집 */}
          <div className="flex w-1/2 flex-col rounded-md border bg-muted p-4">
            {selectedLabelItem ? (
              <>
                {/* 선택된 항목 정보 */}
                <div className="mb-4 rounded-md border bg-white p-3">
                  <div className="mb-2 flex items-center gap-2">
                    <Badge variant="outline">{getTypeLabel(selectedLabelItem.type)}</Badge>
                    <span className="font-medium">{selectedLabelItem.label}</span>
                  </div>

                  {/* 키 선택 */}
                  <div className="flex items-center gap-2">
                    <span className="text-sm text-muted-foreground">다국어 키:</span>
                    <KeySelectCombobox
                      value={
                        selectedItems.get(selectedLabelItem.id)?.langKeyId &&
                        selectedItems.get(selectedLabelItem.id)?.langKey
                          ? {
                              keyId: selectedItems.get(selectedLabelItem.id)!.langKeyId!,
                              langKey: selectedItems.get(selectedLabelItem.id)!.langKey!,
                            }
                          : undefined
                      }
                      onChange={(key) => handleKeySelect(selectedLabelItem.id, key)}
                      langKeys={langKeys}
                      isLoading={isLoadingKeys}
                    />
                  </div>
                </div>

                {/* 번역 텍스트 편집 */}
                <div className="flex-1 overflow-hidden">
                  <div className="mb-2">
                    <h4 className="text-sm font-medium">번역 텍스트</h4>
                  </div>

                  {isLoadingTranslations || activeLanguages.length === 0 ? (
                    <div className="flex h-32 items-center justify-center">
                      <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
                    </div>
                  ) : !selectedItems.get(selectedLabelItem.id)?.langKeyId ? (
                    <div className="flex h-32 items-center justify-center text-sm text-muted-foreground">
                      먼저 다국어 키를 선택해주세요
                    </div>
                  ) : (
                    <ScrollArea className="h-[280px]">
                      <div className="space-y-3 pr-4">
                        {activeLanguages.map((lang) => (
                          <div key={lang.langCode} className="rounded-md border bg-white p-3">
                            <div className="mb-1.5 flex items-center gap-2">
                              <Badge variant="secondary" className="text-xs">
                                {lang.langCode}
                              </Badge>
                              <span className="text-xs text-muted-foreground">
                                {lang.langNative || lang.langName}
                              </span>
                            </div>
                            <Input
                              value={currentTranslations[lang.langCode] || ""}
                              onChange={(e) => handleTranslationChange(lang.langCode, e.target.value)}
                              placeholder={`${lang.langName} 번역 입력...`}
                              className="h-9 text-sm"
                            />
                          </div>
                        ))}
                      </div>
                    </ScrollArea>
                  )}
                </div>
              </>
            ) : (
              <div className="flex h-full flex-col items-center justify-center text-muted-foreground">
                <Languages className="mb-2 h-12 w-12 opacity-20" />
                <p className="text-sm">좌측에서 항목을 선택하세요</p>
                <p className="text-xs">선택한 항목의 다국어 설정을 할 수 있습니다</p>
              </div>
            )}
          </div>
        </div>

        {/* 하단 진행률 표시 */}
        <div className="mb-2 rounded-md border bg-muted/30 p-3">
          <div className="mb-2 flex items-center justify-between">
            <div className="flex items-center gap-4 text-sm">
              <span className="font-medium">번역 현황</span>
              <div className="flex items-center gap-3 text-xs text-muted-foreground">
                <span className="flex items-center gap-1">
                  <CheckCircle2 className="h-3 w-3 text-emerald-500" />
                  완료 {translationStats.complete}
                </span>
                <span className="flex items-center gap-1">
                  <CircleDot className="h-3 w-3 text-amber-500" />
                  부분 {translationStats.partial}
                </span>
                <span className="flex items-center gap-1">
                  <Circle className="h-3 w-3 text-muted-foreground/50" />
                  미완료 {translationStats.none}
                </span>
              </div>
            </div>
            <span className="text-sm font-medium">{progressPercentage}%</span>
          </div>
          <Progress value={progressPercentage} className="h-2" />
        </div>

        <DialogFooter className="gap-2">
          <Button variant="outline" onClick={onClose}>
            닫기
          </Button>
          <Button
            disabled={isSaving}
            onClick={async () => {
              setIsSaving(true);
              try {
                // 1. 번역 텍스트 저장
                await handleSaveAllTranslations();
                
                // 2. 컴포넌트 매핑 저장
                const updates = Array.from(selectedItems.entries())
                  .filter(([, data]) => data.langKeyId && data.langKey)
                  .map(([id, data]) => ({
                    componentId: id,
                    langKeyId: data.langKeyId!,
                    langKey: data.langKey!,
                  }));
                onSave(updates);
                onClose();
              } catch (error) {
                console.error("저장 실패:", error);
              } finally {
                setIsSaving(false);
              }
            }}
          >
            {isSaving ? (
              <>
                <Loader2 className="mr-1 h-4 w-4 animate-spin" />
                저장 중...
              </>
            ) : (
              "저장"
            )}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
};

export default MultilangSettingsModal;
