/**
 * 🔥 개선된 버튼 액션 실행기
 *
 * 계획서에 따른 새로운 실행 플로우:
 * 1. Before 타이밍 제어 실행
 * 2. 메인 액션 실행 (replace가 아닌 경우)
 * 3. After 타이밍 제어 실행
 */

import { toast } from "sonner";
import { showErrorToast } from "@/lib/utils/toastUtils";
import { apiClient } from "@/lib/api/client";
import { ExtendedButtonTypeConfig, ButtonDataflowConfig } from "@/types/control-management";
import { ButtonActionType } from "@/types/v2-core";

// ===== 인터페이스 정의 =====

export interface ButtonExecutionContext {
  buttonId: string;
  screenId: string;
  userId: string;
  companyCode: string;
  startTime: number;
  formData?: Record<string, any>;
  selectedRows?: any[];
  tableData?: any[];
  flowSelectedData?: any[];
  flowSelectedStepId?: number | null;
}

export interface ExecutionResult {
  success: boolean;
  message: string;
  executionTime: number;
  data?: any;
  error?: string;
}

export interface ButtonExecutionResult {
  success: boolean;
  results: ExecutionResult[];
  executionTime: number;
  error?: string;
}

interface ControlConfig {
  type: "relationship" | "flow";
  relationshipConfig?: {
    relationshipId: string;
    relationshipName: string;
    executionTiming: "before" | "after" | "replace";
    contextData?: Record<string, any>;
  };
  // 🆕 플로우 기반 제어 설정
  flowConfig?: {
    flowId: number;
    flowName: string;
    executionTiming: "before" | "after" | "replace";
    contextData?: Record<string, any>;
  };
}

interface ExecutionPlan {
  beforeControls: ControlConfig[];
  afterControls: ControlConfig[];
  hasReplaceControl: boolean;
}

// ===== 메인 실행기 클래스 =====

export class ImprovedButtonActionExecutor {
  /**
   * 🔥 개선된 버튼 액션 실행
   */
  static async executeButtonAction(
    buttonConfig: ExtendedButtonTypeConfig,
    formData: Record<string, any>,
    context: ButtonExecutionContext,
  ): Promise<ButtonExecutionResult> {
    console.log("🔥 ImprovedButtonActionExecutor 시작:", {
      buttonConfig,
      formData,
      context,
    });

    const executionPlan = this.createExecutionPlan(buttonConfig);
    const results: ExecutionResult[] = [];

    console.log("📋 생성된 실행 계획:", {
      beforeControls: executionPlan.beforeControls,
      afterControls: executionPlan.afterControls,
      hasReplaceControl: executionPlan.hasReplaceControl,
    });

    try {
      console.log("🚀 버튼 액션 실행 시작:", {
        actionType: buttonConfig.actionType,
        hasControls: executionPlan.beforeControls.length + executionPlan.afterControls.length > 0,
        hasReplace: executionPlan.hasReplaceControl,
      });

      // 1. Before 타이밍 제어 실행
      if (executionPlan.beforeControls.length > 0) {
        console.log("⏰ Before 제어 실행 시작");
        const beforeResults = await this.executeControls(executionPlan.beforeControls, formData, context);
        results.push(...beforeResults);

        // Before 제어 중 실패가 있으면 중단
        const hasFailure = beforeResults.some((r) => !r.success);
        if (hasFailure) {
          throw new Error("Before 제어 실행 중 오류가 발생했습니다.");
        }
      }

      // 2. 메인 액션 실행 (replace가 아닌 경우에만)
      if (!executionPlan.hasReplaceControl) {
        console.log("⚡ 메인 액션 실행:", buttonConfig.actionType);
        const mainResult = await this.executeMainAction(buttonConfig, formData, context);
        results.push(mainResult);

        if (!mainResult.success) {
          throw new Error("메인 액션 실행 중 오류가 발생했습니다.");
        }
      } else {
        console.log("🔄 Replace 모드: 메인 액션 건너뜀");
      }

      // 3. After 타이밍 제어 실행
      if (executionPlan.afterControls.length > 0) {
        console.log("⏰ After 제어 실행 시작");
        const afterResults = await this.executeControls(executionPlan.afterControls, formData, context);
        results.push(...afterResults);
      }

      const totalExecutionTime = Date.now() - context.startTime;
      console.log("✅ 버튼 액션 실행 완료:", `${totalExecutionTime}ms`);

      return {
        success: true,
        results,
        executionTime: totalExecutionTime,
      };
    } catch (error) {
      console.error("❌ 버튼 액션 실행 실패:", error);

      // 롤백 처리
      await this.handleExecutionError(error, results, buttonConfig);

      return {
        success: false,
        results,
        executionTime: Date.now() - context.startTime,
        error: error.message,
      };
    }
  }

  /**
   * 🔥 실행 계획 생성
   */
  private static createExecutionPlan(buttonConfig: ExtendedButtonTypeConfig): ExecutionPlan {
    const plan: ExecutionPlan = {
      beforeControls: [],
      afterControls: [],
      hasReplaceControl: false,
    };

    const dataflowConfig = buttonConfig.dataflowConfig;
    if (!dataflowConfig) {
      console.log("⚠️ dataflowConfig가 없습니다");
      return plan;
    }

    // 🔧 controlMode가 없으면 flowConfig/relationshipConfig 존재 여부로 자동 판단
    const effectiveControlMode = dataflowConfig.controlMode 
      || (dataflowConfig.flowConfig ? "flow" : null)
      || (dataflowConfig.relationshipConfig ? "relationship" : null)
      || "none";

    console.log("📋 실행 계획 생성:", {
      controlMode: dataflowConfig.controlMode,
      effectiveControlMode,
      hasFlowConfig: !!dataflowConfig.flowConfig,
      hasRelationshipConfig: !!dataflowConfig.relationshipConfig,
      enableDataflowControl: buttonConfig.enableDataflowControl,
    });

    // 관계 기반 제어
    if (effectiveControlMode === "relationship" && dataflowConfig.relationshipConfig) {
      const control: ControlConfig = {
        type: "relationship",
        relationshipConfig: dataflowConfig.relationshipConfig,
      };

      switch (dataflowConfig.relationshipConfig.executionTiming) {
        case "before":
          plan.beforeControls.push(control);
          break;
        case "after":
          plan.afterControls.push(control);
          break;
        case "replace":
          plan.afterControls.push(control); // Replace는 after로 처리하되 플래그 설정
          plan.hasReplaceControl = true;
          break;
      }
    }

    // 🆕 플로우 기반 제어
    if (effectiveControlMode === "flow" && dataflowConfig.flowConfig) {
      const control: ControlConfig = {
        type: "flow",
        flowConfig: dataflowConfig.flowConfig,
      };

      console.log("📋 플로우 제어 설정:", dataflowConfig.flowConfig);

      switch (dataflowConfig.flowConfig.executionTiming) {
        case "before":
          plan.beforeControls.push(control);
          break;
        case "after":
          plan.afterControls.push(control);
          break;
        case "replace":
          plan.afterControls.push(control);
          plan.hasReplaceControl = true;
          break;
      }
    }

    return plan;
  }

  /**
   * 🔥 제어 실행 (관계 또는 플로우)
   */
  private static async executeControls(
    controls: ControlConfig[],
    formData: Record<string, any>,
    context: ButtonExecutionContext,
  ): Promise<ExecutionResult[]> {
    const results: ExecutionResult[] = [];

    for (const control of controls) {
      try {
        let result: ExecutionResult;

        // 🆕 제어 타입에 따라 분기 처리
        if (control.type === "flow" && control.flowConfig) {
          result = await this.executeFlow(control.flowConfig, formData, context);
        } else if (control.type === "relationship" && control.relationshipConfig) {
          result = await this.executeRelationship(control.relationshipConfig, formData, context);
        } else {
          throw new Error(`지원하지 않는 제어 타입: ${control.type}`);
        }

        results.push(result);

        // 제어 실행 실패 시 중단
        if (!result.success) {
          throw new Error(result.message);
        }
      } catch (error: any) {
        console.error(`제어 실행 실패 (${control.type}):`, error);
        results.push({
          success: false,
          message: `${control.type} 제어 실행 실패: ${error.message}`,
          executionTime: 0,
          error: error.message,
        });
        throw error;
      }
    }

    return results;
  }

  /**
   * 🆕 플로우 실행
   */
  private static async executeFlow(
    config: {
      flowId: number;
      flowName: string;
      executionTiming: "before" | "after" | "replace";
      contextData?: Record<string, any>;
    },
    formData: Record<string, any>,
    context: ButtonExecutionContext,
  ): Promise<ExecutionResult> {
    const startTime = Date.now();

    try {
      console.log(`🔄 플로우 실행 시작: ${config.flowName} (ID: ${config.flowId})`);

      // 플로우 실행 API 호출
      const response = await apiClient.post(`/api/dataflow/node-flows/${config.flowId}/execute`, {
        formData,
        contextData: config.contextData || {},
        selectedRows: context.selectedRows || [],
        flowSelectedData: context.flowSelectedData || [],
        screenId: context.screenId,
        companyCode: context.companyCode,
        userId: context.userId,
      });

      const executionTime = Date.now() - startTime;

      if (response.data?.success) {
        console.log(`✅ 플로우 실행 성공: ${config.flowName}`, response.data);
        return {
          success: true,
          message: `플로우 "${config.flowName}" 실행 완료`,
          executionTime,
          data: response.data,
        };
      } else {
        throw new Error(response.data?.message || "플로우 실행 실패");
      }
    } catch (error: any) {
      const executionTime = Date.now() - startTime;
      console.error(`❌ 플로우 실행 실패: ${config.flowName}`, error);

      return {
        success: false,
        message: `플로우 "${config.flowName}" 실행 실패: ${error.message}`,
        executionTime,
        error: error.message,
      };
    }
  }

  /**
   * 🔥 관계 실행
   */
  private static async executeRelationship(
    config: {
      relationshipId: string;
      relationshipName: string;
      executionTiming: "before" | "after" | "replace";
      contextData?: Record<string, any>;
    },
    formData: Record<string, any>,
    context: ButtonExecutionContext,
  ): Promise<ExecutionResult> {
    try {
      console.log(`🔗 관계 실행 시작: ${config.relationshipName} (ID: ${config.relationshipId})`);

      // 1. 관계 정보 조회
      const relationshipData = await this.getRelationshipData(config.relationshipId);
      if (!relationshipData) {
        throw new Error(`관계 정보를 찾을 수 없습니다: ${config.relationshipId}`);
      }

      console.log("📋 관계 데이터 로드 완료:", relationshipData);

      // 2. 관계 타입에 따른 실행
      const relationships = relationshipData.relationships;
      const connectionType = relationships.connectionType;

      console.log("🔍 관계 상세 정보:", {
        connectionType,
        hasExternalCallConfig: !!relationships.externalCallConfig,
        externalCallConfig: relationships.externalCallConfig,
        hasDataSaveConfig: !!relationships.dataSaveConfig,
        dataSaveConfig: relationships.dataSaveConfig,
      });

      let result: ExecutionResult;

      if (connectionType === "external_call") {
        // 외부 호출 실행
        result = await this.executeExternalCall(relationships, formData, context);
      } else if (connectionType === "data_save") {
        // 데이터 저장 실행
        result = await this.executeDataSave(relationships, formData, context);
      } else {
        throw new Error(`지원하지 않는 연결 타입: ${connectionType}`);
      }

      console.log(`✅ 관계 실행 완료: ${config.relationshipName}`, result);

      if (result.success) {
        toast.success(`관계 '${config.relationshipName}' 실행 완료`);
      } else {
        showErrorToast(`관계 '${config.relationshipName}' 실행에 실패했습니다`, result.message, {
          guidance: "관계 설정과 대상 데이터를 확인해 주세요.",
        });
      }

      return result;
    } catch (error: any) {
      console.error(`❌ 관계 실행 실패: ${config.relationshipName}`, error);
      const errorResult = {
        success: false,
        message: `관계 '${config.relationshipName}' 실행 실패: ${error.message}`,
        executionTime: 0,
        error: error.message,
      };

      showErrorToast(`관계 '${config.relationshipName}' 실행에 실패했습니다`, error, {
        guidance: "관계 설정과 연결 상태를 확인해 주세요.",
      });
      return errorResult;
    }
  }

  /**
   * 관계 데이터 조회
   */
  private static async getRelationshipData(relationshipId: string): Promise<any> {
    try {
      console.log(`🔍 관계 데이터 조회 시작: ${relationshipId}`);

      const response = await apiClient.get(`/dataflow-diagrams/${relationshipId}`);

      console.log("✅ 관계 데이터 조회 성공:", response.data);

      if (!response.data.success) {
        throw new Error(response.data.message || "관계 데이터 조회 실패");
      }

      return response.data.data;
    } catch (error) {
      console.error("관계 데이터 조회 오류:", error);
      throw error;
    }
  }

  /**
   * 외부 호출 실행
   */
  private static async executeExternalCall(
    relationships: any,
    formData: Record<string, any>,
    context: ButtonExecutionContext,
  ): Promise<ExecutionResult> {
    try {
      console.log("🔍 외부 호출 실행 시작 - relationships 구조:", relationships);

      const externalCallConfig = relationships.externalCallConfig;
      console.log("🔍 externalCallConfig:", externalCallConfig);

      if (!externalCallConfig) {
        console.error("❌ 외부 호출 설정이 없습니다. relationships 구조:", relationships);
        throw new Error("외부 호출 설정이 없습니다");
      }

      const restApiSettings = externalCallConfig.restApiSettings;
      if (!restApiSettings) {
        throw new Error("REST API 설정이 없습니다");
      }

      console.log(`🌐 외부 API 호출: ${restApiSettings.apiUrl}`);

      // API 호출 준비
      const headers: Record<string, string> = {
        "Content-Type": "application/json",
        ...restApiSettings.headers,
      };

      // 인증 처리
      if (restApiSettings.authentication?.type === "api-key") {
        headers["Authorization"] = `Bearer ${restApiSettings.authentication.apiKey}`;
      }

      // 요청 바디 준비 (템플릿 처리)
      let requestBody = restApiSettings.bodyTemplate || "";
      if (requestBody) {
        // 간단한 템플릿 치환 ({{변수명}} 형태)
        requestBody = requestBody.replace(/\{\{(\w+)\}\}/g, (match: string, key: string) => {
          return formData[key] || (context as any).contextData?.[key] || new Date().toISOString();
        });
      }

      // 백엔드 프록시를 통한 외부 API 호출 (CORS 문제 해결)
      console.log("🌐 백엔드 프록시를 통한 외부 API 호출 준비:", {
        originalUrl: restApiSettings.apiUrl,
        method: restApiSettings.httpMethod || "GET",
        headers,
        body: restApiSettings.httpMethod !== "GET" ? requestBody : undefined,
      });

      // 백엔드 프록시 API 호출 - GenericApiSettings 형식에 맞게 전달
      const requestPayload = {
        diagramId: relationships.diagramId || 45, // 관계 ID 사용
        relationshipId: relationships.relationshipId || "relationship-45",
        settings: {
          callType: "rest-api",
          apiType: "generic",
          url: restApiSettings.apiUrl,
          method: restApiSettings.httpMethod || "POST",
          headers: restApiSettings.headers || {},
          body: requestBody,
          authentication: restApiSettings.authentication || { type: "none" },
          timeout: restApiSettings.timeout || 30000,
          retryCount: restApiSettings.retryCount || 3,
        },
        templateData: restApiSettings.httpMethod !== "GET" && requestBody ? JSON.parse(requestBody) : formData,
      };

      console.log("📤 백엔드로 전송할 데이터:", requestPayload);

      const proxyResponse = await apiClient.post("/external-calls/execute", requestPayload);

      console.log("📡 백엔드 프록시 응답:", proxyResponse.data);

      if (!proxyResponse.data.success) {
        throw new Error(`프록시 API 호출 실패: ${proxyResponse.data.error || proxyResponse.data.message}`);
      }

      const responseData = proxyResponse.data.result;
      console.log("✅ 외부 API 호출 성공 (프록시):", responseData);

      // 데이터 매핑 처리 (inbound mapping)
      if (externalCallConfig.dataMappingConfig?.inboundMapping) {
        console.log(`📥 데이터 매핑 설정 발견 - HTTP 메서드: ${restApiSettings.httpMethod}`);
        console.log("📥 매핑 설정:", externalCallConfig.dataMappingConfig.inboundMapping);
        console.log("📥 응답 데이터:", responseData);

        await this.processInboundMapping(externalCallConfig.dataMappingConfig.inboundMapping, responseData, context);
      } else {
        console.log(`ℹ️ 데이터 매핑 설정이 없습니다 - HTTP 메서드: ${restApiSettings.httpMethod}`);
      }

      return {
        success: true,
        message: "외부 호출 실행 완료",
        executionTime: Date.now() - context.startTime,
        data: responseData,
      };
    } catch (error: any) {
      console.error("외부 호출 실행 오류:", error);
      return {
        success: false,
        message: `외부 호출 실행 실패: ${error.message}`,
        executionTime: Date.now() - context.startTime,
        error: error.message,
      };
    }
  }

  /**
   * 데이터 저장 실행
   */
  private static async executeDataSave(
    relationships: any,
    formData: Record<string, any>,
    context: ButtonExecutionContext,
  ): Promise<ExecutionResult> {
    try {
      console.log("💾 데이터 저장 실행 시작");

      // 제어 조건 확인
      const controlConditions = relationships.controlConditions || [];
      if (controlConditions.length > 0) {
        const conditionsMet = this.evaluateConditions(controlConditions, formData, context);
        if (!conditionsMet) {
          return {
            success: false,
            message: "제어 조건을 만족하지 않아 데이터 저장을 건너뜁니다",
            executionTime: Date.now() - context.startTime,
          };
        }
      }

      // 액션 그룹 실행
      const actionGroups = relationships.actionGroups || [];
      const results = [];

      for (const actionGroup of actionGroups) {
        if (!actionGroup.isEnabled) {
          console.log(`⏭️ 비활성화된 액션 그룹 건너뜀: ${actionGroup.name}`);
          continue;
        }

        console.log(`🎯 액션 그룹 실행: ${actionGroup.name}`);

        for (const action of actionGroup.actions) {
          if (!action.isEnabled) {
            console.log(`⏭️ 비활성화된 액션 건너뜀: ${action.name}`);
            continue;
          }

          const actionResult = await this.executeDataAction(action, relationships, formData, context);
          results.push(actionResult);

          if (!actionResult.success) {
            console.error(`❌ 액션 실행 실패: ${action.name}`, actionResult);
          }
        }
      }

      const successCount = results.filter((r) => r.success).length;
      const totalCount = results.length;

      return {
        success: successCount > 0,
        message: `데이터 저장 완료: ${successCount}/${totalCount} 액션 성공`,
        executionTime: Date.now() - context.startTime,
        data: {
          results,
          successCount,
          totalCount,
        },
      };
    } catch (error: any) {
      console.error("데이터 저장 실행 오류:", error);
      return {
        success: false,
        message: `데이터 저장 실행 실패: ${error.message}`,
        executionTime: Date.now() - context.startTime,
        error: error.message,
      };
    }
  }

  /**
   * 개별 데이터 액션 실행
   */
  private static async executeDataAction(
    action: any,
    relationships: any,
    formData: Record<string, any>,
    context: ButtonExecutionContext,
  ): Promise<ExecutionResult> {
    try {
      console.log(`🔧 데이터 액션 실행: ${action.name} (${action.actionType})`);
      console.log("📥 받은 formData:", formData);
      console.log("📥 formData 키들:", Object.keys(formData));

      // 🔥 UPDATE 액션의 경우 formData를 기본으로 시작 (기본키 포함)
      const mappedData: Record<string, any> = action.actionType === "update" ? { ...formData } : {};

      // 필드 매핑 처리 (기존 데이터에 덮어쓰기)
      for (const mapping of action.fieldMappings) {
        if (mapping.valueType === "static") {
          // 정적 값 처리
          let value = mapping.value;
          if (value === "#NOW") {
            value = new Date().toISOString();
          }
          mappedData[mapping.targetField] = value;
          console.log(`🔧 정적 값 매핑: ${mapping.targetField} = ${value}`);
        } else {
          // 필드 매핑 처리
          const sourceField = mapping.fromField?.columnName;
          if (sourceField && formData[sourceField] !== undefined) {
            mappedData[mapping.toField.columnName] = formData[sourceField];
            console.log(`🔧 필드 매핑: ${sourceField} → ${mapping.toField.columnName} = ${formData[sourceField]}`);
          }
        }
      }

      console.log("📋 최종 매핑된 데이터:", mappedData);
      console.log("🔑 기본키 포함 여부 체크:", {
        hasId: "id" in mappedData,
        keys: Object.keys(mappedData),
        values: Object.values(mappedData),
      });

      // 대상 연결 정보
      const toConnection = relationships.toConnection;
      const targetTable = relationships.toTable?.tableName;

      if (!targetTable) {
        throw new Error("대상 테이블이 지정되지 않았습니다");
      }

      // 데이터 저장 API 호출
      const saveResult = await this.saveDataToTable(targetTable, mappedData, action.actionType, toConnection);

      return {
        success: true,
        message: `데이터 액션 "${action.name}" 실행 완료`,
        executionTime: Date.now() - context.startTime,
        data: saveResult,
      };
    } catch (error: any) {
      console.error(`데이터 액션 실행 오류: ${action.name}`, error);
      return {
        success: false,
        message: `데이터 액션 실행 실패: ${error.message}`,
        executionTime: Date.now() - context.startTime,
        error: error.message,
      };
    }
  }

  /**
   * 테이블에 데이터 저장
   */
  private static async saveDataToTable(
    tableName: string,
    data: Record<string, any>,
    actionType: string,
    connection?: any,
  ): Promise<any> {
    try {
      console.log(`💾 테이블 데이터 저장 시작: ${tableName}`, {
        actionType,
        data,
        connection,
      });

      // 데이터 저장 API 호출 (apiClient 사용)
      const response = await apiClient.post("/dataflow/execute-data-action", {
        tableName,
        data,
        actionType,
        connection,
      });

      console.log(`✅ 테이블 데이터 저장 성공: ${tableName}`, response.data);
      return response.data;
    } catch (error) {
      console.error("테이블 데이터 저장 오류:", error);
      throw error;
    }
  }

  /**
   * 조건 평가
   */
  private static evaluateConditions(
    conditions: any[],
    formData: Record<string, any>,
    context: ButtonExecutionContext,
  ): boolean {
    console.log("🔍 조건 평가 시작:", {
      conditions,
      formDataKeys: Object.keys(formData),
      formData,
      contextData: context.contextData,
    });

    for (const condition of conditions) {
      const fieldValue = formData[condition.field];
      const conditionValue = condition.value;
      const operator = condition.operator;

      console.log("🔍 개별 조건 검증:", {
        field: condition.field,
        operator,
        expectedValue: conditionValue,
        actualValue: fieldValue,
        formDataHasField: condition.field in formData,
        allFormDataKeys: Object.keys(formData),
      });

      let conditionMet = false;
      switch (operator) {
        case "=":
          conditionMet = fieldValue === conditionValue;
          break;
        case "!=":
          conditionMet = fieldValue !== conditionValue;
          break;
        case ">":
          conditionMet = Number(fieldValue) > Number(conditionValue);
          break;
        case "<":
          conditionMet = Number(fieldValue) < Number(conditionValue);
          break;
        case ">=":
          conditionMet = Number(fieldValue) >= Number(conditionValue);
          break;
        case "<=":
          conditionMet = Number(fieldValue) <= Number(conditionValue);
          break;
        default:
          console.warn(`지원하지 않는 연산자: ${operator}`);
          conditionMet = true;
      }

      if (!conditionMet) {
        console.log(`❌ 조건 불만족: ${condition.field} ${operator} ${conditionValue} (실제값: ${fieldValue})`);
        console.log("❌ 사용 가능한 필드들:", Object.keys(formData));
        console.log("❌ 전체 formData:", formData);
        return false;
      }
    }

    console.log("✅ 모든 조건 만족");
    return true;
  }

  /**
   * 다양한 API 응답 구조에서 실제 데이터 추출
   */
  private static extractActualData(responseData: any): any {
    console.log(`🔍 데이터 추출 시작 - 원본 타입: ${typeof responseData}`);

    // null이나 undefined인 경우
    if (!responseData) {
      console.log("⚠️ 응답 데이터가 null 또는 undefined");
      return [];
    }

    // 이미 배열인 경우 (직접 배열 응답)
    if (Array.isArray(responseData)) {
      console.log("✅ 직접 배열 응답 감지");
      return responseData;
    }

    // 문자열인 경우 JSON 파싱 시도
    if (typeof responseData === "string") {
      console.log("🔄 JSON 문자열 파싱 시도");
      try {
        const parsed = JSON.parse(responseData);
        console.log("✅ JSON 파싱 성공, 재귀 호출");
        return this.extractActualData(parsed);
      } catch (error) {
        console.log("⚠️ JSON 파싱 실패, 원본 문자열 반환:", error);
        return [responseData];
      }
    }

    // 객체가 아닌 경우 (숫자 등)
    if (typeof responseData !== "object") {
      console.log(`⚠️ 객체가 아닌 응답: ${typeof responseData}`);
      return [responseData];
    }

    // 일반적인 데이터 필드명들을 우선순위대로 확인
    const commonDataFields = [
      "data", // { data: [...] }
      "result", // { result: [...] }
      "results", // { results: [...] }
      "items", // { items: [...] }
      "list", // { list: [...] }
      "records", // { records: [...] }
      "rows", // { rows: [...] }
      "content", // { content: [...] }
      "payload", // { payload: [...] }
      "response", // { response: [...] }
    ];

    for (const field of commonDataFields) {
      if (responseData[field] !== undefined) {
        console.log(`✅ '${field}' 필드에서 데이터 추출`);

        const extractedData = responseData[field];

        // 추출된 데이터가 문자열인 경우 JSON 파싱 시도
        if (typeof extractedData === "string") {
          console.log("🔄 추출된 데이터가 JSON 문자열, 파싱 시도");
          try {
            const parsed = JSON.parse(extractedData);
            console.log("✅ JSON 파싱 성공, 재귀 호출");
            return this.extractActualData(parsed);
          } catch (error) {
            console.log("⚠️ JSON 파싱 실패, 원본 문자열 반환:", error);
            return [extractedData];
          }
        }

        // 추출된 데이터가 객체이고 또 다른 중첩 구조일 수 있으므로 재귀 호출
        if (typeof extractedData === "object" && !Array.isArray(extractedData)) {
          console.log("🔄 중첩된 객체 감지, 재귀 추출 시도");
          return this.extractActualData(extractedData);
        }

        return extractedData;
      }
    }

    // 특별한 필드가 없는 경우, 객체의 값들 중에서 배열을 찾기
    const objectValues = Object.values(responseData);
    const arrayValue = objectValues.find((value) => Array.isArray(value));

    if (arrayValue) {
      console.log("✅ 객체 값 중 배열 발견");
      return arrayValue;
    }

    // 객체의 값들 중에서 객체를 찾아서 재귀 탐색
    for (const value of objectValues) {
      if (value && typeof value === "object" && !Array.isArray(value)) {
        console.log("🔄 객체 값에서 재귀 탐색");
        const nestedResult = this.extractActualData(value);
        if (Array.isArray(nestedResult) && nestedResult.length > 0) {
          return nestedResult;
        }
      }
    }

    // 모든 시도가 실패한 경우, 원본 객체를 단일 항목 배열로 반환
    console.log("📦 원본 객체를 단일 항목으로 처리");
    return [responseData];
  }

  /**
   * 인바운드 데이터 매핑 처리
   */
  private static async processInboundMapping(
    inboundMapping: any,
    responseData: any,
    context: ButtonExecutionContext,
  ): Promise<void> {
    try {
      console.log("📥 인바운드 데이터 매핑 처리 시작");
      console.log("📥 원본 응답 데이터:", responseData);

      const targetTable = inboundMapping.targetTable;
      const fieldMappings = inboundMapping.fieldMappings || [];
      const insertMode = inboundMapping.insertMode || "insert";

      console.log("📥 매핑 설정:", {
        targetTable,
        fieldMappings,
        insertMode,
      });

      // 응답 데이터에서 실제 데이터 추출 (다양한 구조 지원)
      const actualData = this.extractActualData(responseData);

      console.log("📥 추출된 실제 데이터:", actualData);

      // 배열이 아닌 경우 배열로 변환
      const dataArray = Array.isArray(actualData) ? actualData : [actualData];

      console.log("📥 처리할 데이터 배열:", dataArray);

      if (dataArray.length === 0) {
        console.log("⚠️ 처리할 데이터가 없습니다");
        return;
      }

      for (const item of dataArray) {
        const mappedData: Record<string, any> = {};

        console.log("📥 개별 아이템 처리:", item);

        // 필드 매핑 적용
        for (const mapping of fieldMappings) {
          const sourceValue = item[mapping.sourceField];
          console.log(`📥 필드 매핑: ${mapping.sourceField} -> ${mapping.targetField} = ${sourceValue}`);

          if (sourceValue !== undefined && sourceValue !== null) {
            mappedData[mapping.targetField] = sourceValue;
          }
        }

        console.log("📋 매핑된 데이터:", mappedData);

        // 매핑된 데이터가 비어있지 않은 경우에만 저장
        if (Object.keys(mappedData).length > 0) {
          await this.saveDataToTable(targetTable, mappedData, insertMode);
        } else {
          console.log("⚠️ 매핑된 데이터가 비어있어 저장을 건너뜁니다");
        }
      }

      console.log("✅ 인바운드 데이터 매핑 완료");
    } catch (error) {
      console.error("인바운드 데이터 매핑 오류:", error);
      throw error;
    }
  }

  /**
   * 🔥 메인 액션 실행
   */
  private static async executeMainAction(
    buttonConfig: ExtendedButtonTypeConfig,
    formData: Record<string, any>,
    context: ButtonExecutionContext,
  ): Promise<ExecutionResult> {
    try {
      const startTime = performance.now();

      // transferData 액션 처리
      if (buttonConfig.actionType === "transferData") {
        return await this.executeTransferDataAction(buttonConfig, formData, context);
      }

      // 결재 요청 모달 열기
      if (buttonConfig.actionType === "approval") {
        const actionConfig = (buttonConfig as any).componentConfig?.action || buttonConfig;
        const selectedRow = context.selectedRows?.[0] || context.formData || formData || {};
        const targetTable = actionConfig.approvalTargetTable || "";
        const recordIdField = actionConfig.approvalRecordIdField || "id";
        const targetRecordId = selectedRow?.[recordIdField] || "";

        window.dispatchEvent(
          new CustomEvent("open-approval-modal", {
            detail: {
              targetTable,
              targetRecordId: targetRecordId ? String(targetRecordId) : "",
              targetRecordData: Object.keys(selectedRow).length > 0 ? selectedRow : undefined,
              definitionId: actionConfig.approvalDefinitionId || undefined,
              screenId: context.screenId ? Number(context.screenId) : undefined,
              buttonComponentId: context.buttonId,
            },
          }),
        );

        return {
          success: true,
          message: "결재 요청 모달이 열렸습니다",
          executionTime: performance.now() - startTime,
          data: { actionType: "approval", targetTable, targetRecordId },
        };
      }

      // 기존 액션들 (임시 구현)
      const result = {
        success: true,
        message: `${buttonConfig.actionType} 액션 실행 완료`,
        executionTime: performance.now() - startTime,
        data: { actionType: buttonConfig.actionType, formData },
      };

      console.log("✅ 메인 액션 실행 완료:", result.message);
      return result;
    } catch (error) {
      console.error("메인 액션 실행 오류:", error);
      return {
        success: false,
        message: `${buttonConfig.actionType} 액션 실행 실패: ${error.message}`,
        executionTime: 0,
        error: error.message,
      };
    }
  }

  /**
   * 데이터 전달 액션 실행
   */
  private static async executeTransferDataAction(
    buttonConfig: ExtendedButtonTypeConfig,
    formData: Record<string, any>,
    context: ButtonExecutionContext,
  ): Promise<ExecutionResult> {
    const startTime = performance.now();
    
    try {
      const dataTransferConfig = buttonConfig.dataTransfer;
      
      if (!dataTransferConfig) {
        throw new Error("데이터 전달 설정이 없습니다.");
      }

      console.log("📦 데이터 전달 시작:", dataTransferConfig);

      // 1. 화면 컨텍스트에서 소스 컴포넌트 찾기
      const { ScreenContextProvider } = await import("@/contexts/ScreenContext");
      // 실제로는 현재 화면의 컨텍스트를 사용해야 하지만, 여기서는 전역적으로 접근할 수 없음
      // 대신 context에 screenContext를 전달하도록 수정 필요
      
      throw new Error("데이터 전달 기능은 버튼 컴포넌트에서 직접 구현되어야 합니다.");
      
    } catch (error) {
      console.error("❌ 데이터 전달 실패:", error);
      return {
        success: false,
        message: `데이터 전달 실패: ${error.message}`,
        executionTime: performance.now() - startTime,
        error: error.message,
      };
    }
  }

  /**
   * 🔥 실행 오류 처리 및 롤백
   */
  private static async handleExecutionError(
    error: Error,
    results: ExecutionResult[],
    buttonConfig: ExtendedButtonTypeConfig,
  ): Promise<void> {
    console.error("🔄 실행 오류 처리 시작:", error.message);

    // 롤백이 필요한 경우 처리
    const rollbackNeeded = buttonConfig.dataflowConfig?.executionOptions?.rollbackOnError;
    if (rollbackNeeded) {
      console.log("🔄 롤백 처리 시작...");

      // 성공한 결과들을 역순으로 롤백
      const successfulResults = results.filter((r) => r.success).reverse();

      for (const result of successfulResults) {
        try {
          // 롤백 로직 구현 (필요시)
          console.log("🔄 롤백:", result.message);
        } catch (rollbackError) {
          console.error("롤백 실패:", rollbackError);
        }
      }
    }

    showErrorToast("버튼 액션 실행 중 오류가 발생했습니다", error, {
      guidance: "잠시 후 다시 시도해 주세요. 문제가 계속되면 관리자에게 문의해 주세요.",
    });
  }
}
