/**
 * 🔥 버튼 데이터플로우 컨트롤러
 *
 * 성능 최적화를 위한 API 엔드포인트:
 * 1. 즉시 응답 패턴
 * 2. 백그라운드 작업 처리
 * 3. 캐시 활용
 */

import { Request, Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import EventTriggerService from "../services/eventTriggerService";
import * as dataflowDiagramService from "../services/dataflowDiagramService";
import logger from "../utils/logger";

/**
 * 🔥 버튼 설정 조회 (캐시 지원)
 */
export async function getButtonDataflowConfig(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { buttonId } = req.params;
    const companyCode = req.user?.companyCode;

    if (!buttonId) {
      res.status(400).json({
        success: false,
        message: "버튼 ID가 필요합니다.",
      });
      return;
    }

    // 버튼별 제어관리 설정 조회
    // TODO: 실제 버튼 설정 테이블에서 조회
    // 현재는 mock 데이터 반환
    const mockConfig = {
      controlMode: "simple",
      selectedDiagramId: 1,
      selectedRelationshipId: "rel-123",
      executionOptions: {
        rollbackOnError: true,
        enableLogging: true,
        asyncExecution: true,
      },
    };

    res.json({
      success: true,
      data: mockConfig,
    });
  } catch (error) {
    logger.error("Failed to get button dataflow config:", error);
    res.status(500).json({
      success: false,
      message: "버튼 설정 조회 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 🔥 버튼 설정 업데이트
 */
export async function updateButtonDataflowConfig(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { buttonId } = req.params;
    const config = req.body;
    const companyCode = req.user?.companyCode;

    if (!buttonId) {
      res.status(400).json({
        success: false,
        message: "버튼 ID가 필요합니다.",
      });
      return;
    }

    // TODO: 실제 버튼 설정 테이블에 저장
    logger.info(`Button dataflow config updated: ${buttonId}`, config);

    res.json({
      success: true,
      message: "버튼 설정이 업데이트되었습니다.",
    });
  } catch (error) {
    logger.error("Failed to update button dataflow config:", error);
    res.status(500).json({
      success: false,
      message: "버튼 설정 업데이트 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 🔥 사용 가능한 관계도 목록 조회
 */
export async function getAvailableDiagrams(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const companyCode = req.user?.companyCode;

    if (!companyCode) {
      res.status(400).json({
        success: false,
        message: "회사 코드가 필요합니다.",
      });
      return;
    }

    const diagramsResult = await dataflowDiagramService.getDataflowDiagrams(
      companyCode,
      1,
      100
    );
    const diagrams = diagramsResult.diagrams;

    res.json({
      success: true,
      data: diagrams,
    });
  } catch (error) {
    logger.error("Failed to get available diagrams:", error);
    res.status(500).json({
      success: false,
      message: "관계도 목록 조회 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 🔥 특정 관계도의 관계 목록 조회
 */
export async function getDiagramRelationships(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { diagramId } = req.params;
    const companyCode = req.user?.companyCode;

    if (!diagramId || !companyCode) {
      res.status(400).json({
        success: false,
        message: "관계도 ID와 회사 코드가 필요합니다.",
      });
      return;
    }

    const diagram = await dataflowDiagramService.getDataflowDiagramById(
      parseInt(diagramId),
      companyCode
    );

    if (!diagram) {
      res.status(404).json({
        success: false,
        message: "관계도를 찾을 수 없습니다.",
      });
      return;
    }

    const relationships = (diagram.relationships as any)?.relationships || [];

    console.log("🔍 백엔드 - 관계도 데이터:", {
      diagramId: diagram.diagram_id,
      diagramName: diagram.diagram_name,
      relationshipsRaw: diagram.relationships,
      relationshipsArray: relationships,
      relationshipsCount: relationships.length,
    });

    // 각 관계의 구조도 로깅
    relationships.forEach((rel: any, index: number) => {
      console.log(`🔍 백엔드 - 관계 ${index + 1}:`, rel);
    });

    res.json({
      success: true,
      data: relationships,
    });
  } catch (error) {
    logger.error("Failed to get diagram relationships:", error);
    res.status(500).json({
      success: false,
      message: "관계 목록 조회 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 🔥 관계 미리보기 정보 조회
 */
export async function getRelationshipPreview(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { diagramId, relationshipId } = req.params;
    const companyCode = req.user?.companyCode;

    if (!diagramId || !relationshipId || !companyCode) {
      res.status(400).json({
        success: false,
        message: "관계도 ID, 관계 ID, 회사 코드가 필요합니다.",
      });
      return;
    }

    const diagram = await dataflowDiagramService.getDataflowDiagramById(
      parseInt(diagramId),
      companyCode
    );

    if (!diagram) {
      res.status(404).json({
        success: false,
        message: "관계도를 찾을 수 없습니다.",
      });
      return;
    }

    // 관계 정보 찾기
    console.log("🔍 관계 미리보기 요청:", {
      diagramId,
      relationshipId,
      diagramRelationships: diagram.relationships,
      relationshipsArray: (diagram.relationships as any)?.relationships,
    });

    const relationships = (diagram.relationships as any)?.relationships || [];
    console.log(
      "🔍 사용 가능한 관계 목록:",
      relationships.map((rel: any) => ({
        id: rel.id,
        name: rel.relationshipName || rel.name, // relationshipName 사용
        sourceTable: rel.fromTable || rel.sourceTable, // fromTable 사용
        targetTable: rel.toTable || rel.targetTable, // toTable 사용
        originalData: rel, // 디버깅용
      }))
    );

    const relationship = relationships.find(
      (rel: any) => rel.id === relationshipId
    );

    console.log("🔍 찾은 관계:", relationship);

    if (!relationship) {
      console.log("❌ 관계를 찾을 수 없음:", {
        requestedId: relationshipId,
        availableIds: relationships.map((rel: any) => rel.id),
      });

      // 🔧 임시 해결책: 첫 번째 관계를 사용하거나 기본 응답 반환
      if (relationships.length > 0) {
        console.log("🔧 첫 번째 관계를 대신 사용:", relationships[0].id);

        const fallbackRelationship = relationships[0];

        console.log("🔍 fallback 관계 선택:", fallbackRelationship);
        console.log("🔍 diagram.control 전체 구조:", diagram.control);
        console.log("🔍 diagram.plan 전체 구조:", diagram.plan);

        const fallbackControl = Array.isArray(diagram.control)
          ? diagram.control.find((c: any) => c.id === fallbackRelationship.id)
          : null;
        const fallbackPlan = Array.isArray(diagram.plan)
          ? diagram.plan.find((p: any) => p.id === fallbackRelationship.id)
          : null;

        console.log("🔍 찾은 fallback control:", fallbackControl);
        console.log("🔍 찾은 fallback plan:", fallbackPlan);

        const fallbackPreviewData = {
          relationship: fallbackRelationship,
          control: fallbackControl,
          plan: fallbackPlan,
          conditionsCount: (fallbackControl as any)?.conditions?.length || 0,
          actionsCount: (fallbackPlan as any)?.actions?.length || 0,
        };

        console.log("🔍 최종 fallback 응답 데이터:", fallbackPreviewData);

        res.json({
          success: true,
          data: fallbackPreviewData,
        });
        return;
      }

      res.status(404).json({
        success: false,
        message: `관계를 찾을 수 없습니다. 요청된 ID: ${relationshipId}, 사용 가능한 ID: ${relationships.map((rel: any) => rel.id).join(", ")}`,
      });
      return;
    }

    // 제어 및 계획 정보 추출
    const control = Array.isArray(diagram.control)
      ? diagram.control.find((c: any) => c.id === relationshipId)
      : null;

    const plan = Array.isArray(diagram.plan)
      ? diagram.plan.find((p: any) => p.id === relationshipId)
      : null;

    const previewData = {
      relationship,
      control,
      plan,
      conditionsCount: (control as any)?.conditions?.length || 0,
      actionsCount: (plan as any)?.actions?.length || 0,
    };

    res.json({
      success: true,
      data: previewData,
    });
  } catch (error) {
    logger.error("Failed to get relationship preview:", error);
    res.status(500).json({
      success: false,
      message: "관계 미리보기 조회 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 🔥 최적화된 버튼 실행 (즉시 응답)
 */
export async function executeOptimizedButton(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const {
      buttonId,
      actionType,
      buttonConfig,
      contextData,
      timing = "after",
    } = req.body;
    const companyCode = req.user?.companyCode;

    if (!buttonId || !actionType || !companyCode) {
      res.status(400).json({
        success: false,
        message: "필수 파라미터가 누락되었습니다.",
      });
      return;
    }

    const startTime = Date.now();

    // 🔥 타이밍에 따른 즉시 응답 처리
    if (timing === "after") {
      // After: 기존 액션 즉시 실행 + 백그라운드 제어관리
      const immediateResult = await executeOriginalAction(
        actionType,
        contextData
      );

      // 제어관리는 백그라운드에서 처리 (실제로는 큐에 추가)
      const jobId = `job_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;

      // TODO: 실제 작업 큐에 추가
      processDataflowInBackground(
        jobId,
        buttonConfig,
        contextData,
        companyCode,
        "normal"
      );

      const responseTime = Date.now() - startTime;
      logger.info(`Button executed (after): ${responseTime}ms`);

      res.json({
        success: true,
        data: {
          jobId,
          immediateResult,
          isBackground: true,
          timing: "after",
          responseTime,
        },
      });
    } else if (timing === "before") {
      // Before: 간단한 검증 후 기존 액션
      const isSimpleValidation = checkIfSimpleValidation(buttonConfig);

      if (isSimpleValidation) {
        // 간단한 검증: 즉시 처리
        const validationResult = await validateQuickly(
          buttonConfig,
          contextData
        );

        if (!validationResult.success) {
          res.json({
            success: true,
            data: {
              jobId: "validation_failed",
              immediateResult: validationResult,
              timing: "before",
            },
          });
          return;
        }

        // 검증 통과 시 기존 액션 실행
        const actionResult = await executeOriginalAction(
          actionType,
          contextData
        );

        const responseTime = Date.now() - startTime;
        logger.info(`Button executed (before-simple): ${responseTime}ms`);

        res.json({
          success: true,
          data: {
            jobId: "immediate",
            immediateResult: actionResult,
            timing: "before",
            responseTime,
          },
        });
      } else {
        // 복잡한 검증: 백그라운드 처리
        const jobId = `job_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;

        // TODO: 실제 작업 큐에 추가 (높은 우선순위)
        processDataflowInBackground(
          jobId,
          buttonConfig,
          contextData,
          companyCode,
          "high"
        );

        res.json({
          success: true,
          data: {
            jobId,
            immediateResult: {
              success: true,
              message: "검증 중입니다. 잠시만 기다려주세요.",
              processing: true,
            },
            isBackground: true,
            timing: "before",
          },
        });
      }
    } else if (timing === "replace") {
      // Replace: 제어관리만 실행
      const isSimpleControl = checkIfSimpleControl(buttonConfig);

      if (isSimpleControl) {
        // 간단한 제어: 즉시 실행
        const result = await executeSimpleDataflowAction(
          buttonConfig,
          contextData,
          companyCode
        );

        const responseTime = Date.now() - startTime;
        logger.info(`Button executed (replace-simple): ${responseTime}ms`);

        res.json({
          success: true,
          data: {
            jobId: "immediate",
            immediateResult: result,
            timing: "replace",
            responseTime,
          },
        });
      } else {
        // 복잡한 제어: 백그라운드 실행
        const jobId = `job_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;

        // TODO: 실제 작업 큐에 추가
        processDataflowInBackground(
          jobId,
          buttonConfig,
          contextData,
          companyCode,
          "normal"
        );

        res.json({
          success: true,
          data: {
            jobId,
            immediateResult: {
              success: true,
              message: "사용자 정의 작업을 처리 중입니다...",
              processing: true,
            },
            isBackground: true,
            timing: "replace",
          },
        });
      }
    }
  } catch (error) {
    logger.error("Failed to execute optimized button:", error);
    res.status(500).json({
      success: false,
      message: "버튼 실행 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 🔥 간단한 데이터플로우 즉시 실행
 */
export async function executeSimpleDataflow(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { config, contextData } = req.body;
    const companyCode = req.user?.companyCode;

    if (!companyCode) {
      res.status(400).json({
        success: false,
        message: "회사 코드가 필요합니다.",
      });
      return;
    }

    const result = await executeSimpleDataflowAction(
      config,
      contextData,
      companyCode
    );

    res.json({
      success: true,
      data: result,
    });
  } catch (error) {
    logger.error("Failed to execute simple dataflow:", error);
    res.status(500).json({
      success: false,
      message: "간단한 제어관리 실행 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 🔥 백그라운드 작업 상태 조회
 */
export async function getJobStatus(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { jobId } = req.params;

    // TODO: 실제 작업 큐에서 상태 조회
    // 현재는 mock 응답
    const mockStatus = {
      status: "completed",
      result: {
        success: true,
        executedActions: 2,
        message: "백그라운드 처리가 완료되었습니다.",
      },
      progress: 100,
    };

    res.json({
      success: true,
      data: mockStatus,
    });
  } catch (error) {
    logger.error("Failed to get job status:", error);
    res.status(500).json({
      success: false,
      message: "작업 상태 조회 중 오류가 발생했습니다.",
    });
  }
}

// ============================================================================
// 🔥 헬퍼 함수들
// ============================================================================

/**
 * 기존 액션 실행 (mock)
 */
async function executeOriginalAction(
  actionType: string,
  contextData: Record<string, any>
): Promise<any> {
  // 간단한 지연 시뮬레이션
  await new Promise((resolve) => setTimeout(resolve, 50));

  return {
    success: true,
    message: `${actionType} 액션이 완료되었습니다.`,
    actionType,
    timestamp: new Date().toISOString(),
    data: contextData,
  };
}

/**
 * 간단한 검증인지 확인
 */
function checkIfSimpleValidation(buttonConfig: any): boolean {
  if (buttonConfig?.dataflowConfig?.controlMode !== "advanced") {
    return true;
  }

  const conditions =
    buttonConfig?.dataflowConfig?.directControl?.conditions || [];
  return (
    conditions.length <= 5 &&
    conditions.every(
      (c: any) =>
        c.type === "condition" &&
        ["=", "!=", ">", "<", ">=", "<="].includes(c.operator || "")
    )
  );
}

/**
 * 간단한 제어관리인지 확인
 */
function checkIfSimpleControl(buttonConfig: any): boolean {
  if (buttonConfig?.dataflowConfig?.controlMode === "simple") {
    return true;
  }

  const actions = buttonConfig?.dataflowConfig?.directControl?.actions || [];
  const conditions =
    buttonConfig?.dataflowConfig?.directControl?.conditions || [];

  return actions.length <= 3 && conditions.length <= 5;
}

/**
 * 빠른 검증 실행
 */
async function validateQuickly(
  buttonConfig: any,
  contextData: Record<string, any>
): Promise<any> {
  // 간단한 mock 검증
  await new Promise((resolve) => setTimeout(resolve, 10));

  return {
    success: true,
    message: "검증이 완료되었습니다.",
  };
}

/**
 * 간단한 데이터플로우 실행
 */
async function executeSimpleDataflowAction(
  config: any,
  contextData: Record<string, any>,
  companyCode: string
): Promise<any> {
  try {
    // 실제로는 EventTriggerService 사용
    const result = await EventTriggerService.executeEventTriggers(
      "insert", // TODO: 동적으로 결정
      "test_table", // TODO: 설정에서 가져오기
      contextData,
      companyCode
    );

    return {
      success: true,
      executedActions: result.length,
      message: `${result.length}개의 액션이 실행되었습니다.`,
      results: result,
    };
  } catch (error) {
    logger.error("Simple dataflow execution failed:", error);
    throw error;
  }
}

/**
 * 백그라운드에서 데이터플로우 처리 (비동기)
 */
function processDataflowInBackground(
  jobId: string,
  buttonConfig: any,
  contextData: Record<string, any>,
  companyCode: string,
  priority: string = "normal"
): void {
  // 실제로는 작업 큐에 추가
  // 여기서는 간단한 setTimeout으로 시뮬레이션
  setTimeout(async () => {
    try {
      logger.info(`Background job started: ${jobId}`);

      // 실제 제어관리 로직 실행
      const result = await executeSimpleDataflowAction(
        buttonConfig.dataflowConfig,
        contextData,
        companyCode
      );

      logger.info(`Background job completed: ${jobId}`, result);

      // 실제로는 WebSocket이나 polling으로 클라이언트에 알림
    } catch (error) {
      logger.error(`Background job failed: ${jobId}`, error);
    }
  }, 1000); // 1초 후 실행 시뮬레이션
}

/**
 * 🔥 전체 관계 목록 조회 (버튼 제어용)
 */
export async function getAllRelationships(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const companyCode = req.user?.companyCode || "*";

    logger.info(`전체 관계 목록 조회 요청 - companyCode: ${companyCode}`);

    // 모든 관계도에서 관계 목록을 가져옴
    const allRelationships = await dataflowDiagramService.getAllRelationshipsForButtonControl(companyCode);

    logger.info(`전체 관계 ${allRelationships.length}개 조회 완료`);

    res.json({
      success: true,
      data: allRelationships,
      message: `전체 관계 ${allRelationships.length}개 조회 완료`,
    });
  } catch (error) {
    logger.error("전체 관계 목록 조회 실패:", error);
    res.status(500).json({
      success: false,
      message: error instanceof Error ? error.message : "전체 관계 목록 조회 실패",
      errorCode: "GET_ALL_RELATIONSHIPS_ERROR",
    });
  }
}

/**
 * 두 테이블 간의 조인 관계 조회 (마스터-디테일 저장용)
 */
export async function getJoinRelationship(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { mainTable, detailTable } = req.params;
    const companyCode = req.user?.companyCode || "*";

    if (!mainTable || !detailTable) {
      res.status(400).json({
        success: false,
        message: "메인 테이블과 디테일 테이블이 필요합니다.",
      });
      return;
    }

    // DataflowService에서 조인 관계 조회
    const { DataflowService } = await import("../services/dataflowService");
    const dataflowService = new DataflowService();
    
    const result = await dataflowService.getJoinRelationshipBetweenTables(
      mainTable,
      detailTable,
      companyCode
    );

    res.json({
      success: true,
      data: result,
    });
  } catch (error) {
    logger.error("조인 관계 조회 실패:", error);
    res.status(500).json({
      success: false,
      message: error instanceof Error ? error.message : "조인 관계 조회 실패",
    });
  }
}
