"use client";

import React, { useState, useEffect, useCallback } 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 { Label } from "@/components/ui/label";
import { Link } from "lucide-react";
import { DataFlowAPI, TableRelationship, TableInfo, ColumnInfo, ConditionNode } from "@/lib/api/dataflow";
import {
  ConnectionConfig,
  SimpleKeySettings,
  DataSaveSettings,
  ExternalCallSettings,
  SimpleExternalCallSettings,
  ConnectionSetupModalProps,
} from "@/types/connectionTypes";
import { isConditionalConnection } from "@/utils/connectionUtils";
import { useConditionManager } from "@/hooks/useConditionManager";
import { ConditionalSettings } from "./condition/ConditionalSettings";
import { ConnectionTypeSelector } from "./connection/ConnectionTypeSelector";
import { SimpleKeySettings as SimpleKeySettingsComponent } from "./connection/SimpleKeySettings";
import { DataSaveSettings as DataSaveSettingsComponent } from "./connection/DataSaveSettings";
import { SimpleExternalCallSettings as ExternalCallSettingsComponent } from "./connection/SimpleExternalCallSettings";
import toast from "react-hot-toast";

export const ConnectionSetupModal: React.FC<ConnectionSetupModalProps> = ({
  isOpen,
  connection,
  companyCode,
  onConfirm,
  onCancel,
}) => {
  const [config, setConfig] = useState<ConnectionConfig>({
    relationshipName: "",
    connectionType: "simple-key",
    fromColumnName: "",
    toColumnName: "",
    settings: {},
  });

  // 연결 종류별 설정 상태
  const [simpleKeySettings, setSimpleKeySettings] = useState<SimpleKeySettings>({
    notes: "",
  });

  const [dataSaveSettings, setDataSaveSettings] = useState<DataSaveSettings>({
    actions: [],
  });

  const [externalCallSettings, setExternalCallSettings] = useState<SimpleExternalCallSettings>({
    message: "",
  });

  // 테이블 및 컬럼 선택을 위한 상태들
  const [availableTables, setAvailableTables] = useState<TableInfo[]>([]);
  const [selectedFromTable, setSelectedFromTable] = useState<string>("");
  const [selectedToTable, setSelectedToTable] = useState<string>("");
  const [fromTableColumns, setFromTableColumns] = useState<ColumnInfo[]>([]);
  const [toTableColumns, setToTableColumns] = useState<ColumnInfo[]>([]);
  const [selectedFromColumns, setSelectedFromColumns] = useState<string[]>([]);
  const [selectedToColumns, setSelectedToColumns] = useState<string[]>([]);
  const [tableColumnsCache, setTableColumnsCache] = useState<{ [tableName: string]: ColumnInfo[] }>({});

  // 조건 관리 훅 사용
  const {
    conditions,
    setConditions,
    addCondition,
    addGroupStart,
    addGroupEnd,
    updateCondition,
    removeCondition,
    getCurrentGroupLevel,
  } = useConditionManager();

  // 기존 설정 로드 함수
  const loadExistingSettings = useCallback(
    (settings: Record<string, unknown>, connectionType: string) => {
      if (connectionType === "simple-key" && settings.notes) {
        setSimpleKeySettings({
          notes: settings.notes as string,
        });
      } else if (connectionType === "data-save") {
        // data-save 설정 로드 - 안전하게 처리 (다양한 구조 지원)
        let actionsData: Record<string, unknown>[] = [];
        const settingsRecord = settings as Record<string, unknown>;

        if (Array.isArray(settingsRecord.actions)) {
          // 직접 actions 배열이 있는 경우
          actionsData = settingsRecord.actions as Record<string, unknown>[];
        } else if (settingsRecord.plan && typeof settingsRecord.plan === "object" && settingsRecord.plan !== null) {
          // plan 객체 안에 actions가 있는 경우
          const planRecord = settingsRecord.plan as Record<string, unknown>;
          if (Array.isArray(planRecord.actions)) {
            actionsData = planRecord.actions as Record<string, unknown>[];
          }
        } else if (Array.isArray(settings)) {
          // settings 자체가 actions 배열인 경우
          actionsData = settings as Record<string, unknown>[];
        }
        setDataSaveSettings({
          actions: actionsData.map((action: Record<string, unknown>) => ({
            id: (action.id as string) || `action-${Date.now()}`,
            name: (action.name as string) || "새 액션",
            actionType: (action.actionType as "insert" | "update" | "delete" | "upsert") || "insert",
            conditions: Array.isArray(action.conditions)
              ? (action.conditions as ConditionNode[]).map((condition) => ({
                  ...condition,
                  operator: condition.operator || "=", // 기본값 보장
                }))
              : [],
            fieldMappings: Array.isArray(action.fieldMappings)
              ? action.fieldMappings.map((mapping: Record<string, unknown>) => ({
                  sourceTable: (mapping.sourceTable as string) || "",
                  sourceField: (mapping.sourceField as string) || "",
                  targetTable: (mapping.targetTable as string) || "",
                  targetField: (mapping.targetField as string) || "",
                  defaultValue: (mapping.defaultValue as string) || "",
                  transformFunction: (mapping.transformFunction as string) || "",
                }))
              : [],
            splitConfig: action.splitConfig
              ? {
                  sourceField: ((action.splitConfig as Record<string, unknown>).sourceField as string) || "",
                  delimiter: ((action.splitConfig as Record<string, unknown>).delimiter as string) || ",",
                  targetField: ((action.splitConfig as Record<string, unknown>).targetField as string) || "",
                }
              : undefined,
          })),
        });

        // control 설정도 로드 (전체 실행 조건)
        if (settingsRecord.control && typeof settingsRecord.control === "object" && settingsRecord.control !== null) {
          const controlRecord = settingsRecord.control as Record<string, unknown>;
          if (Array.isArray(controlRecord.conditionTree)) {
            const conditionTree = controlRecord.conditionTree as ConditionNode[];
            setConditions(
              conditionTree.map((condition) => ({
                ...condition,
                operator: condition.operator || "=", // 기본값 보장
              })),
            );
          }
        }
      } else if (connectionType === "external-call") {
        // 외부 호출 설정은 plan에서 로드
        const settingsRecord = settings as Record<string, unknown>;
        let externalCallData: Record<string, unknown> = {};

        if (settingsRecord.plan && typeof settingsRecord.plan === "object" && settingsRecord.plan !== null) {
          const planRecord = settingsRecord.plan as Record<string, unknown>;
          if (planRecord.externalCall && typeof planRecord.externalCall === "object") {
            externalCallData = planRecord.externalCall as Record<string, unknown>;
          }
        }

        setExternalCallSettings({
          configId: (externalCallData.configId as number) || undefined,
          configName: (externalCallData.configName as string) || undefined,
          message: (externalCallData.message as string) || "",
        });
      }
    },
    [setConditions, setSimpleKeySettings, setDataSaveSettings, setExternalCallSettings],
  );

  // 테이블 목록 로드
  useEffect(() => {
    const loadTables = async () => {
      try {
        const tables = await DataFlowAPI.getTables();
        setAvailableTables(tables);
      } catch (error) {
        console.error("테이블 목록 로드 실패:", error);
        toast.error("테이블 목록을 불러오는데 실패했습니다.");
      }
    };

    if (isOpen) {
      loadTables();
    }
  }, [isOpen]);

  // 모달이 열릴 때 기본값 설정
  useEffect(() => {
    if (isOpen && connection) {
      const fromTableName = connection.fromNode.tableName;
      const toTableName = connection.toNode.tableName;
      const fromDisplayName = connection.fromNode.displayName;
      const toDisplayName = connection.toNode.displayName;

      // 테이블 선택 설정
      setSelectedFromTable(fromTableName);
      setSelectedToTable(toTableName);

      // 기존 관계 정보가 있으면 사용, 없으면 기본값 설정
      const existingRel = connection.existingRelationship;
      const connectionType =
        (existingRel?.connectionType as "simple-key" | "data-save" | "external-call") || "simple-key";

      setConfig({
        relationshipName: existingRel?.relationshipName || `${fromDisplayName} → ${toDisplayName}`,
        connectionType,
        fromColumnName: "",
        toColumnName: "",
        settings: existingRel?.settings || {},
      });

      // 기존 설정 데이터 로드
      if (existingRel?.settings) {
        loadExistingSettings(existingRel.settings, connectionType);
      } else {
        // 기본값 설정
        setSimpleKeySettings({
          notes: existingRel?.note || `${fromDisplayName}과 ${toDisplayName} 간의 키값 연결`,
        });
        setDataSaveSettings({ actions: [] });
      }

      // 필드 선택 상태 초기화
      setSelectedFromColumns([]);
      setSelectedToColumns([]);

      // 선택된 컬럼 정보가 있다면 설정
      if (connection.selectedColumnsData) {
        const fromColumns = connection.selectedColumnsData[fromTableName]?.columns || [];
        const toColumns = connection.selectedColumnsData[toTableName]?.columns || [];

        setSelectedFromColumns(fromColumns);
        setSelectedToColumns(toColumns);

        setConfig((prev) => ({
          ...prev,
          fromColumnName: fromColumns.join(", "),
          toColumnName: toColumns.join(", "),
        }));
      }
    }
  }, [isOpen, connection, setConditions, loadExistingSettings]);

  // From 테이블 선택 시 컬럼 로드
  useEffect(() => {
    const loadFromColumns = async () => {
      if (selectedFromTable) {
        try {
          const columns = await DataFlowAPI.getTableColumns(selectedFromTable);
          setFromTableColumns(columns);
        } catch (error) {
          console.error("From 테이블 컬럼 로드 실패:", error);
          toast.error("From 테이블 컬럼을 불러오는데 실패했습니다.");
        }
      }
    };

    loadFromColumns();
  }, [selectedFromTable]);

  // To 테이블 선택 시 컬럼 로드
  useEffect(() => {
    const loadToColumns = async () => {
      if (selectedToTable) {
        try {
          const columns = await DataFlowAPI.getTableColumns(selectedToTable);
          setToTableColumns(columns);
        } catch (error) {
          console.error("To 테이블 컬럼 로드 실패:", error);
          toast.error("To 테이블 컬럼을 불러오는데 실패했습니다.");
        }
      }
    };

    loadToColumns();
  }, [selectedToTable]);

  // 선택된 컬럼들이 변경될 때 config 업데이트
  useEffect(() => {
    setConfig((prev) => ({
      ...prev,
      fromColumnName: selectedFromColumns.join(", "),
      toColumnName: selectedToColumns.join(", "),
    }));
  }, [selectedFromColumns, selectedToColumns]);

  // 테이블 컬럼 로드 함수 (캐시 활용)
  const loadTableColumns = async (tableName: string): Promise<ColumnInfo[]> => {
    if (tableColumnsCache[tableName]) {
      return tableColumnsCache[tableName];
    }

    try {
      const columns = await DataFlowAPI.getTableColumns(tableName);
      setTableColumnsCache((prev) => ({
        ...prev,
        [tableName]: columns,
      }));
      return columns;
    } catch (error) {
      console.error(`${tableName} 컬럼 로드 실패:`, error);
      return [];
    }
  };

  // 테이블 선택 시 컬럼 로드
  useEffect(() => {
    const loadColumns = async () => {
      const tablesToLoad = new Set<string>();

      // 필드 매핑에서 사용되는 모든 테이블 수집
      dataSaveSettings.actions?.forEach((action) => {
        action.fieldMappings?.forEach((mapping) => {
          if (mapping.sourceTable && !tableColumnsCache[mapping.sourceTable]) {
            tablesToLoad.add(mapping.sourceTable);
          }
          if (mapping.targetTable && !tableColumnsCache[mapping.targetTable]) {
            tablesToLoad.add(mapping.targetTable);
          }
        });
      });

      // 필요한 테이블들의 컬럼만 로드
      for (const tableName of tablesToLoad) {
        await loadTableColumns(tableName);
      }
    };

    loadColumns();
  }, [dataSaveSettings.actions, tableColumnsCache]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleConfirm = () => {
    if (!config.relationshipName || !connection) {
      toast.error("필수 정보를 모두 입력해주세요.");
      return;
    }

    // 연결 종류별 설정을 준비
    let settings = {};
    let plan = {}; // plan 변수 선언

    switch (config.connectionType) {
      case "simple-key":
        settings = simpleKeySettings;
        break;
      case "data-save":
        settings = dataSaveSettings;

        // INSERT가 아닌 액션 타입에 대한 실행조건 필수 검증
        for (const action of dataSaveSettings.actions) {
          if (action.actionType !== "insert") {
            if (!action.conditions || action.conditions.length === 0) {
              toast.error(
                `${action.actionType.toUpperCase()} 액션은 실행조건이 필수입니다. '${action.name}' 액션에 실행조건을 추가해주세요.`,
              );
              return;
            }

            // 실제 조건이 있는지 확인 (group-start, group-end만 있는 경우 제외)
            const hasValidConditions = action.conditions.some((condition) => {
              if (condition.type !== "condition") return false;
              if (!condition.field || !condition.operator) return false;

              // value가 null, undefined, 빈 문자열이면 유효하지 않음
              const value = condition.value;
              if (value === null || value === undefined || value === "") return false;

              return true;
            });

            if (!hasValidConditions) {
              toast.error(
                `${action.actionType.toUpperCase()} 액션은 완전한 실행조건이 필요합니다. '${action.name}' 액션에 필드, 연산자, 값을 모두 설정해주세요.`,
              );
              return;
            }
          }
        }
        break;
      case "external-call":
        // 외부 호출은 plan에 저장
        plan = {
          externalCall: {
            configId: externalCallSettings.configId,
            configName: externalCallSettings.configName,
            message: externalCallSettings.message,
          },
        };
        settings = {}; // 외부 호출은 settings에 저장하지 않음
        break;
    }

    // 단순 키값 연결일 때만 컬럼 선택 검증
    if (config.connectionType === "simple-key") {
      if (selectedFromColumns.length === 0 || selectedToColumns.length === 0) {
        toast.error("선택된 컬럼이 없습니다. From과 To 테이블에서 각각 최소 1개 이상의 컬럼을 선택해주세요.");
        return;
      }
    }

    // 선택된 테이블과 컬럼 정보 사용
    const fromTableName = selectedFromTable || connection.fromNode.tableName;
    const toTableName = selectedToTable || connection.toNode.tableName;

    // 조건부 연결 설정 데이터 준비
    const conditionalSettings = isConditionalConnection(config.connectionType)
      ? {
          control: {
            triggerType: "insert",
            conditionTree: conditions.length > 0 ? conditions : null,
          },
          category: {
            type: config.connectionType,
          },
          plan: {
            sourceTable: fromTableName,
            targetActions:
              config.connectionType === "data-save"
                ? dataSaveSettings.actions.map((action) => ({
                    id: action.id,
                    actionType: action.actionType,
                    enabled: true,
                    conditions:
                      action.conditions?.map((condition) => {
                        // 모든 조건 타입에 대해 operator 필드 보장
                        const baseCondition = { ...condition };
                        if (condition.type === "condition") {
                          baseCondition.operator = condition.operator || "=";
                        }
                        return baseCondition;
                      }) || [],
                    fieldMappings: action.fieldMappings.map((mapping) => ({
                      sourceTable: mapping.sourceTable,
                      sourceField: mapping.sourceField,
                      targetTable: mapping.targetTable,
                      targetField: mapping.targetField,
                      defaultValue: mapping.defaultValue,
                      transformFunction: mapping.transformFunction,
                    })),
                    splitConfig: action.splitConfig,
                  }))
                : [],
          },
        }
      : {};

    // 컬럼 정보는 단순 키값 연결일 때만 사용
    const finalFromColumns = config.connectionType === "simple-key" ? selectedFromColumns : [];
    const finalToColumns = config.connectionType === "simple-key" ? selectedToColumns : [];

    // 메모리 기반 시스템: 관계 데이터만 생성하여 부모로 전달
    const relationshipData: TableRelationship = {
      relationship_name: config.relationshipName,
      from_table_name: fromTableName,
      to_table_name: toTableName,
      from_column_name: finalFromColumns.join(","), // 여러 컬럼을 콤마로 구분
      to_column_name: finalToColumns.join(","), // 여러 컬럼을 콤마로 구분
      connection_type: config.connectionType,
      company_code: companyCode,
      settings: {
        ...settings,
        ...conditionalSettings, // 조건부 연결 설정 추가
        ...plan, // 외부 호출 plan 추가
      },
    };

    toast.success("관계가 생성되었습니다!");

    // 부모 컴포넌트로 관계 데이터 전달 (DB 저장 없이)
    onConfirm(relationshipData);
    handleCancel(); // 모달 닫기
  };

  const handleCancel = () => {
    setConfig({
      relationshipName: "",
      connectionType: "simple-key",
      fromColumnName: "",
      toColumnName: "",
    });
    onCancel();
  };

  // 연결 종류별 설정 패널 렌더링
  const renderConnectionTypeSettings = () => {
    switch (config.connectionType) {
      case "simple-key":
        return (
          <SimpleKeySettingsComponent
            settings={simpleKeySettings}
            onSettingsChange={setSimpleKeySettings}
            availableTables={availableTables}
            selectedFromTable={selectedFromTable}
            selectedToTable={selectedToTable}
            fromTableColumns={fromTableColumns}
            toTableColumns={toTableColumns}
            selectedFromColumns={selectedFromColumns}
            selectedToColumns={selectedToColumns}
            onFromColumnsChange={setSelectedFromColumns}
            onToColumnsChange={setSelectedToColumns}
          />
        );

      case "data-save":
        return (
          <DataSaveSettingsComponent
            settings={dataSaveSettings}
            onSettingsChange={setDataSaveSettings}
            availableTables={availableTables}
            fromTableColumns={fromTableColumns}
            toTableColumns={toTableColumns}
            fromTableName={selectedFromTable}
            toTableName={selectedToTable}
            tableColumnsCache={tableColumnsCache}
          />
        );

      case "external-call":
        return (
          <ExternalCallSettingsComponent settings={externalCallSettings} onSettingsChange={setExternalCallSettings} />
        );

      default:
        return null;
    }
  };

  const isButtonDisabled = () => {
    // 공통 검증: 관계 이름은 필수
    const hasRelationshipName = !!config.relationshipName?.trim();
    if (!hasRelationshipName) return true;

    // 연결 타입별 검증
    switch (config.connectionType) {
      case "simple-key":
        // 단순 키값 연결: From과 To 컬럼이 모두 선택되어야 함
        const hasFromColumns = selectedFromColumns.length > 0;
        const hasToColumns = selectedToColumns.length > 0;
        return !hasFromColumns || !hasToColumns;

      case "data-save":
        // 데이터 저장: 액션과 필드 매핑이 완성되어야 함
        const hasActions = dataSaveSettings.actions.length > 0;

        // DELETE 액션은 필드 매핑이 필요 없음
        const allActionsHaveMappings = dataSaveSettings.actions.every((action) => {
          if (action.actionType === "delete") {
            return true; // DELETE는 필드 매핑 불필요
          }
          return action.fieldMappings.length > 0;
        });

        const allMappingsComplete = dataSaveSettings.actions.every((action) => {
          if (action.actionType === "delete") {
            return true; // DELETE는 필드 매핑 검증 생략
          }

          // INSERT 액션의 경우 모든 TO 테이블 컬럼이 매핑되거나 기본값이 있어야 함
          if (action.actionType === "insert") {
            // TO 테이블의 모든 컬럼을 찾기
            const toTableName = action.fieldMappings[0]?.targetTable;
            if (!toTableName) return false;

            const toTableColumns = tableColumnsCache[toTableName] || [];
            if (toTableColumns.length === 0) return false;

            // 모든 TO 컬럼이 매핑되거나 기본값이 있는지 확인
            return toTableColumns.every((column) => {
              const mapping = action.fieldMappings.find((m) => m.targetField === column.columnName);
              if (!mapping) return false;

              // 소스 매핑 또는 기본값 중 하나는 있어야 함
              const hasSource = mapping.sourceTable && mapping.sourceField;
              const hasDefault = mapping.defaultValue && mapping.defaultValue.trim();

              return hasSource || hasDefault;
            });
          }

          return action.fieldMappings.every((mapping) => {
            // 타겟은 항상 필요
            if (!mapping.targetTable || !mapping.targetField) return false;

            // 소스와 기본값 중 하나는 있어야 함
            const hasSource = mapping.sourceTable && mapping.sourceField;
            const hasDefault = mapping.defaultValue && mapping.defaultValue.trim();

            // FROM 테이블이 비어있으면 기본값이 필요
            if (!mapping.sourceTable) {
              return !!hasDefault;
            }

            // FROM 테이블이 있으면 소스 매핑 완성 또는 기본값 필요
            return hasSource || hasDefault;
          });
        });

        // INSERT가 아닌 액션 타입에 대한 실행조건 필수 검증
        const allRequiredConditionsMet = dataSaveSettings.actions.every((action) => {
          if (action.actionType === "insert") {
            return true; // INSERT는 조건 불필요
          }

          // INSERT가 아닌 액션은 유효한 조건이 있어야 함
          if (!action.conditions || action.conditions.length === 0) {
            return false;
          }

          // 실제 조건이 있는지 확인 (group-start, group-end만 있는 경우 제외)
          const hasValidConditions = action.conditions.some((condition) => {
            if (condition.type !== "condition") return false;
            if (!condition.field || !condition.operator) return false;

            // value가 null, undefined, 빈 문자열이면 유효하지 않음
            const value = condition.value;
            if (value === null || value === undefined || value === "") return false;

            return true;
          });

          return hasValidConditions;
        });

        return !hasActions || !allActionsHaveMappings || !allMappingsComplete || !allRequiredConditionsMet;

      case "external-call":
        // 외부 호출: 설정 ID와 메시지가 있어야 함
        return !externalCallSettings.configId || !externalCallSettings.message?.trim();

      default:
        return false;
    }
  };

  if (!connection) return null;

  return (
    <Dialog open={isOpen} onOpenChange={handleCancel}>
      <DialogContent className="max-h-[80vh] max-w-3xl overflow-y-auto">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2 text-lg">
            <Link className="h-4 w-4" />
            필드 연결 설정
          </DialogTitle>
        </DialogHeader>

        <div className="space-y-4">
          {/* 기본 연결 설정 */}
          <div className="grid grid-cols-2 gap-4">
            <div>
              <Label htmlFor="relationshipName">연결 이름</Label>
              <Input
                id="relationshipName"
                value={config.relationshipName}
                onChange={(e) => setConfig({ ...config, relationshipName: e.target.value })}
                placeholder="employee_id_department_id_연결"
                className="text-sm"
              />
            </div>
          </div>

          {/* 연결 종류 선택 */}
          <ConnectionTypeSelector config={config} onConfigChange={setConfig} />

          {/* 조건부 연결을 위한 조건 설정 */}
          {isConditionalConnection(config.connectionType) && (
            <ConditionalSettings
              conditions={conditions}
              fromTableColumns={fromTableColumns}
              onAddCondition={addCondition}
              onAddGroupStart={addGroupStart}
              onAddGroupEnd={addGroupEnd}
              onUpdateCondition={updateCondition}
              onRemoveCondition={removeCondition}
              getCurrentGroupLevel={getCurrentGroupLevel}
            />
          )}

          {/* 연결 종류별 상세 설정 */}
          {renderConnectionTypeSettings()}
        </div>

        <DialogFooter>
          <Button variant="outline" onClick={handleCancel}>
            취소
          </Button>
          <Button onClick={handleConfirm} disabled={isButtonDisabled()}>
            연결 생성
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
};
