/**
 * 노드 플로우 기반 버튼 실행기
 */

import { executeNodeFlow, ExecutionResult } from "../api/nodeFlows";
import { logger } from "../utils/logger";
import { toast } from "sonner";
import type { ButtonDataflowConfig, ExtendedControlContext } from "@/types/control-management";

export interface ButtonExecutionContext {
  buttonId: string;
  screenId?: number;
  companyCode?: string;
  userId?: string;
  formData: Record<string, any>;
  selectedRows?: any[];
  selectedRowsData?: Record<string, any>[];
  controlDataSource?: "form" | "table-selection" | "table-all" | "flow-selection" | "flow-step-all" | "both" | "all-sources";
  
  // 🆕 테이블 전체 데이터 (table-all 모드용)
  tableAllData?: Record<string, any>[];
  
  // 🆕 플로우 스텝 전체 데이터 (flow-step-all 모드용)
  flowStepAllData?: Record<string, any>[];
  flowStepId?: number;
  
  // 🆕 플로우 선택 데이터 (flow-selection 모드용)
  flowSelectedData?: Record<string, any>[];
  
  onRefresh?: () => void;
  onClose?: () => void;
}

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

/**
 * 노드 플로우 실행 함수
 */
export async function executeButtonWithFlow(
  flowConfig: ButtonDataflowConfig["flowConfig"],
  context: ButtonExecutionContext,
  originalAction?: () => Promise<void>,
): Promise<FlowExecutionResult> {
  if (!flowConfig) {
    throw new Error("플로우 설정이 없습니다.");
  }

  const { flowId, flowName, executionTiming = "before" } = flowConfig;

  logger.info(`🚀 노드 플로우 실행 시작:`, {
    flowId,
    flowName,
    timing: executionTiming,
    contextKeys: Object.keys(context),
  });

  try {
    // 컨텍스트 데이터 준비
    const contextData = prepareContextData(context);

    // 타이밍에 따라 실행
    switch (executionTiming) {
      case "before":
        // 1. 플로우 먼저 실행
        const beforeResult = await executeNodeFlow(flowId, contextData);

        if (!beforeResult.success) {
          toast.error(`플로우 실행 실패: ${beforeResult.message}`);
          return {
            success: false,
            message: beforeResult.message,
            data: beforeResult,
          };
        }

        toast.success(`플로우 실행 완료: ${flowName}`);

        // 2. 원래 버튼 액션 실행
        if (originalAction) {
          await originalAction();
        }

        return {
          success: true,
          message: "플로우 및 버튼 액션이 성공적으로 실행되었습니다.",
          executionTime: beforeResult.executionTime,
          data: beforeResult,
        };

      case "after":
        // 1. 원래 버튼 액션 먼저 실행
        if (originalAction) {
          await originalAction();
        }

        // 2. 플로우 실행
        const afterResult = await executeNodeFlow(flowId, contextData);

        if (!afterResult.success) {
          toast.warning(`버튼 액션은 성공했으나 플로우 실행 실패: ${afterResult.message}`);
        } else {
          toast.success(`플로우 실행 완료: ${flowName}`);
        }

        return {
          success: afterResult.success,
          message: afterResult.message,
          executionTime: afterResult.executionTime,
          data: afterResult,
        };

      case "replace":
        // 플로우만 실행 (원래 액션 대체)
        const replaceResult = await executeNodeFlow(flowId, contextData);

        if (!replaceResult.success) {
          toast.error(`플로우 실행 실패: ${replaceResult.message}`);
        } else {
          toast.success(`플로우 실행 완료: ${flowName}`, {
            description: `${replaceResult.summary.success}/${replaceResult.summary.total} 노드 성공`,
          });
        }

        return {
          success: replaceResult.success,
          message: replaceResult.message,
          executionTime: replaceResult.executionTime,
          data: replaceResult,
        };

      default:
        throw new Error(`지원하지 않는 실행 타이밍: ${executionTiming}`);
    }
  } catch (error) {
    logger.error("플로우 실행 오류:", error);
    const errorMessage = error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다.";
    toast.error(`플로우 실행 오류: ${errorMessage}`);

    return {
      success: false,
      message: errorMessage,
    };
  }
}

/**
 * 컨텍스트 데이터 준비
 */
function prepareContextData(context: ButtonExecutionContext): Record<string, any> {
  // 🔥 controlDataSource 자동 감지 (명시적으로 설정되지 않은 경우)
  let dataSource = context.controlDataSource;

  if (!dataSource) {
    // 1. 플로우 선택 데이터가 있으면 flow-selection
    if (context.flowSelectedData && context.flowSelectedData.length > 0) {
      dataSource = "flow-selection";
      logger.info("🔄 자동 판단: flow-selection 모드 사용", {
        flowSelectedDataLength: context.flowSelectedData.length,
      });
    }
    // 2. 플로우 스텝 전체 데이터가 있으면 flow-step-all
    else if (context.flowStepAllData && context.flowStepAllData.length > 0) {
      dataSource = "flow-step-all";
      logger.info("🔄 자동 판단: flow-step-all 모드 사용", {
        flowStepAllDataLength: context.flowStepAllData.length,
      });
    }
    // 3. 테이블 선택 데이터가 있으면 table-selection
    else if (context.selectedRowsData && context.selectedRowsData.length > 0) {
      dataSource = "table-selection";
      logger.info("🔄 자동 판단: table-selection 모드 사용", {
        selectedRowsDataLength: context.selectedRowsData.length,
      });
    }
    // 4. 테이블 전체 데이터가 있으면 table-all
    else if (context.tableAllData && context.tableAllData.length > 0) {
      dataSource = "table-all";
      logger.info("🔄 자동 판단: table-all 모드 사용", {
        tableAllDataLength: context.tableAllData.length,
      });
    }
    // 5. 폼 데이터만 있으면 form
    else {
      dataSource = "form";
      logger.info("🔄 자동 판단: form 모드 사용");
    }
  }

  const baseContext = {
    buttonId: context.buttonId,
    screenId: context.screenId,
    companyCode: context.companyCode,
    userId: context.userId,
    controlDataSource: dataSource,
  };

  // 데이터 소스에 따라 데이터 준비

  switch (dataSource) {
    case "form":
      return {
        ...baseContext,
        formData: context.formData || {},
        sourceData: [context.formData || {}], // 배열로 통일
      };

    case "table-selection":
      return {
        ...baseContext,
        formData: context.formData || {},
        selectedRowsData: context.selectedRowsData || [],
        sourceData: context.selectedRowsData || [],
      };

    case "table-all":
      return {
        ...baseContext,
        formData: context.formData || {},
        tableAllData: context.tableAllData || [],
        sourceData: context.tableAllData || [],
      };

    case "flow-selection":
      return {
        ...baseContext,
        formData: context.formData || {},
        flowSelectedData: context.flowSelectedData || [],
        sourceData: context.flowSelectedData || [],
      };

    case "flow-step-all":
      return {
        ...baseContext,
        formData: context.formData || {},
        flowStepAllData: context.flowStepAllData || [],
        flowStepId: context.flowStepId,
        sourceData: context.flowStepAllData || [],
      };

    case "both":
      // 폼 + 테이블 선택
      return {
        ...baseContext,
        formData: context.formData || {},
        selectedRowsData: context.selectedRowsData || [],
        sourceData: [
          context.formData || {},
          ...(context.selectedRowsData || []),
        ],
      };

    case "all-sources":
      // 모든 소스 결합
      return {
        ...baseContext,
        formData: context.formData || {},
        selectedRowsData: context.selectedRowsData || [],
        tableAllData: context.tableAllData || [],
        flowSelectedData: context.flowSelectedData || [],
        flowStepAllData: context.flowStepAllData || [],
        sourceData: [
          context.formData || {},
          ...(context.selectedRowsData || []),
          ...(context.tableAllData || []),
          ...(context.flowSelectedData || []),
          ...(context.flowStepAllData || []),
        ].filter(item => Object.keys(item).length > 0), // 빈 객체 제거
      };

    default:
      logger.warn(`알 수 없는 데이터 소스: ${dataSource}, 기본값(form) 사용`);
      return {
        ...baseContext,
        formData: context.formData || {},
        sourceData: [context.formData || {}],
      };
  }
}

/**
 * 플로우 실행 결과 처리
 */
export function handleFlowExecutionResult(result: FlowExecutionResult, context: ButtonExecutionContext): void {
  if (result.success) {
    logger.info("✅ 플로우 실행 성공:", result);

    // 성공 시 데이터 새로고침
    if (context.onRefresh) {
      context.onRefresh();
    }

    // 실행 결과 요약 표시
    if (result.data) {
      const { summary } = result.data;
      console.log("📊 플로우 실행 요약:", {
        전체: summary.total,
        성공: summary.success,
        실패: summary.failed,
        스킵: summary.skipped,
        실행시간: `${result.executionTime}ms`,
      });
    }
  } else {
    logger.error("❌ 플로우 실행 실패:", result);

    // 실패한 노드 정보 표시
    if (result.data) {
      const failedNodes = result.data.nodes.filter((n) => n.status === "failed");
      if (failedNodes.length > 0) {
        console.error("❌ 실패한 노드들:", failedNodes);
      }
    }
  }
}
