"use client";

/**
 * UnifiedRepeater 컴포넌트
 *
 * 렌더링 모드:
 * - inline: 현재 테이블 컬럼 직접 입력
 * - modal: 엔티티 선택 (FK 저장) + 추가 입력 컬럼
 *
 * RepeaterTable 및 ItemSelectionModal 재사용
 */

import React, { useState, useEffect, useCallback, useMemo, useRef } from "react";
import { Button } from "@/components/ui/button";
import { Plus } from "lucide-react";
import { cn } from "@/lib/utils";
import {
  UnifiedRepeaterConfig,
  UnifiedRepeaterProps,
  RepeaterColumnConfig as UnifiedColumnConfig,
  DEFAULT_REPEATER_CONFIG,
} from "@/types/unified-repeater";
import { apiClient } from "@/lib/api/client";
import { allocateNumberingCode } from "@/lib/api/numberingRule";

// modal-repeater-table 컴포넌트 재사용
import { RepeaterTable } from "@/lib/registry/components/modal-repeater-table/RepeaterTable";
import { ItemSelectionModal } from "@/lib/registry/components/modal-repeater-table/ItemSelectionModal";
import { RepeaterColumnConfig } from "@/lib/registry/components/modal-repeater-table/types";

// 전역 UnifiedRepeater 등록 (buttonActions에서 사용)
declare global {
  interface Window {
    __unifiedRepeaterInstances?: Set<string>;
  }
}

export const UnifiedRepeater: React.FC<UnifiedRepeaterProps> = ({
  config: propConfig,
  parentId,
  data: initialData,
  onDataChange,
  onRowClick,
  className,
}) => {
  // 설정 병합
  const config: UnifiedRepeaterConfig = useMemo(
    () => ({
      ...DEFAULT_REPEATER_CONFIG,
      ...propConfig,
      dataSource: { ...DEFAULT_REPEATER_CONFIG.dataSource, ...propConfig.dataSource },
      features: { ...DEFAULT_REPEATER_CONFIG.features, ...propConfig.features },
      modal: { ...DEFAULT_REPEATER_CONFIG.modal, ...propConfig.modal },
    }),
    [propConfig],
  );

  // 상태
  const [data, setData] = useState<any[]>(initialData || []);
  const [selectedRows, setSelectedRows] = useState<Set<number>>(new Set());
  const [modalOpen, setModalOpen] = useState(false);

  // 🆕 데이터 변경 시 자동으로 컬럼 너비 조정 트리거
  const [autoWidthTrigger, setAutoWidthTrigger] = useState(0);

  // 소스 테이블 컬럼 라벨 매핑
  const [sourceColumnLabels, setSourceColumnLabels] = useState<Record<string, string>>({});

  // 🆕 소스 테이블의 카테고리 타입 컬럼 목록
  const [sourceCategoryColumns, setSourceCategoryColumns] = useState<string[]>([]);

  // 🆕 카테고리 코드 → 라벨 매핑 (RepeaterTable 표시용)
  const [categoryLabelMap, setCategoryLabelMap] = useState<Record<string, string>>({});

  // 현재 테이블 컬럼 정보 (inputType 매핑용)
  const [currentTableColumnInfo, setCurrentTableColumnInfo] = useState<Record<string, any>>({});

  // 동적 데이터 소스 상태
  const [activeDataSources, setActiveDataSources] = useState<Record<string, string>>({});

  // 🆕 최신 엔티티 참조 정보 (column_labels에서 조회)
  const [resolvedSourceTable, setResolvedSourceTable] = useState<string>("");
  const [resolvedReferenceKey, setResolvedReferenceKey] = useState<string>("id");

  const isModalMode = config.renderMode === "modal";

  // 전역 리피터 등록
  useEffect(() => {
    const tableName = config.dataSource?.tableName;
    if (tableName) {
      if (!window.__unifiedRepeaterInstances) {
        window.__unifiedRepeaterInstances = new Set();
      }
      window.__unifiedRepeaterInstances.add(tableName);
    }

    return () => {
      if (tableName && window.__unifiedRepeaterInstances) {
        window.__unifiedRepeaterInstances.delete(tableName);
      }
    };
  }, [config.dataSource?.tableName]);

  // 저장 이벤트 리스너
  useEffect(() => {
    const handleSaveEvent = async (event: CustomEvent) => {
      const tableName = config.dataSource?.tableName;
      const eventParentId = event.detail?.parentId;
      const mainFormData = event.detail?.mainFormData;

      if (!tableName || data.length === 0) {
        return;
      }

      try {
        // 테이블 유효 컬럼 조회
        let validColumns: Set<string> = new Set();
        try {
          const columnsResponse = await apiClient.get(`/table-management/tables/${tableName}/columns`);
          const columns =
            columnsResponse.data?.data?.columns || columnsResponse.data?.columns || columnsResponse.data || [];
          validColumns = new Set(columns.map((col: any) => col.columnName || col.column_name || col.name));
        } catch {
          console.warn("테이블 컬럼 정보 조회 실패");
        }

        for (let i = 0; i < data.length; i++) {
          const row = data[i];

          // 내부 필드 제거
          const cleanRow = Object.fromEntries(Object.entries(row).filter(([key]) => !key.startsWith("_")));

          // 메인 폼 데이터 병합
          const { id: _mainId, ...mainFormDataWithoutId } = mainFormData || {};
          const mergedData = {
            ...mainFormDataWithoutId,
            ...cleanRow,
          };

          // 유효하지 않은 컬럼 제거
          const filteredData: Record<string, any> = {};
          for (const [key, value] of Object.entries(mergedData)) {
            if (validColumns.size === 0 || validColumns.has(key)) {
              filteredData[key] = value;
            }
          }

          await apiClient.post(`/table-management/tables/${tableName}/add`, filteredData);
        }

        console.log("UnifiedRepeater 저장 완료:", data.length, "건");
      } catch (error) {
        console.error("UnifiedRepeater 저장 실패:", error);
        throw error;
      }
    };

    window.addEventListener("repeaterSave" as any, handleSaveEvent);
    return () => {
      window.removeEventListener("repeaterSave" as any, handleSaveEvent);
    };
  }, [data, config.dataSource?.tableName, parentId]);

  // 현재 테이블 컬럼 정보 로드
  useEffect(() => {
    const loadCurrentTableColumnInfo = async () => {
      const tableName = config.dataSource?.tableName;
      if (!tableName) return;

      try {
        const response = await apiClient.get(`/table-management/tables/${tableName}/columns`);
        const columns = response.data?.data?.columns || response.data?.columns || response.data || [];

        const columnMap: Record<string, any> = {};
        columns.forEach((col: any) => {
          const name = col.columnName || col.column_name || col.name;
          columnMap[name] = {
            inputType: col.inputType || col.input_type || col.webType || "text",
            displayName: col.displayName || col.display_name || col.label || name,
            detailSettings: col.detailSettings || col.detail_settings,
          };
        });
        setCurrentTableColumnInfo(columnMap);
      } catch (error) {
        console.error("컬럼 정보 로드 실패:", error);
      }
    };
    loadCurrentTableColumnInfo();
  }, [config.dataSource?.tableName]);

  // 🆕 FK 컬럼 기반으로 최신 참조 테이블 정보 조회 (column_labels에서)
  useEffect(() => {
    const resolveEntityReference = async () => {
      const tableName = config.dataSource?.tableName;
      const foreignKey = config.dataSource?.foreignKey;

      if (!isModalMode || !tableName || !foreignKey) {
        // config에 저장된 값을 기본값으로 사용
        setResolvedSourceTable(config.dataSource?.sourceTable || "");
        setResolvedReferenceKey(config.dataSource?.referenceKey || "id");
        return;
      }

      try {
        // 현재 테이블의 컬럼 정보에서 FK 컬럼의 참조 테이블 조회
        const response = await apiClient.get(`/table-management/tables/${tableName}/columns`);
        const columns = response.data?.data?.columns || response.data?.columns || response.data || [];

        const fkColumn = columns.find((col: any) => (col.columnName || col.column_name || col.name) === foreignKey);

        if (fkColumn) {
          // column_labels의 reference_table 사용 (항상 최신값)
          const refTable =
            fkColumn.detailSettings?.referenceTable ||
            fkColumn.reference_table ||
            fkColumn.referenceTable ||
            config.dataSource?.sourceTable ||
            "";
          const refKey =
            fkColumn.detailSettings?.referenceColumn ||
            fkColumn.reference_column ||
            fkColumn.referenceColumn ||
            config.dataSource?.referenceKey ||
            "id";

          console.log("🔄 [UnifiedRepeater] 엔티티 참조 정보 조회:", {
            foreignKey,
            resolvedSourceTable: refTable,
            resolvedReferenceKey: refKey,
            configSourceTable: config.dataSource?.sourceTable,
          });

          setResolvedSourceTable(refTable);
          setResolvedReferenceKey(refKey);
        } else {
          // FK 컬럼을 찾지 못한 경우 config 값 사용
          setResolvedSourceTable(config.dataSource?.sourceTable || "");
          setResolvedReferenceKey(config.dataSource?.referenceKey || "id");
        }
      } catch (error) {
        console.error("엔티티 참조 정보 조회 실패:", error);
        // 오류 시 config 값 사용
        setResolvedSourceTable(config.dataSource?.sourceTable || "");
        setResolvedReferenceKey(config.dataSource?.referenceKey || "id");
      }
    };

    resolveEntityReference();
  }, [
    config.dataSource?.tableName,
    config.dataSource?.foreignKey,
    config.dataSource?.sourceTable,
    config.dataSource?.referenceKey,
    isModalMode,
  ]);

  // 소스 테이블 컬럼 라벨 로드 (modal 모드) - resolvedSourceTable 사용
  // 🆕 카테고리 타입 컬럼도 함께 감지
  useEffect(() => {
    const loadSourceColumnLabels = async () => {
      if (!isModalMode || !resolvedSourceTable) return;

      try {
        const response = await apiClient.get(`/table-management/tables/${resolvedSourceTable}/columns`);
        const columns = response.data?.data?.columns || response.data?.columns || response.data || [];

        const labels: Record<string, string> = {};
        const categoryCols: string[] = [];

        columns.forEach((col: any) => {
          const name = col.columnName || col.column_name || col.name;
          labels[name] = col.displayName || col.display_name || col.label || name;

          // 🆕 카테고리 타입 컬럼 감지
          const inputType = col.inputType || col.input_type || "";
          if (inputType === "category") {
            categoryCols.push(name);
          }
        });

        setSourceColumnLabels(labels);
        setSourceCategoryColumns(categoryCols);
      } catch (error) {
        console.error("소스 컬럼 라벨 로드 실패:", error);
      }
    };
    loadSourceColumnLabels();
  }, [resolvedSourceTable, isModalMode]);

  // UnifiedColumnConfig → RepeaterColumnConfig 변환
  // 🆕 모든 컬럼을 columns 배열의 순서대로 처리 (isSourceDisplay 플래그로 구분)
  const repeaterColumns: RepeaterColumnConfig[] = useMemo(() => {
    return config.columns
      .filter((col: UnifiedColumnConfig) => col.visible !== false)
      .map((col: UnifiedColumnConfig): RepeaterColumnConfig => {
        const colInfo = currentTableColumnInfo[col.key];
        const inputType = col.inputType || colInfo?.inputType || "text";

        // 소스 표시 컬럼인 경우 (모달 모드에서 읽기 전용)
        if (col.isSourceDisplay) {
          const label = col.title || sourceColumnLabels[col.key] || col.key;
          return {
            field: `_display_${col.key}`,
            label,
            type: "text",
            editable: false,
            calculated: true,
            width: col.width === "auto" ? undefined : col.width,
          };
        }

        // 일반 입력 컬럼
        let type: "text" | "number" | "date" | "select" | "category" = "text";
        if (inputType === "number" || inputType === "decimal") type = "number";
        else if (inputType === "date" || inputType === "datetime") type = "date";
        else if (inputType === "code") type = "select";
        else if (inputType === "category") type = "category"; // 🆕 카테고리 타입

        // 🆕 카테고리 참조 ID 가져오기 (tableName.columnName 형식)
        // category 타입인 경우 현재 테이블명과 컬럼명을 조합
        let categoryRef: string | undefined;
        if (inputType === "category") {
          // 🆕 소스 표시 컬럼이면 소스 테이블 사용, 아니면 타겟 테이블 사용
          const tableName = col.isSourceDisplay ? resolvedSourceTable : config.dataSource?.tableName;
          if (tableName) {
            categoryRef = `${tableName}.${col.key}`;
          }
        }

        return {
          field: col.key,
          label: col.title || colInfo?.displayName || col.key,
          type,
          editable: col.editable !== false,
          width: col.width === "auto" ? undefined : col.width,
          required: false,
          categoryRef, // 🆕 카테고리 참조 ID 전달
          hidden: col.hidden, // 🆕 히든 처리
          autoFill: col.autoFill, // 🆕 자동 입력 설정
        };
      });
  }, [config.columns, sourceColumnLabels, currentTableColumnInfo, resolvedSourceTable, config.dataSource?.tableName]);

  // 🆕 데이터 변경 시 카테고리 라벨 로드 (RepeaterTable 표시용)
  useEffect(() => {
    const loadCategoryLabels = async () => {
      if (sourceCategoryColumns.length === 0 || data.length === 0) {
        return;
      }

      // 데이터에서 카테고리 컬럼의 모든 고유 코드 수집
      const allCodes = new Set<string>();
      for (const row of data) {
        for (const col of sourceCategoryColumns) {
          // _display_ 접두사가 있는 컬럼과 원본 컬럼 모두 확인
          const val = row[`_display_${col}`] || row[col];
          if (val && typeof val === "string") {
            const codes = val
              .split(",")
              .map((c: string) => c.trim())
              .filter(Boolean);
            for (const code of codes) {
              if (!categoryLabelMap[code] && code.startsWith("CATEGORY_")) {
                allCodes.add(code);
              }
            }
          }
        }
      }

      if (allCodes.size === 0) {
        return;
      }

      try {
        const response = await apiClient.post("/table-categories/labels-by-codes", {
          valueCodes: Array.from(allCodes),
        });

        if (response.data?.success && response.data.data) {
          setCategoryLabelMap((prev) => ({
            ...prev,
            ...response.data.data,
          }));
        }
      } catch (error) {
        console.error("카테고리 라벨 조회 실패:", error);
      }
    };

    loadCategoryLabels();
  }, [data, sourceCategoryColumns]);

  // 데이터 변경 핸들러
  const handleDataChange = useCallback(
    (newData: any[]) => {
      setData(newData);
      onDataChange?.(newData);
      // 🆕 데이터 변경 시 자동으로 컬럼 너비 조정
      setAutoWidthTrigger((prev) => prev + 1);
    },
    [onDataChange],
  );

  // 행 변경 핸들러
  const handleRowChange = useCallback(
    (index: number, newRow: any) => {
      const newData = [...data];
      newData[index] = newRow;
      // 🆕 handleDataChange 대신 직접 호출 (행 변경마다 너비 조정은 불필요)
      setData(newData);
      onDataChange?.(newData);
    },
    [data, onDataChange],
  );

  // 행 삭제 핸들러
  const handleRowDelete = useCallback(
    (index: number) => {
      const newData = data.filter((_, i) => i !== index);
      handleDataChange(newData); // 🆕 handleDataChange 사용

      // 선택 상태 업데이트
      const newSelected = new Set<number>();
      selectedRows.forEach((i) => {
        if (i < index) newSelected.add(i);
        else if (i > index) newSelected.add(i - 1);
      });
      setSelectedRows(newSelected);
    },
    [data, selectedRows, handleDataChange],
  );

  // 일괄 삭제 핸들러
  const handleBulkDelete = useCallback(() => {
    const newData = data.filter((_, index) => !selectedRows.has(index));
    handleDataChange(newData); // 🆕 handleDataChange 사용
    setSelectedRows(new Set());
  }, [data, selectedRows, handleDataChange]);

  // 행 추가 (inline 모드)
  // 🆕 자동 입력 값 생성 함수 (동기 - 채번 제외)
  const generateAutoFillValueSync = useCallback(
    (col: any, rowIndex: number, mainFormData?: Record<string, unknown>) => {
      if (!col.autoFill || col.autoFill.type === "none") return undefined;

      const now = new Date();
      
      switch (col.autoFill.type) {
        case "currentDate":
          return now.toISOString().split("T")[0]; // YYYY-MM-DD
        
        case "currentDateTime":
          return now.toISOString().slice(0, 19).replace("T", " "); // YYYY-MM-DD HH:mm:ss
        
        case "sequence":
          return rowIndex + 1; // 1부터 시작하는 순번
        
        case "numbering":
          // 채번은 별도 비동기 처리 필요
          return null; // null 반환하여 비동기 처리 필요함을 표시
        
        case "fromMainForm":
          if (col.autoFill.sourceField && mainFormData) {
            return mainFormData[col.autoFill.sourceField];
          }
          return "";
        
        case "fixed":
          return col.autoFill.fixedValue ?? "";
        
        default:
          return undefined;
      }
    },
    [],
  );

  // 🆕 채번 API 호출 (비동기)
  const generateNumberingCode = useCallback(async (ruleId: string): Promise<string> => {
    try {
      const result = await allocateNumberingCode(ruleId);
      if (result.success && result.data?.generatedCode) {
        return result.data.generatedCode;
      }
      console.error("채번 실패:", result.error);
      return "";
    } catch (error) {
      console.error("채번 API 호출 실패:", error);
      return "";
    }
  }, []);

  // 🆕 행 추가 (inline 모드 또는 모달 열기) - 비동기로 변경
  const handleAddRow = useCallback(async () => {
    if (isModalMode) {
      setModalOpen(true);
    } else {
      const newRow: any = { _id: `new_${Date.now()}` };
      const currentRowCount = data.length;
      
      // 먼저 동기적 자동 입력 값 적용
      for (const col of config.columns) {
        const autoValue = generateAutoFillValueSync(col, currentRowCount);
        if (autoValue === null && col.autoFill?.type === "numbering" && col.autoFill.numberingRuleId) {
          // 채번 규칙: 즉시 API 호출
          newRow[col.key] = await generateNumberingCode(col.autoFill.numberingRuleId);
        } else if (autoValue !== undefined) {
          newRow[col.key] = autoValue;
        } else {
          newRow[col.key] = "";
        }
      }
      
      const newData = [...data, newRow];
      handleDataChange(newData);
    }
  }, [isModalMode, config.columns, data, handleDataChange, generateAutoFillValueSync, generateNumberingCode]);

  // 모달에서 항목 선택 - 비동기로 변경
  const handleSelectItems = useCallback(
    async (items: Record<string, unknown>[]) => {
      const fkColumn = config.dataSource?.foreignKey;
      const currentRowCount = data.length;

      // 채번이 필요한 컬럼 찾기
      const numberingColumns = config.columns.filter(
        (col) => !col.isSourceDisplay && col.autoFill?.type === "numbering" && col.autoFill.numberingRuleId
      );

      const newRows = await Promise.all(
        items.map(async (item, index) => {
          const row: any = { _id: `new_${Date.now()}_${Math.random()}` };

          // FK 값 저장 (resolvedReferenceKey 사용)
          if (fkColumn && item[resolvedReferenceKey]) {
            row[fkColumn] = item[resolvedReferenceKey];
          }

          // 모든 컬럼 처리 (순서대로)
          for (const col of config.columns) {
            if (col.isSourceDisplay) {
              // 소스 표시 컬럼: 소스 테이블에서 값 복사 (읽기 전용)
              row[`_display_${col.key}`] = item[col.key] || "";
            } else {
              // 자동 입력 값 적용
              const autoValue = generateAutoFillValueSync(col, currentRowCount + index);
              if (autoValue === null && col.autoFill?.type === "numbering" && col.autoFill.numberingRuleId) {
                // 채번 규칙: 즉시 API 호출
                row[col.key] = await generateNumberingCode(col.autoFill.numberingRuleId);
              } else if (autoValue !== undefined) {
                row[col.key] = autoValue;
              } else if (row[col.key] === undefined) {
                // 입력 컬럼: 빈 값으로 초기화
                row[col.key] = "";
              }
            }
          }

          return row;
        })
      );

      const newData = [...data, ...newRows];
      handleDataChange(newData);
      setModalOpen(false);
    },
    [config.dataSource?.foreignKey, resolvedReferenceKey, config.columns, data, handleDataChange, generateAutoFillValueSync, generateNumberingCode],
  );

  // 소스 컬럼 목록 (모달용) - 🆕 columns 배열에서 isSourceDisplay인 것만 필터링
  const sourceColumns = useMemo(() => {
    return config.columns
      .filter((col) => col.isSourceDisplay && col.visible !== false)
      .map((col) => col.key)
      .filter((key) => key && key !== "none");
  }, [config.columns]);

  // 🆕 beforeFormSave 이벤트에서 채번 placeholder를 실제 값으로 변환
  const dataRef = useRef(data);
  dataRef.current = data;
  
  useEffect(() => {
    const handleBeforeFormSave = async (event: Event) => {
      const customEvent = event as CustomEvent;
      const formData = customEvent.detail?.formData;
      
      if (!formData || !dataRef.current.length) return;
      
      // 채번 placeholder가 있는 행들을 찾아서 실제 값으로 변환
      const processedData = await Promise.all(
        dataRef.current.map(async (row) => {
          const newRow = { ...row };
          
          for (const key of Object.keys(newRow)) {
            const value = newRow[key];
            if (typeof value === "string" && value.startsWith("__NUMBERING_RULE__")) {
              // __NUMBERING_RULE__ruleId__ 형식에서 ruleId 추출
              const match = value.match(/__NUMBERING_RULE__(.+)__/);
              if (match) {
                const ruleId = match[1];
                try {
                  const result = await allocateNumberingCode(ruleId);
                  if (result.success && result.data?.generatedCode) {
                    newRow[key] = result.data.generatedCode;
                  } else {
                    console.error("채번 실패:", result.error);
                    newRow[key] = ""; // 채번 실패 시 빈 값
                  }
                } catch (error) {
                  console.error("채번 API 호출 실패:", error);
                  newRow[key] = "";
                }
              }
            }
          }
          
          return newRow;
        }),
      );
      
      // 처리된 데이터를 formData에 추가
      const fieldName = config.fieldName || "repeaterData";
      formData[fieldName] = processedData;
    };
    
    window.addEventListener("beforeFormSave", handleBeforeFormSave);
    
    return () => {
      window.removeEventListener("beforeFormSave", handleBeforeFormSave);
    };
  }, [config.fieldName]);

  return (
    <div className={cn("space-y-4", className)}>
      {/* 헤더 영역 */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <span className="text-muted-foreground text-sm">
            {data.length > 0 && `${data.length}개 항목`}
            {selectedRows.size > 0 && ` (${selectedRows.size}개 선택됨)`}
          </span>
        </div>
        <div className="flex gap-2">
          {selectedRows.size > 0 && (
            <Button variant="destructive" onClick={handleBulkDelete} className="h-8 text-xs sm:h-10 sm:text-sm">
              선택 삭제 ({selectedRows.size})
            </Button>
          )}
          <Button onClick={handleAddRow} className="h-8 text-xs sm:h-10 sm:text-sm">
            <Plus className="mr-2 h-4 w-4" />
            {isModalMode ? config.modal?.buttonText || "검색" : "추가"}
          </Button>
        </div>
      </div>

      {/* Repeater 테이블 */}
      <RepeaterTable
        columns={repeaterColumns}
        data={data}
        onDataChange={handleDataChange}
        onRowChange={handleRowChange}
        onRowDelete={handleRowDelete}
        activeDataSources={activeDataSources}
        onDataSourceChange={(field, optionId) => {
          setActiveDataSources((prev) => ({ ...prev, [field]: optionId }));
        }}
        selectedRows={selectedRows}
        onSelectionChange={setSelectedRows}
        equalizeWidthsTrigger={autoWidthTrigger}
        categoryColumns={sourceCategoryColumns}
        categoryLabelMap={categoryLabelMap}
      />

      {/* 항목 선택 모달 (modal 모드) - 검색 필드는 표시 컬럼과 동일하게 자동 설정 */}
      {isModalMode && (
        <ItemSelectionModal
          open={modalOpen}
          onOpenChange={setModalOpen}
          sourceTable={resolvedSourceTable}
          sourceColumns={sourceColumns}
          sourceSearchFields={sourceColumns}
          multiSelect={config.features?.multiSelect ?? true}
          modalTitle={config.modal?.title || "항목 검색"}
          alreadySelected={data}
          uniqueField={resolvedReferenceKey}
          onSelect={handleSelectItems}
          columnLabels={sourceColumnLabels}
          categoryColumns={sourceCategoryColumns}
        />
      )}
    </div>
  );
};

UnifiedRepeater.displayName = "UnifiedRepeater";

export default UnifiedRepeater;
