"use client";

/**
 * UPDATE 액션 노드 속성 편집 (개선 버전)
 */

import { useEffect, useState } from "react";
import { Plus, Trash2, Check, ChevronsUpDown, ArrowRight, Database, Globe, Link2 } from "lucide-react";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Checkbox } from "@/components/ui/checkbox";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { cn } from "@/lib/utils";
import { useFlowEditorStore } from "@/lib/stores/flowEditorStore";
import { tableTypeApi } from "@/lib/api/screen";
import { getTestedExternalConnections, getExternalTables, getExternalColumns } from "@/lib/api/nodeExternalConnections";
import type { UpdateActionNodeData } from "@/types/node-editor";
import type { ExternalConnection, ExternalTable, ExternalColumn } from "@/lib/api/nodeExternalConnections";

interface UpdateActionPropertiesProps {
  nodeId: string;
  data: UpdateActionNodeData;
}

interface TableOption {
  tableName: string;
  displayName: string;
  description: string;
  label: string;
}

interface ColumnInfo {
  columnName: string;
  columnLabel?: string;
  dataType: string;
  isNullable: boolean;
}

const OPERATORS = [
  { value: "EQUALS", label: "=" },
  { value: "NOT_EQUALS", label: "≠" },
  { value: "GREATER_THAN", label: ">" },
  { value: "LESS_THAN", label: "<" },
  { value: "GREATER_THAN_OR_EQUAL", label: "≥" },
  { value: "LESS_THAN_OR_EQUAL", label: "≤" },
  { value: "LIKE", label: "LIKE" },
  { value: "NOT_LIKE", label: "NOT LIKE" },
  { value: "IN", label: "IN" },
  { value: "NOT_IN", label: "NOT IN" },
  { value: "IS_NULL", label: "IS NULL" },
  { value: "IS_NOT_NULL", label: "IS NOT NULL" },
] as const;

export function UpdateActionProperties({ nodeId, data }: UpdateActionPropertiesProps) {
  const { updateNode, nodes, edges, getExternalConnectionsCache } = useFlowEditorStore();

  // 🔥 타겟 타입 상태
  const [targetType, setTargetType] = useState<"internal" | "external" | "api">(data.targetType || "internal");

  const [displayName, setDisplayName] = useState(data.displayName || data.targetTable);
  const [targetTable, setTargetTable] = useState(data.targetTable);
  const [fieldMappings, setFieldMappings] = useState(data.fieldMappings || []);
  const [whereConditions, setWhereConditions] = useState(data.whereConditions || []);
  const [batchSize, setBatchSize] = useState(data.options?.batchSize?.toString() || "");
  const [ignoreErrors, setIgnoreErrors] = useState(data.options?.ignoreErrors || false);

  // 내부 DB 테이블 관련 상태
  const [tables, setTables] = useState<TableOption[]>([]);
  const [tablesLoading, setTablesLoading] = useState(false);
  const [tablesOpen, setTablesOpen] = useState(false);

  // 컬럼 관련 상태
  const [targetColumns, setTargetColumns] = useState<ColumnInfo[]>([]);
  const [columnsLoading, setColumnsLoading] = useState(false);

  // 소스 필드 목록 (연결된 입력 노드에서 가져오기)
  const [sourceFields, setSourceFields] = useState<Array<{ name: string; label?: string }>>([]);
  // REST API 소스 노드 연결 여부
  const [hasRestAPISource, setHasRestAPISource] = useState(false);

  // 🔥 외부 DB 관련 상태
  const [externalConnections, setExternalConnections] = useState<ExternalConnection[]>([]);
  const [externalConnectionsLoading, setExternalConnectionsLoading] = useState(false);
  const [selectedExternalConnectionId, setSelectedExternalConnectionId] = useState<number | undefined>(
    data.externalConnectionId,
  );
  const [externalTables, setExternalTables] = useState<ExternalTable[]>([]);
  const [externalTablesLoading, setExternalTablesLoading] = useState(false);
  const [externalTargetTable, setExternalTargetTable] = useState(data.externalTargetTable);
  const [externalColumns, setExternalColumns] = useState<ExternalColumn[]>([]);
  const [externalColumnsLoading, setExternalColumnsLoading] = useState(false);

  // 🔥 REST API 관련 상태
  const [apiEndpoint, setApiEndpoint] = useState(data.apiEndpoint || "");
  const [apiMethod, setApiMethod] = useState<"PUT" | "PATCH">(data.apiMethod || "PUT");
  const [apiAuthType, setApiAuthType] = useState<"none" | "basic" | "bearer" | "apikey">(data.apiAuthType || "none");
  const [apiAuthConfig, setApiAuthConfig] = useState(data.apiAuthConfig || {});
  const [apiHeaders, setApiHeaders] = useState<Record<string, string>>(data.apiHeaders || {});
  const [apiBodyTemplate, setApiBodyTemplate] = useState(data.apiBodyTemplate || "");

  // 데이터 변경 시 로컬 상태 업데이트
  useEffect(() => {
    setDisplayName(data.displayName || data.targetTable);
    setTargetTable(data.targetTable);
    setFieldMappings(data.fieldMappings || []);
    setWhereConditions(data.whereConditions || []);
    setBatchSize(data.options?.batchSize?.toString() || "");
    setIgnoreErrors(data.options?.ignoreErrors || false);
  }, [data]);

  // 내부 DB 테이블 목록 로딩
  useEffect(() => {
    if (targetType === "internal") {
      loadTables();
    }
  }, [targetType]);

  // 타겟 테이블 변경 시 컬럼 로딩 (내부 DB)
  useEffect(() => {
    if (targetType === "internal" && targetTable) {
      loadColumns(targetTable);
    }
  }, [targetType, targetTable]);

  // 🔥 외부 DB: 커넥션 목록 로딩
  useEffect(() => {
    if (targetType === "external") {
      loadExternalConnections();
    }
  }, [targetType]);

  // 🔥 외부 DB: 테이블 목록 로딩
  useEffect(() => {
    if (targetType === "external" && selectedExternalConnectionId) {
      loadExternalTables(selectedExternalConnectionId);
    }
  }, [targetType, selectedExternalConnectionId]);

  // 🔥 외부 DB: 컬럼 목록 로딩
  useEffect(() => {
    if (targetType === "external" && selectedExternalConnectionId && externalTargetTable) {
      loadExternalColumns(selectedExternalConnectionId, externalTargetTable);
    }
  }, [targetType, selectedExternalConnectionId, externalTargetTable]);

  // 연결된 소스 노드에서 필드 가져오기 (재귀적으로 모든 상위 노드 탐색)
  useEffect(() => {
    const getAllSourceFields = (
      targetNodeId: string,
      visitedNodes = new Set<string>(),
    ): { fields: Array<{ name: string; label?: string }>; hasRestAPI: boolean } => {
      if (visitedNodes.has(targetNodeId)) {
        return { fields: [], hasRestAPI: false };
      }
      visitedNodes.add(targetNodeId);

      const inputEdges = edges.filter((edge) => edge.target === targetNodeId);
      const sourceNodeIds = inputEdges.map((edge) => edge.source);
      const sourceNodes = nodes.filter((node) => sourceNodeIds.includes(node.id));

      const fields: Array<{ name: string; label?: string }> = [];
      let foundRestAPI = false;

      sourceNodes.forEach((node) => {
        // 1️⃣ 데이터 변환 노드: 변환된 필드 + 상위 노드의 원본 필드
        if (node.type === "dataTransform") {
          const upperResult = getAllSourceFields(node.id, visitedNodes);
          const upperFields = upperResult.fields;
          foundRestAPI = foundRestAPI || upperResult.hasRestAPI;

          if ((node.data as any).transformations && Array.isArray((node.data as any).transformations)) {
            const inPlaceFields = new Set<string>();

            (node.data as any).transformations.forEach((transform: any) => {
              const targetField = transform.targetField || transform.sourceField;
              const isInPlace = !transform.targetField || transform.targetField === transform.sourceField;

              if (isInPlace) {
                inPlaceFields.add(transform.sourceField);
              } else if (targetField) {
                fields.push({
                  name: targetField,
                  label: transform.targetFieldLabel || targetField,
                });
              }
            });

            upperFields.forEach((field) => {
              fields.push(field);
            });
          } else {
            fields.push(...upperFields);
          }
        }
        // 2️⃣ REST API 소스 노드
        else if (node.type === "restAPISource") {
          foundRestAPI = true;
          const responseFields = (node.data as any).responseFields;
          if (responseFields && Array.isArray(responseFields)) {
            responseFields.forEach((field: any) => {
              const fieldName = field.name || field.fieldName;
              const fieldLabel = field.label || field.displayName;
              if (fieldName) {
                fields.push({
                  name: fieldName,
                  label: fieldLabel,
                });
              }
            });
          }
        }
        // 3️⃣ 테이블/외부DB 소스 노드
        else if (node.type === "tableSource" || node.type === "externalDBSource") {
          const nodeFields = (node.data as any).fields || (node.data as any).outputFields;

          if (nodeFields && Array.isArray(nodeFields)) {
            nodeFields.forEach((field: any) => {
              const fieldName = field.name || field.fieldName || field.column_name;
              const fieldLabel = field.label || field.displayName || field.label_ko;
              if (fieldName) {
                fields.push({
                  name: fieldName,
                  label: fieldLabel,
                });
              }
            });
          } else {
            // 필드가 없으면 상위 노드로 계속 탐색
            const upperResult = getAllSourceFields(node.id, visitedNodes);
            fields.push(...upperResult.fields);
            foundRestAPI = foundRestAPI || upperResult.hasRestAPI;
          }
        }
        // 4️⃣ 통과 노드 (조건, 기타 모든 노드): 상위 노드로 계속 탐색
        else {
          const upperResult = getAllSourceFields(node.id, visitedNodes);
          fields.push(...upperResult.fields);
          foundRestAPI = foundRestAPI || upperResult.hasRestAPI;
        }
      });

      return { fields, hasRestAPI: foundRestAPI };
    };

    const result = getAllSourceFields(nodeId);

    // 중복 제거
    const uniqueFields = Array.from(new Map(result.fields.map((field) => [field.name, field])).values());

    setSourceFields(uniqueFields);
    setHasRestAPISource(result.hasRestAPI);
  }, [nodeId, nodes, edges]);

  const loadTables = async () => {
    try {
      setTablesLoading(true);
      const tableList = await tableTypeApi.getTables();
      console.log("🔍 UPDATE 노드 - 테이블 목록:", tableList);

      const options: TableOption[] = tableList.map((table) => {
        const label = (table as any).tableLabel || table.displayName || table.tableName || "알 수 없는 테이블";

        return {
          tableName: table.tableName,
          displayName: table.displayName || table.tableName,
          description: table.description || "",
          label,
        };
      });

      console.log("✅ UPDATE 노드 - 테이블 옵션:", options);
      setTables(options);
    } catch (error) {
      console.error("❌ UPDATE 노드 - 테이블 목록 로딩 실패:", error);
    } finally {
      setTablesLoading(false);
    }
  };

  // 🔥 외부 DB 커넥션 목록 로딩
  const loadExternalConnections = async () => {
    try {
      setExternalConnectionsLoading(true);

      // 캐시 확인
      const cached = getExternalConnectionsCache();
      if (cached) {
        setExternalConnections(cached);
        setExternalConnectionsLoading(false);
        return;
      }

      const connections = await getTestedExternalConnections();
      setExternalConnections(connections);
    } catch (error) {
      console.error("외부 커넥션 목록 로딩 실패:", error);
    } finally {
      setExternalConnectionsLoading(false);
    }
  };

  // 🔥 외부 DB 테이블 목록 로딩
  const loadExternalTables = async (connectionId: number) => {
    try {
      setExternalTablesLoading(true);
      const tables = await getExternalTables(connectionId);
      setExternalTables(tables);
    } catch (error) {
      console.error("외부 테이블 목록 로딩 실패:", error);
    } finally {
      setExternalTablesLoading(false);
    }
  };

  // 🔥 외부 DB 컬럼 목록 로딩
  const loadExternalColumns = async (connectionId: number, tableName: string) => {
    try {
      setExternalColumnsLoading(true);
      const columns = await getExternalColumns(connectionId, tableName);
      setExternalColumns(columns);
    } catch (error) {
      console.error("외부 컬럼 목록 로딩 실패:", error);
    } finally {
      setExternalColumnsLoading(false);
    }
  };

  const loadColumns = async (tableName: string) => {
    try {
      setColumnsLoading(true);
      console.log(`🔍 UPDATE 노드 - 컬럼 조회 중: ${tableName}`);

      const columns = await tableTypeApi.getColumns(tableName);

      const columnInfo: ColumnInfo[] = columns.map((col: any) => ({
        columnName: col.column_name || col.columnName,
        columnLabel: col.label_ko || col.columnLabel,
        dataType: col.data_type || col.dataType || "unknown",
        isNullable: col.is_nullable === "YES" || col.isNullable === true,
      }));

      setTargetColumns(columnInfo);
      console.log(`✅ UPDATE 노드 - 컬럼 ${columnInfo.length}개 로딩 완료`);
    } catch (error) {
      console.error("❌ UPDATE 노드 - 컬럼 목록 로딩 실패:", error);
      setTargetColumns([]);
    } finally {
      setColumnsLoading(false);
    }
  };

  const handleTableSelect = async (newTableName: string) => {
    const selectedTable = tables.find((t) => t.tableName === newTableName);
    const newDisplayName = selectedTable?.label || selectedTable?.displayName || newTableName;

    setTargetTable(newTableName);
    setDisplayName(newDisplayName);

    await loadColumns(newTableName);

    // 즉시 반영
    updateNode(nodeId, {
      displayName: newDisplayName,
      targetTable: newTableName,
      fieldMappings,
      whereConditions,
      options: {
        batchSize: batchSize ? parseInt(batchSize) : undefined,
        ignoreErrors,
      },
    });

    setTablesOpen(false);
  };

  const handleAddMapping = () => {
    const newMappings = [
      ...fieldMappings,
      {
        sourceField: null,
        targetField: "",
        staticValue: undefined,
      },
    ];
    setFieldMappings(newMappings);
    updateNode(nodeId, { fieldMappings: newMappings });
  };

  const handleRemoveMapping = (index: number) => {
    const newMappings = fieldMappings.filter((_, i) => i !== index);
    setFieldMappings(newMappings);
    updateNode(nodeId, { fieldMappings: newMappings });
  };

  const handleMappingChange = (index: number, field: string, value: any) => {
    const newMappings = [...fieldMappings];

    // 필드 변경 시 라벨도 함께 저장
    if (field === "sourceField") {
      const sourceField = sourceFields.find((f) => f.name === value);
      newMappings[index] = {
        ...newMappings[index],
        sourceField: value,
        sourceFieldLabel: sourceField?.label,
      };
    } else if (field === "targetField") {
      const targetColumn = targetColumns.find((c) => c.columnName === value);
      newMappings[index] = {
        ...newMappings[index],
        targetField: value,
        targetFieldLabel: targetColumn?.columnLabel,
      };
    } else {
      newMappings[index] = { ...newMappings[index], [field]: value };
    }

    setFieldMappings(newMappings);
    updateNode(nodeId, { fieldMappings: newMappings });
  };

  // 🔥 타겟 타입 변경 핸들러
  const handleTargetTypeChange = (newType: "internal" | "external" | "api") => {
    setTargetType(newType);
    updateNode(nodeId, {
      targetType: newType,
      ...(newType === "internal" && {
        targetTable: data.targetTable,
        targetConnection: data.targetConnection,
        displayName: data.displayName,
      }),
      ...(newType === "external" && {
        externalConnectionId: data.externalConnectionId,
        externalConnectionName: data.externalConnectionName,
        externalDbType: data.externalDbType,
        externalTargetTable: data.externalTargetTable,
        externalTargetSchema: data.externalTargetSchema,
      }),
      ...(newType === "api" && {
        apiEndpoint: data.apiEndpoint,
        apiMethod: data.apiMethod,
        apiAuthType: data.apiAuthType,
        apiAuthConfig: data.apiAuthConfig,
        apiHeaders: data.apiHeaders,
        apiBodyTemplate: data.apiBodyTemplate,
      }),
    });
  };

  const handleAddCondition = () => {
    const newConditions = [
      ...whereConditions,
      {
        field: "",
        operator: "EQUALS",
        staticValue: "",
      },
    ];
    setWhereConditions(newConditions);
    updateNode(nodeId, { whereConditions: newConditions });
  };

  const handleRemoveCondition = (index: number) => {
    const newConditions = whereConditions.filter((_, i) => i !== index);
    setWhereConditions(newConditions);
    updateNode(nodeId, { whereConditions: newConditions });
  };

  const handleConditionChange = (index: number, field: string, value: any) => {
    const newConditions = [...whereConditions];

    // 필드 변경 시 라벨도 함께 저장
    if (field === "field") {
      const targetColumn = targetColumns.find((c) => c.columnName === value);
      newConditions[index] = {
        ...newConditions[index],
        field: value,
        fieldLabel: targetColumn?.columnLabel,
      };
    } else if (field === "sourceField") {
      const sourceField = sourceFields.find((f) => f.name === value);
      newConditions[index] = {
        ...newConditions[index],
        sourceField: value,
        sourceFieldLabel: sourceField?.label,
      };
    } else {
      newConditions[index] = { ...newConditions[index], [field]: value };
    }

    setWhereConditions(newConditions);
    updateNode(nodeId, { whereConditions: newConditions });
  };

  // 즉시 반영 핸들러들
  const handleDisplayNameChange = (newDisplayName: string) => {
    setDisplayName(newDisplayName);
    updateNode(nodeId, { displayName: newDisplayName });
  };

  const handleFieldMappingsChange = (newMappings: any[]) => {
    setFieldMappings(newMappings);
    updateNode(nodeId, { fieldMappings: newMappings });
  };

  const handleWhereConditionsChange = (newConditions: any[]) => {
    setWhereConditions(newConditions);
    updateNode(nodeId, { whereConditions: newConditions });
  };

  const handleBatchSizeChange = (newBatchSize: string) => {
    setBatchSize(newBatchSize);
    updateNode(nodeId, {
      options: {
        batchSize: newBatchSize ? parseInt(newBatchSize) : undefined,
        ignoreErrors,
      },
    });
  };

  const handleIgnoreErrorsChange = (checked: boolean) => {
    setIgnoreErrors(checked);
    updateNode(nodeId, {
      options: {
        batchSize: batchSize ? parseInt(batchSize) : undefined,
        ignoreErrors: checked,
      },
    });
  };

  const selectedTableLabel = tables.find((t) => t.tableName === targetTable)?.label || targetTable;

  return (
    <ScrollArea className="h-full">
      <div className="space-y-4 p-4 pb-8">
        {/* 기본 정보 */}
        <div>
          <h3 className="mb-3 text-sm font-semibold">기본 정보</h3>

          <div className="space-y-3">
            <div>
              <Label htmlFor="displayName" className="text-xs">
                표시 이름
              </Label>
              <Input
                id="displayName"
                value={displayName}
                onChange={(e) => setDisplayName(e.target.value)}
                className="mt-1"
                placeholder="노드 표시 이름"
              />
            </div>

            {/* 🔥 타겟 타입 선택 */}
            <div>
              <Label className="mb-2 block text-xs font-medium">타겟 선택</Label>
              <div className="grid grid-cols-3 gap-2">
                {/* 내부 데이터베이스 */}
                <button
                  onClick={() => handleTargetTypeChange("internal")}
                  className={cn(
                    "relative flex flex-col items-center gap-2 rounded-lg border-2 p-3 transition-all",
                    targetType === "internal" ? "border-blue-500 bg-blue-50" : "border-gray-200 hover:border-gray-300",
                  )}
                >
                  <Database className={cn("h-5 w-5", targetType === "internal" ? "text-blue-600" : "text-gray-400")} />
                  <span
                    className={cn("text-xs font-medium", targetType === "internal" ? "text-blue-700" : "text-gray-600")}
                  >
                    내부 DB
                  </span>
                  {targetType === "internal" && <Check className="absolute top-2 right-2 h-4 w-4 text-blue-600" />}
                </button>

                {/* 외부 데이터베이스 */}
                <button
                  onClick={() => handleTargetTypeChange("external")}
                  className={cn(
                    "relative flex flex-col items-center gap-2 rounded-lg border-2 p-3 transition-all",
                    targetType === "external"
                      ? "border-green-500 bg-green-50"
                      : "border-gray-200 hover:border-gray-300",
                  )}
                >
                  <Globe className={cn("h-5 w-5", targetType === "external" ? "text-green-600" : "text-gray-400")} />
                  <span
                    className={cn(
                      "text-xs font-medium",
                      targetType === "external" ? "text-green-700" : "text-gray-600",
                    )}
                  >
                    외부 DB
                  </span>
                  {targetType === "external" && <Check className="absolute top-2 right-2 h-4 w-4 text-green-600" />}
                </button>

                {/* REST API */}
                <button
                  onClick={() => handleTargetTypeChange("api")}
                  className={cn(
                    "relative flex flex-col items-center gap-2 rounded-lg border-2 p-3 transition-all",
                    targetType === "api" ? "border-purple-500 bg-purple-50" : "border-gray-200 hover:border-gray-300",
                  )}
                >
                  <Link2 className={cn("h-5 w-5", targetType === "api" ? "text-purple-600" : "text-gray-400")} />
                  <span
                    className={cn("text-xs font-medium", targetType === "api" ? "text-purple-700" : "text-gray-600")}
                  >
                    REST API
                  </span>
                  {targetType === "api" && <Check className="absolute top-2 right-2 h-4 w-4 text-purple-600" />}
                </button>
              </div>
            </div>

            {/* 내부 DB: 타겟 테이블 Combobox */}
            {targetType === "internal" && (
              <div>
                <Label className="text-xs">타겟 테이블</Label>
                <Popover open={tablesOpen} onOpenChange={setTablesOpen}>
                  <PopoverTrigger asChild>
                    <Button
                      variant="outline"
                      role="combobox"
                      aria-expanded={tablesOpen}
                      className="mt-1 w-full justify-between"
                      disabled={tablesLoading}
                    >
                      {tablesLoading ? (
                        <span className="text-muted-foreground">로딩 중...</span>
                      ) : targetTable ? (
                        <span className="truncate">{selectedTableLabel}</span>
                      ) : (
                        <span className="text-muted-foreground">테이블을 선택하세요</span>
                      )}
                      <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
                    </Button>
                  </PopoverTrigger>
                  <PopoverContent className="w-[320px] p-0" align="start">
                    <Command>
                      <CommandInput placeholder="테이블 검색..." />
                      <CommandEmpty>테이블을 찾을 수 없습니다.</CommandEmpty>
                      <CommandList>
                        <CommandGroup>
                          {tables.map((table) => (
                            <CommandItem
                              key={table.tableName}
                              value={`${table.label} ${table.displayName} ${table.tableName}`}
                              onSelect={() => handleTableSelect(table.tableName)}
                            >
                              <Check
                                className={cn(
                                  "mr-2 h-4 w-4",
                                  targetTable === table.tableName ? "opacity-100" : "opacity-0",
                                )}
                              />
                              <div className="flex flex-col">
                                <span className="font-medium">{table.label || table.displayName}</span>
                                <span className="text-muted-foreground text-xs">{table.tableName}</span>
                              </div>
                            </CommandItem>
                          ))}
                        </CommandGroup>
                      </CommandList>
                    </Command>
                  </PopoverContent>
                </Popover>
              </div>
            )}

            {/* 🔥 외부 DB 설정 (INSERT 노드와 동일 패턴) */}
            {targetType === "external" && (
              <>
                {/* 외부 커넥션 선택 */}
                <div>
                  <Label className="mb-1.5 block text-xs font-medium">외부 데이터베이스 커넥션</Label>
                  <Select
                    value={selectedExternalConnectionId?.toString()}
                    onValueChange={(value) => {
                      const connectionId = parseInt(value);
                      const selectedConnection = externalConnections.find((c) => c.id === connectionId);
                      setSelectedExternalConnectionId(connectionId);
                      setExternalTargetTable("");
                      setExternalColumns([]);
                      updateNode(nodeId, {
                        externalConnectionId: connectionId,
                        externalConnectionName: selectedConnection?.name,
                        externalDbType: selectedConnection?.db_type,
                      });
                    }}
                  >
                    <SelectTrigger className="h-8 text-xs">
                      <SelectValue placeholder="커넥션을 선택하세요" />
                    </SelectTrigger>
                    <SelectContent>
                      {externalConnectionsLoading ? (
                        <div className="p-2 text-center text-xs text-gray-500">로딩 중...</div>
                      ) : externalConnections.length === 0 ? (
                        <div className="p-2 text-center text-xs text-gray-500">사용 가능한 커넥션이 없습니다</div>
                      ) : (
                        externalConnections.map((conn) => (
                          <SelectItem key={conn.id} value={conn.id!.toString()}>
                            <div className="flex items-center gap-2">
                              <span className="font-medium">{conn.db_type}</span>
                              <span className="text-gray-500">-</span>
                              <span>{conn.name}</span>
                            </div>
                          </SelectItem>
                        ))
                      )}
                    </SelectContent>
                  </Select>
                </div>

                {/* 외부 테이블 선택 */}
                {selectedExternalConnectionId && (
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium">테이블</Label>
                    <Select
                      value={externalTargetTable}
                      onValueChange={(value) => {
                        const selectedTable = externalTables.find((t) => t.table_name === value);
                        setExternalTargetTable(value);
                        updateNode(nodeId, {
                          externalTargetTable: value,
                          externalTargetSchema: selectedTable?.schema,
                        });
                      }}
                    >
                      <SelectTrigger className="h-8 text-xs">
                        <SelectValue placeholder="테이블을 선택하세요" />
                      </SelectTrigger>
                      <SelectContent>
                        {externalTablesLoading ? (
                          <div className="p-2 text-center text-xs text-gray-500">로딩 중...</div>
                        ) : externalTables.length === 0 ? (
                          <div className="p-2 text-center text-xs text-gray-500">테이블이 없습니다</div>
                        ) : (
                          externalTables.map((table) => (
                            <SelectItem key={table.table_name} value={table.table_name}>
                              <div className="flex items-center gap-2">
                                <span className="font-medium">{table.table_name}</span>
                                {table.schema && <span className="text-xs text-gray-500">({table.schema})</span>}
                              </div>
                            </SelectItem>
                          ))
                        )}
                      </SelectContent>
                    </Select>
                  </div>
                )}

                {/* 외부 컬럼 표시 */}
                {externalTargetTable && externalColumns.length > 0 && (
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium">컬럼 목록</Label>
                    <div className="max-h-32 space-y-1 overflow-y-auto rounded border bg-gray-50 p-2">
                      {externalColumns.map((col) => (
                        <div key={col.column_name} className="flex items-center justify-between text-xs">
                          <span className="font-medium">{col.column_name}</span>
                          <span className="text-gray-500">{col.data_type}</span>
                        </div>
                      ))}
                    </div>
                  </div>
                )}
              </>
            )}

            {/* 🔥 REST API 설정 */}
            {targetType === "api" && (
              <div className="space-y-4">
                {/* API 엔드포인트 */}
                <div>
                  <Label className="mb-1.5 block text-xs font-medium">API 엔드포인트</Label>
                  <Input
                    placeholder="https://api.example.com/v1/users/{id}"
                    value={apiEndpoint}
                    onChange={(e) => {
                      setApiEndpoint(e.target.value);
                      updateNode(nodeId, { apiEndpoint: e.target.value });
                    }}
                    className="h-8 text-xs"
                  />
                </div>

                {/* HTTP 메서드 */}
                <div>
                  <Label className="mb-1.5 block text-xs font-medium">HTTP 메서드</Label>
                  <Select
                    value={apiMethod}
                    onValueChange={(value: "PUT" | "PATCH") => {
                      setApiMethod(value);
                      updateNode(nodeId, { apiMethod: value });
                    }}
                  >
                    <SelectTrigger className="h-8 text-xs">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="PUT">PUT</SelectItem>
                      <SelectItem value="PATCH">PATCH</SelectItem>
                    </SelectContent>
                  </Select>
                </div>

                {/* 인증 타입 */}
                <div>
                  <Label className="mb-1.5 block text-xs font-medium">인증 방식</Label>
                  <Select
                    value={apiAuthType}
                    onValueChange={(value: "none" | "basic" | "bearer" | "apikey") => {
                      setApiAuthType(value);
                      updateNode(nodeId, { apiAuthType: value });
                    }}
                  >
                    <SelectTrigger className="h-8 text-xs">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="none">인증 없음</SelectItem>
                      <SelectItem value="bearer">Bearer Token</SelectItem>
                      <SelectItem value="basic">Basic Auth</SelectItem>
                      <SelectItem value="apikey">API Key</SelectItem>
                    </SelectContent>
                  </Select>
                </div>

                {/* 인증 설정 */}
                {apiAuthType !== "none" && (
                  <div className="space-y-2 rounded border bg-gray-50 p-3">
                    <Label className="block text-xs font-medium">인증 정보</Label>

                    {apiAuthType === "bearer" && (
                      <Input
                        placeholder="Bearer Token"
                        value={(apiAuthConfig as any)?.token || ""}
                        onChange={(e) => {
                          const newConfig = { token: e.target.value };
                          setApiAuthConfig(newConfig);
                          updateNode(nodeId, { apiAuthConfig: newConfig });
                        }}
                        className="h-8 text-xs"
                      />
                    )}

                    {apiAuthType === "basic" && (
                      <div className="space-y-2">
                        <Input
                          placeholder="사용자명"
                          value={(apiAuthConfig as any)?.username || ""}
                          onChange={(e) => {
                            const newConfig = { ...(apiAuthConfig as any), username: e.target.value };
                            setApiAuthConfig(newConfig);
                            updateNode(nodeId, { apiAuthConfig: newConfig });
                          }}
                          className="h-8 text-xs"
                        />
                        <Input
                          type="password"
                          placeholder="비밀번호"
                          value={(apiAuthConfig as any)?.password || ""}
                          onChange={(e) => {
                            const newConfig = { ...(apiAuthConfig as any), password: e.target.value };
                            setApiAuthConfig(newConfig);
                            updateNode(nodeId, { apiAuthConfig: newConfig });
                          }}
                          className="h-8 text-xs"
                        />
                      </div>
                    )}

                    {apiAuthType === "apikey" && (
                      <div className="space-y-2">
                        <Input
                          placeholder="헤더 이름 (예: X-API-Key)"
                          value={(apiAuthConfig as any)?.headerName || ""}
                          onChange={(e) => {
                            const newConfig = { ...(apiAuthConfig as any), headerName: e.target.value };
                            setApiAuthConfig(newConfig);
                            updateNode(nodeId, { apiAuthConfig: newConfig });
                          }}
                          className="h-8 text-xs"
                        />
                        <Input
                          placeholder="API Key"
                          value={(apiAuthConfig as any)?.apiKey || ""}
                          onChange={(e) => {
                            const newConfig = { ...(apiAuthConfig as any), apiKey: e.target.value };
                            setApiAuthConfig(newConfig);
                            updateNode(nodeId, { apiAuthConfig: newConfig });
                          }}
                          className="h-8 text-xs"
                        />
                      </div>
                    )}
                  </div>
                )}

                {/* 커스텀 헤더 */}
                <div>
                  <Label className="mb-1.5 block text-xs font-medium">커스텀 헤더 (선택사항)</Label>
                  <div className="space-y-2 rounded border bg-gray-50 p-3">
                    {Object.entries(apiHeaders).map(([key, value], index) => (
                      <div key={index} className="flex gap-2">
                        <Input
                          placeholder="헤더 이름"
                          value={key}
                          onChange={(e) => {
                            const newHeaders = { ...apiHeaders };
                            delete newHeaders[key];
                            newHeaders[e.target.value] = value;
                            setApiHeaders(newHeaders);
                            updateNode(nodeId, { apiHeaders: newHeaders });
                          }}
                          className="h-7 flex-1 text-xs"
                        />
                        <Input
                          placeholder="헤더 값"
                          value={value}
                          onChange={(e) => {
                            const newHeaders = { ...apiHeaders, [key]: e.target.value };
                            setApiHeaders(newHeaders);
                            updateNode(nodeId, { apiHeaders: newHeaders });
                          }}
                          className="h-7 flex-1 text-xs"
                        />
                        <Button
                          size="sm"
                          variant="ghost"
                          onClick={() => {
                            const newHeaders = { ...apiHeaders };
                            delete newHeaders[key];
                            setApiHeaders(newHeaders);
                            updateNode(nodeId, { apiHeaders: newHeaders });
                          }}
                          className="h-7 w-7 p-0"
                        >
                          <Trash2 className="h-3 w-3" />
                        </Button>
                      </div>
                    ))}
                    <Button
                      size="sm"
                      variant="outline"
                      onClick={() => {
                        const newHeaders = { ...apiHeaders, "": "" };
                        setApiHeaders(newHeaders);
                        updateNode(nodeId, { apiHeaders: newHeaders });
                      }}
                      className="h-7 w-full text-xs"
                    >
                      <Plus className="mr-1 h-3 w-3" />
                      헤더 추가
                    </Button>
                  </div>
                </div>

                {/* 요청 바디 설정 */}
                <div>
                  <Label className="mb-1.5 block text-xs font-medium">
                    요청 바디 템플릿
                    <span className="ml-1 text-gray-500">{`{{fieldName}}`}으로 소스 필드 참조</span>
                  </Label>
                  <textarea
                    placeholder={`{\n  "id": "{{id}}",\n  "name": "{{name}}",\n  "email": "{{email}}"\n}`}
                    value={apiBodyTemplate}
                    onChange={(e) => {
                      setApiBodyTemplate(e.target.value);
                      updateNode(nodeId, { apiBodyTemplate: e.target.value });
                    }}
                    className="w-full rounded border p-2 font-mono text-xs"
                    rows={8}
                  />
                  <p className="mt-1 text-xs text-gray-500">
                    소스 데이터의 필드명을 {`{{필드명}}`} 형태로 참조할 수 있습니다.
                  </p>
                </div>
              </div>
            )}
          </div>
        </div>

        {/* WHERE 조건 */}
        <div>
          <div className="mb-2 flex items-center justify-between">
            <h3 className="text-sm font-semibold">WHERE 조건</h3>
            <Button size="sm" variant="outline" onClick={handleAddCondition} className="h-7 px-2 text-xs">
              <Plus className="mr-1 h-3 w-3" />
              조건 추가
            </Button>
          </div>

          {!targetTable && !columnsLoading && (
            <div className="rounded border border-dashed bg-yellow-50 p-3 text-center text-xs text-yellow-700">
              ⚠️ 먼저 타겟 테이블을 선택하세요
            </div>
          )}

          {targetTable && whereConditions.length === 0 && (
            <div className="rounded border border-dashed bg-gray-50 p-3 text-center text-xs text-gray-500">
              WHERE 조건을 추가하세요
            </div>
          )}

          {targetTable && whereConditions.length > 0 && targetColumns.length > 0 && (
            <div className="space-y-3">
              {whereConditions.map((condition, index) => (
                <div key={index} className="rounded border bg-blue-50 p-3">
                  <div className="mb-2 flex items-center justify-between">
                    <span className="text-xs font-medium text-gray-700">조건 #{index + 1}</span>
                    <Button
                      size="sm"
                      variant="ghost"
                      onClick={() => handleRemoveCondition(index)}
                      className="h-6 w-6 p-0 text-red-600 hover:text-red-700"
                    >
                      <Trash2 className="h-3 w-3" />
                    </Button>
                  </div>

                  <div className="space-y-2">
                    {/* 타겟 필드 */}
                    <div>
                      <Label className="text-xs text-gray-600">타겟 필드</Label>
                      <Select
                        value={condition.field}
                        onValueChange={(value) => handleConditionChange(index, "field", value)}
                      >
                        <SelectTrigger className="mt-1 h-8 text-xs">
                          <SelectValue placeholder="필드 선택" />
                        </SelectTrigger>
                        <SelectContent>
                          {targetColumns.map((col) => (
                            <SelectItem key={col.columnName} value={col.columnName} className="text-xs">
                              <div className="flex items-center justify-between gap-2">
                                <span className="font-mono">{col.columnLabel || col.columnName}</span>
                                <span className="text-muted-foreground">{col.dataType}</span>
                              </div>
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </div>

                    {/* 연산자 */}
                    <div>
                      <Label className="text-xs text-gray-600">연산자</Label>
                      <Select
                        value={condition.operator}
                        onValueChange={(value) => handleConditionChange(index, "operator", value)}
                      >
                        <SelectTrigger className="mt-1 h-8 text-xs">
                          <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                          {OPERATORS.map((op) => (
                            <SelectItem key={op.value} value={op.value} className="text-xs">
                              {op.label}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </div>

                    {/* IS_NULL, IS_NOT_NULL이 아닐 때만 소스 필드와 정적 값 표시 */}
                    {condition.operator !== "IS_NULL" && condition.operator !== "IS_NOT_NULL" && (
                      <>
                        {/* 소스 필드 또는 값 */}
                        <div>
                          <Label className="text-xs text-gray-600">소스 필드 (선택)</Label>
                          <Select
                            value={condition.sourceField || "_NONE_"}
                            onValueChange={(value) =>
                              handleConditionChange(index, "sourceField", value === "_NONE_" ? undefined : value)
                            }
                          >
                            <SelectTrigger className="mt-1 h-8 text-xs">
                              <SelectValue placeholder="소스 필드 선택 (선택)" />
                            </SelectTrigger>
                            <SelectContent>
                              <SelectItem value="_NONE_" className="text-xs text-gray-400">
                                없음 (정적 값 사용)
                              </SelectItem>
                              {sourceFields.map((field) => (
                                <SelectItem key={field.name} value={field.name} className="text-xs">
                                  <div className="flex items-center justify-between gap-2">
                                    <span className="font-medium">{field.label || field.name}</span>
                                    {field.label && field.label !== field.name && (
                                      <span className="text-muted-foreground font-mono text-xs">{field.name}</span>
                                    )}
                                  </div>
                                </SelectItem>
                              ))}
                            </SelectContent>
                          </Select>
                        </div>

                        {/* 정적 값 */}
                        <div>
                          <Label className="text-xs text-gray-600">정적 값</Label>
                          <Input
                            value={condition.staticValue || ""}
                            onChange={(e) => handleConditionChange(index, "staticValue", e.target.value || undefined)}
                            placeholder="비교할 고정 값"
                            className="mt-1 h-8 text-xs"
                          />
                          <p className="mt-1 text-xs text-gray-400">소스 필드가 비어있을 때만 사용됩니다</p>
                        </div>
                      </>
                    )}

                    {/* IS_NULL, IS_NOT_NULL일 때 안내 메시지 */}
                    {(condition.operator === "IS_NULL" || condition.operator === "IS_NOT_NULL") && (
                      <div className="rounded bg-blue-50 p-3 text-xs text-blue-700">
                        ℹ️ {condition.operator === "IS_NULL" ? "IS NULL" : "IS NOT NULL"} 조건은 값 비교가 필요하지
                        않습니다.
                      </div>
                    )}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>

        {/* 필드 매핑 (REST API 타입에서는 숨김) */}
        {targetType !== "api" && (
          <div>
            <div className="mb-2 flex items-center justify-between">
              <h3 className="text-sm font-semibold">업데이트 필드</h3>
              <Button size="sm" variant="outline" onClick={handleAddMapping} className="h-7 px-2 text-xs">
                <Plus className="mr-1 h-3 w-3" />
                매핑 추가
              </Button>
            </div>

            {!targetTable && !columnsLoading && (
              <div className="rounded border border-dashed bg-yellow-50 p-3 text-center text-xs text-yellow-700">
                ⚠️ 먼저 타겟 테이블을 선택하세요
              </div>
            )}

            {targetTable && !columnsLoading && targetColumns.length === 0 && (
              <div className="rounded border border-dashed bg-red-50 p-3 text-center text-xs text-red-700">
                ❌ 컬럼 정보를 불러올 수 없습니다
              </div>
            )}

            {targetTable && targetColumns.length > 0 && (
              <>
                {fieldMappings.length > 0 ? (
                  <div className="space-y-3">
                    {fieldMappings.map((mapping, index) => (
                      <div key={index} className="rounded border bg-gray-50 p-3">
                        <div className="mb-2 flex items-center justify-between">
                          <span className="text-xs font-medium text-gray-700">매핑 #{index + 1}</span>
                          <Button
                            size="sm"
                            variant="ghost"
                            onClick={() => handleRemoveMapping(index)}
                            className="h-6 w-6 p-0 text-red-600 hover:text-red-700"
                          >
                            <Trash2 className="h-3 w-3" />
                          </Button>
                        </div>

                        <div className="space-y-2">
                          {/* 소스 필드 - REST API인 경우 입력, 아니면 드롭다운 */}
                          <div>
                            <Label className="text-xs text-gray-600">
                              소스 필드{hasRestAPISource && " (REST API - 직접 입력)"}
                            </Label>
                            {hasRestAPISource ? (
                              <Input
                                value={mapping.sourceField || ""}
                                onChange={(e) => handleMappingChange(index, "sourceField", e.target.value || null)}
                                placeholder="API 응답 JSON의 필드명을 입력하세요"
                                className="mt-1 h-8 text-xs"
                              />
                            ) : (
                              <Select
                                value={mapping.sourceField || ""}
                                onValueChange={(value) => handleMappingChange(index, "sourceField", value || null)}
                              >
                                <SelectTrigger className="mt-1 h-8 text-xs">
                                  <SelectValue placeholder="소스 필드 선택" />
                                </SelectTrigger>
                                <SelectContent>
                                  {sourceFields.length === 0 ? (
                                    <div className="p-2 text-center text-xs text-gray-400">
                                      연결된 소스 노드가 없습니다
                                    </div>
                                  ) : (
                                    sourceFields.map((field) => (
                                      <SelectItem key={field.name} value={field.name} className="text-xs">
                                        <div className="flex items-center justify-between gap-2">
                                          <span className="font-medium">{field.label || field.name}</span>
                                          {field.label && field.label !== field.name && (
                                            <span className="text-muted-foreground font-mono text-xs">
                                              {field.name}
                                            </span>
                                          )}
                                        </div>
                                      </SelectItem>
                                    ))
                                  )}
                                </SelectContent>
                              </Select>
                            )}
                          </div>

                          <div className="flex items-center justify-center py-1">
                            <ArrowRight className="h-4 w-4 text-blue-600" />
                          </div>

                          {/* 타겟 필드 드롭다운 */}
                          <div>
                            <Label className="text-xs text-gray-600">타겟 필드</Label>
                            <Select
                              value={mapping.targetField}
                              onValueChange={(value) => handleMappingChange(index, "targetField", value)}
                            >
                              <SelectTrigger className="mt-1 h-8 text-xs">
                                <SelectValue placeholder="타겟 필드 선택" />
                              </SelectTrigger>
                              <SelectContent>
                                {targetColumns.map((col) => (
                                  <SelectItem key={col.columnName} value={col.columnName} className="text-xs">
                                    <div className="flex items-center justify-between gap-2">
                                      <span className="font-mono">{col.columnLabel || col.columnName}</span>
                                      <span className="text-muted-foreground">
                                        {col.dataType}
                                        {!col.isNullable && <span className="text-red-500">*</span>}
                                      </span>
                                    </div>
                                  </SelectItem>
                                ))}
                              </SelectContent>
                            </Select>
                          </div>

                          {/* 정적 값 */}
                          <div>
                            <Label className="text-xs text-gray-600">정적 값 (선택)</Label>
                            <Input
                              value={mapping.staticValue || ""}
                              onChange={(e) => handleMappingChange(index, "staticValue", e.target.value || undefined)}
                              placeholder="소스 필드 대신 고정 값 사용"
                              className="mt-1 h-8 text-xs"
                            />
                            <p className="mt-1 text-xs text-gray-400">소스 필드가 비어있을 때만 사용됩니다</p>
                          </div>
                        </div>
                      </div>
                    ))}
                  </div>
                ) : (
                  <div className="rounded border border-dashed bg-gray-50 p-3 text-center text-xs text-gray-500">
                    업데이트할 필드를 추가하세요
                  </div>
                )}
              </>
            )}
          </div>
        )}

        {/* 옵션 */}
        <div>
          <h3 className="mb-3 text-sm font-semibold">옵션</h3>
          <div className="space-y-3">
            <div>
              <Label htmlFor="batchSize" className="text-xs">
                배치 크기
              </Label>
              <Input
                id="batchSize"
                type="number"
                value={batchSize}
                onChange={(e) => handleBatchSizeChange(e.target.value)}
                className="mt-1"
                placeholder="예: 100"
              />
            </div>

            <div className="flex items-center space-x-2">
              <Checkbox
                id="ignoreErrors"
                checked={ignoreErrors}
                onCheckedChange={(checked) => handleIgnoreErrorsChange(checked as boolean)}
              />
              <Label htmlFor="ignoreErrors" className="cursor-pointer text-xs font-normal">
                오류 무시
              </Label>
            </div>
          </div>
        </div>

      </div>
    </ScrollArea>
  );
}
