import { Request, Response } from "express";
import { logger } from "../utils/logger";
import { AuthenticatedRequest } from "../types/auth";
import { ApiResponse } from "../types/common";
import { DataflowService } from "../services/dataflowService";
import { EventTriggerService } from "../services/eventTriggerService";

/**
 * 테이블 관계 생성
 */
export async function createTableRelationship(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    logger.info("=== 테이블 관계 생성 시작 ===");

    const {
      diagramId,
      relationshipName,
      fromTableName,
      fromColumnName,
      toTableName,
      toColumnName,
      relationshipType,
      connectionType,
      settings,
    } = req.body;

    // 필수 필드 검증
    if (
      !relationshipName ||
      !fromTableName ||
      !fromColumnName ||
      !toTableName ||
      !toColumnName
    ) {
      const response: ApiResponse<null> = {
        success: false,
        message: "필수 필드가 누락되었습니다.",
        error: {
          code: "MISSING_REQUIRED_FIELDS",
          details:
            "relationshipName, fromTableName, fromColumnName, toTableName, toColumnName는 필수입니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    // 사용자 정보에서 회사 코드 가져오기
    const companyCode = (req.user as any)?.company_code || "*";
    const userId = (req.user as any)?.userId || "system";

    const dataflowService = new DataflowService();
    const relationship = await dataflowService.createTableRelationship({
      diagramId: diagramId ? parseInt(diagramId) : undefined,
      relationshipName,
      fromTableName,
      fromColumnName,
      toTableName,
      toColumnName,
      relationshipType: relationshipType || "one-to-one",
      connectionType: connectionType || "simple-key",
      companyCode,
      settings: settings || {},
      createdBy: userId,
    });

    logger.info(`테이블 관계 생성 완료: ${relationship.relationship_id}`);

    const response: ApiResponse<any> = {
      success: true,
      message: "테이블 관계가 성공적으로 생성되었습니다.",
      data: relationship,
    };

    res.status(201).json(response);
  } catch (error) {
    logger.error("테이블 관계 생성 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "테이블 관계 생성 중 오류가 발생했습니다.",
      error: {
        code: "TABLE_RELATIONSHIP_CREATE_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

/**
 * 테이블 관계 목록 조회 (회사별)
 */
export async function getTableRelationships(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    logger.info("=== 테이블 관계 목록 조회 시작 ===");

    // 사용자 정보에서 회사 코드 가져오기
    const companyCode = (req.user as any)?.company_code || "*";

    const dataflowService = new DataflowService();
    const relationships =
      await dataflowService.getTableRelationships(companyCode);

    logger.info(`테이블 관계 목록 조회 완료: ${relationships.length}개`);

    const response: ApiResponse<any[]> = {
      success: true,
      message: "테이블 관계 목록을 성공적으로 조회했습니다.",
      data: relationships,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("테이블 관계 목록 조회 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "테이블 관계 목록 조회 중 오류가 발생했습니다.",
      error: {
        code: "TABLE_RELATIONSHIPS_LIST_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

/**
 * 테이블 관계 수정
 */
export async function updateTableRelationship(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    logger.info("=== 테이블 관계 수정 시작 ===");

    const { relationshipId } = req.params;
    const updateData = req.body;

    if (!relationshipId) {
      const response: ApiResponse<null> = {
        success: false,
        message: "관계 ID가 필요합니다.",
        error: {
          code: "MISSING_RELATIONSHIP_ID",
          details: "relationshipId 파라미터가 누락되었습니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    // 사용자 정보에서 회사 코드와 사용자 ID 가져오기
    const companyCode = (req.user as any)?.company_code || "*";
    const userId = (req.user as any)?.userId || "system";

    const dataflowService = new DataflowService();
    const relationship = await dataflowService.updateTableRelationship(
      parseInt(relationshipId),
      {
        ...updateData,
        updatedBy: userId,
      },
      companyCode
    );

    if (!relationship) {
      const response: ApiResponse<null> = {
        success: false,
        message: "테이블 관계를 찾을 수 없습니다.",
        error: {
          code: "TABLE_RELATIONSHIP_NOT_FOUND",
          details: `관계 ID ${relationshipId}를 찾을 수 없습니다.`,
        },
      };
      res.status(404).json(response);
      return;
    }

    logger.info(`테이블 관계 수정 완료: ${relationshipId}`);

    const response: ApiResponse<any> = {
      success: true,
      message: "테이블 관계가 성공적으로 수정되었습니다.",
      data: relationship,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("테이블 관계 수정 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "테이블 관계 수정 중 오류가 발생했습니다.",
      error: {
        code: "TABLE_RELATIONSHIP_UPDATE_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

/**
 * 테이블 관계 삭제
 */
export async function deleteTableRelationship(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    logger.info("=== 테이블 관계 삭제 시작 ===");

    const { relationshipId } = req.params;

    if (!relationshipId) {
      const response: ApiResponse<null> = {
        success: false,
        message: "관계 ID가 필요합니다.",
        error: {
          code: "MISSING_RELATIONSHIP_ID",
          details: "relationshipId 파라미터가 누락되었습니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    // 사용자 정보에서 회사 코드 가져오기
    const companyCode = (req.user as any)?.company_code || "*";

    const dataflowService = new DataflowService();
    const success = await dataflowService.deleteTableRelationship(
      parseInt(relationshipId),
      companyCode
    );

    if (!success) {
      const response: ApiResponse<null> = {
        success: false,
        message: "테이블 관계를 찾을 수 없습니다.",
        error: {
          code: "TABLE_RELATIONSHIP_NOT_FOUND",
          details: `관계 ID ${relationshipId}를 찾을 수 없습니다.`,
        },
      };
      res.status(404).json(response);
      return;
    }

    logger.info(`테이블 관계 삭제 완료: ${relationshipId}`);

    const response: ApiResponse<null> = {
      success: true,
      message: "테이블 관계가 성공적으로 삭제되었습니다.",
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("테이블 관계 삭제 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "테이블 관계 삭제 중 오류가 발생했습니다.",
      error: {
        code: "TABLE_RELATIONSHIP_DELETE_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

/**
 * 특정 테이블 관계 조회
 */
export async function getTableRelationship(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    logger.info("=== 테이블 관계 조회 시작 ===");

    const { relationshipId } = req.params;

    if (!relationshipId) {
      const response: ApiResponse<null> = {
        success: false,
        message: "관계 ID가 필요합니다.",
        error: {
          code: "MISSING_RELATIONSHIP_ID",
          details: "relationshipId 파라미터가 누락되었습니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    // 사용자 정보에서 회사 코드 가져오기
    const companyCode = (req.user as any)?.company_code || "*";

    const dataflowService = new DataflowService();
    const relationship = await dataflowService.getTableRelationship(
      parseInt(relationshipId),
      companyCode
    );

    if (!relationship) {
      const response: ApiResponse<null> = {
        success: false,
        message: "테이블 관계를 찾을 수 없습니다.",
        error: {
          code: "TABLE_RELATIONSHIP_NOT_FOUND",
          details: `관계 ID ${relationshipId}를 찾을 수 없습니다.`,
        },
      };
      res.status(404).json(response);
      return;
    }

    logger.info(`테이블 관계 조회 완료: ${relationshipId}`);

    const response: ApiResponse<any> = {
      success: true,
      message: "테이블 관계를 성공적으로 조회했습니다.",
      data: relationship,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("테이블 관계 조회 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "테이블 관계 조회 중 오류가 발생했습니다.",
      error: {
        code: "TABLE_RELATIONSHIP_GET_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

// ==================== 데이터 연결 관리 API ====================

/**
 * 데이터 관계 연결 생성
 */
export async function createDataLink(
  req: Request,
  res: Response
): Promise<void> {
  try {
    const {
      relationshipId,
      fromTableName,
      fromColumnName,
      toTableName,
      toColumnName,
      connectionType,
      bridgeData,
    } = req.body;

    // 필수 필드 검증
    if (
      !relationshipId ||
      !fromTableName ||
      !fromColumnName ||
      !toTableName ||
      !toColumnName ||
      !connectionType
    ) {
      const response: ApiResponse<null> = {
        success: false,
        message: "필수 필드가 누락되었습니다.",
        error: {
          code: "MISSING_REQUIRED_FIELDS",
          details:
            "필수 필드: relationshipId, fromTableName, fromColumnName, toTableName, toColumnName, connectionType",
        },
      };
      res.status(400).json(response);
      return;
    }

    const userInfo = (req as any).user;
    const companyCode = userInfo?.company_code || "*";
    const createdBy = userInfo?.userId || "system";

    const dataflowService = new DataflowService();
    const bridge = await dataflowService.createDataLink({
      relationshipId,
      fromTableName,
      fromColumnName,
      toTableName,
      toColumnName,
      connectionType,
      companyCode,
      bridgeData,
      createdBy,
    });

    const response: ApiResponse<typeof bridge> = {
      success: true,
      message: "데이터 연결이 성공적으로 생성되었습니다.",
      data: bridge,
    };

    res.status(201).json(response);
  } catch (error) {
    logger.error("데이터 연결 생성 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "데이터 연결 생성 중 오류가 발생했습니다.",
      error: {
        code: "DATA_LINK_CREATE_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

/**
 * 관계별 연결된 데이터 조회
 */
export async function getLinkedDataByRelationship(
  req: Request,
  res: Response
): Promise<void> {
  try {
    const relationshipId = parseInt(req.params.relationshipId);

    if (!relationshipId || isNaN(relationshipId)) {
      const response: ApiResponse<null> = {
        success: false,
        message: "유효하지 않은 관계 ID입니다.",
        error: {
          code: "INVALID_RELATIONSHIP_ID",
          details: "관계 ID는 숫자여야 합니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    const userInfo = (req as any).user;
    const companyCode = userInfo?.company_code || "*";

    const dataflowService = new DataflowService();
    const linkedData = await dataflowService.getLinkedDataByRelationship(
      relationshipId,
      companyCode
    );

    const response: ApiResponse<typeof linkedData> = {
      success: true,
      message: "연결된 데이터를 성공적으로 조회했습니다.",
      data: linkedData,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("연결된 데이터 조회 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "연결된 데이터 조회 중 오류가 발생했습니다.",
      error: {
        code: "LINKED_DATA_GET_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

/**
 * 데이터 연결 삭제
 */
export async function deleteDataLink(
  req: Request,
  res: Response
): Promise<void> {
  try {
    const bridgeId = parseInt(req.params.bridgeId);

    if (!bridgeId || isNaN(bridgeId)) {
      const response: ApiResponse<null> = {
        success: false,
        message: "유효하지 않은 Bridge ID입니다.",
        error: {
          code: "INVALID_BRIDGE_ID",
          details: "Bridge ID는 숫자여야 합니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    const userInfo = (req as any).user;
    const companyCode = userInfo?.company_code || "*";
    const deletedBy = userInfo?.userId || "system";

    const dataflowService = new DataflowService();
    await dataflowService.deleteDataLink(bridgeId, companyCode, deletedBy);

    const response: ApiResponse<null> = {
      success: true,
      message: "데이터 연결이 성공적으로 삭제되었습니다.",
      data: null,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("데이터 연결 삭제 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "데이터 연결 삭제 중 오류가 발생했습니다.",
      error: {
        code: "DATA_LINK_DELETE_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

// ==================== 테이블 데이터 조회 ====================

/**
 * 테이블 실제 데이터 조회 (페이징)
 * GET /api/dataflow/table-data/:tableName
 */
export async function getTableData(req: Request, res: Response): Promise<void> {
  try {
    const { tableName } = req.params;
    const {
      page = "1",
      limit = "10",
      search = "",
      searchColumn = "",
    } = req.query;

    if (!tableName) {
      const response: ApiResponse<null> = {
        success: false,
        message: "테이블명이 필요합니다.",
        error: {
          code: "MISSING_TABLE_NAME",
          details: "테이블명을 제공해주세요.",
        },
      };
      res.status(400).json(response);
      return;
    }

    const pageNum = parseInt(page as string) || 1;
    const limitNum = parseInt(limit as string) || 10;
    const userInfo = (req as any).user;
    const companyCode = userInfo?.company_code || "*";

    const dataflowService = new DataflowService();
    const result = await dataflowService.getTableData(
      tableName,
      pageNum,
      limitNum,
      search as string,
      searchColumn as string,
      companyCode
    );

    const response: ApiResponse<typeof result> = {
      success: true,
      message: "테이블 데이터를 성공적으로 조회했습니다.",
      data: result,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("테이블 데이터 조회 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "테이블 데이터 조회 중 오류가 발생했습니다.",
      error: {
        code: "TABLE_DATA_GET_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

/**
 * 관계도 그룹 목록 조회 (관계도 이름별로 그룹화)
 */
export async function getDataFlowDiagrams(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    logger.info("=== 관계도 목록 조회 시작 ===");

    const { page = 1, size = 20, searchTerm = "" } = req.query;

    // 사용자 정보에서 회사 코드 가져오기
    const companyCode = (req.user as any)?.company_code || "*";

    const pageNum = parseInt(page as string, 10);
    const sizeNum = parseInt(size as string, 10);

    const dataflowService = new DataflowService();
    const result = await dataflowService.getDataFlowDiagrams(
      companyCode,
      pageNum,
      sizeNum,
      searchTerm as string
    );

    logger.info(`관계도 목록 조회 완료: ${result.total}개`);

    const response: ApiResponse<typeof result> = {
      success: true,
      message: "관계도 목록을 성공적으로 조회했습니다.",
      data: result,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("관계도 목록 조회 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "관계도 목록 조회 중 오류가 발생했습니다.",
      error: {
        code: "DATAFLOW_DIAGRAMS_LIST_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

/**
 * 특정 관계도의 모든 관계 조회
 */
export async function getDiagramRelationships(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    logger.info("=== 관계도 관계 조회 시작 ===");

    const { diagramName } = req.params;

    if (!diagramName) {
      const response: ApiResponse<null> = {
        success: false,
        message: "관계도 이름이 필요합니다.",
        error: {
          code: "MISSING_DIAGRAM_NAME",
          details: "diagramName 파라미터가 필요합니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    // 사용자 정보에서 회사 코드 가져오기
    const companyCode = (req.user as any)?.company_code || "*";

    const dataflowService = new DataflowService();
    const relationships = await dataflowService.getDiagramRelationships(
      companyCode,
      decodeURIComponent(diagramName)
    );

    logger.info(`관계도 관계 조회 완료: ${relationships.length}개`);

    const response: ApiResponse<any[]> = {
      success: true,
      message: "관계도 관계를 성공적으로 조회했습니다.",
      data: relationships,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("관계도 관계 조회 중 오류 발생:", error);

    const response: ApiResponse<null> = {
      success: false,
      message: "관계도 관계 조회 중 오류가 발생했습니다.",
      error: {
        code: "DIAGRAM_RELATIONSHIPS_GET_ERROR",
        details: error instanceof Error ? error.message : "Unknown error",
      },
    };

    res.status(500).json(response);
  }
}

/**
 * 관계도 복사
 */
export async function copyDiagram(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { diagramName } = req.params;
    const companyCode = (req.user as any)?.company_code || "*";

    if (!diagramName) {
      const response: ApiResponse<null> = {
        success: false,
        message: "관계도 이름이 필요합니다.",
        error: {
          code: "MISSING_DIAGRAM_NAME",
          details: "diagramName 파라미터가 필요합니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    const dataflowService = new DataflowService();
    const newDiagramName = await dataflowService.copyDiagram(
      companyCode,
      decodeURIComponent(diagramName)
    );

    const response: ApiResponse<{ newDiagramName: string }> = {
      success: true,
      message: "관계도가 성공적으로 복사되었습니다.",
      data: { newDiagramName },
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("관계도 복사 실패:", error);
    const response: ApiResponse<null> = {
      success: false,
      message: "관계도 복사에 실패했습니다.",
      error: {
        code: "DIAGRAM_COPY_FAILED",
        details:
          error instanceof Error
            ? error.message
            : "알 수 없는 오류가 발생했습니다.",
      },
    };
    res.status(500).json(response);
  }
}

/**
 * 관계도 삭제
 */
export async function deleteDiagram(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { diagramName } = req.params;
    const companyCode = (req.user as any)?.company_code || "*";

    if (!diagramName) {
      const response: ApiResponse<null> = {
        success: false,
        message: "관계도 이름이 필요합니다.",
        error: {
          code: "MISSING_DIAGRAM_NAME",
          details: "diagramName 파라미터가 필요합니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    const dataflowService = new DataflowService();
    const deletedCount = await dataflowService.deleteDiagram(
      companyCode,
      decodeURIComponent(diagramName)
    );

    const response: ApiResponse<{ deletedCount: number }> = {
      success: true,
      message: "관계도가 성공적으로 삭제되었습니다.",
      data: { deletedCount },
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("관계도 삭제 실패:", error);
    const response: ApiResponse<null> = {
      success: false,
      message: "관계도 삭제에 실패했습니다.",
      error: {
        code: "DIAGRAM_DELETE_FAILED",
        details:
          error instanceof Error
            ? error.message
            : "알 수 없는 오류가 발생했습니다.",
      },
    };
    res.status(500).json(response);
  }
}

/**
 * diagram_id로 관계도 관계 조회
 */
export async function getDiagramRelationshipsByDiagramId(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { diagramId } = req.params;
    const companyCode = (req.user as any)?.company_code || "*";

    if (!diagramId) {
      const response: ApiResponse<null> = {
        success: false,
        message: "관계도 ID가 필요합니다.",
        error: {
          code: "MISSING_DIAGRAM_ID",
          details: "diagramId 파라미터가 필요합니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    const dataflowService = new DataflowService();
    const relationships =
      await dataflowService.getDiagramRelationshipsByDiagramId(
        companyCode,
        parseInt(diagramId)
      );

    const response: ApiResponse<any[]> = {
      success: true,
      message: "관계도 관계 목록을 성공적으로 조회했습니다.",
      data: relationships,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("관계도 관계 조회 실패:", error);
    const response: ApiResponse<null> = {
      success: false,
      message: "관계도 관계 조회에 실패했습니다.",
      error: {
        code: "DIAGRAM_RELATIONSHIPS_FETCH_FAILED",
        details:
          error instanceof Error
            ? error.message
            : "알 수 없는 오류가 발생했습니다.",
      },
    };
    res.status(500).json(response);
  }
}

/**
 * relationship_id로 관계도 관계 조회 (하위 호환성 유지)
 */
export async function getDiagramRelationshipsByRelationshipId(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const { relationshipId } = req.params;
    const companyCode = (req.user as any)?.company_code || "*";

    if (!relationshipId) {
      const response: ApiResponse<null> = {
        success: false,
        message: "관계 ID가 필요합니다.",
        error: {
          code: "MISSING_RELATIONSHIP_ID",
          details: "relationshipId 파라미터가 필요합니다.",
        },
      };
      res.status(400).json(response);
      return;
    }

    const dataflowService = new DataflowService();
    const relationships =
      await dataflowService.getDiagramRelationshipsByRelationshipId(
        companyCode,
        parseInt(relationshipId)
      );

    const response: ApiResponse<any[]> = {
      success: true,
      message: "관계도 관계 목록을 성공적으로 조회했습니다.",
      data: relationships,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("관계도 관계 조회 실패:", error);
    const response: ApiResponse<null> = {
      success: false,
      message: "관계도 관계 조회에 실패했습니다.",
      error: {
        code: "DIAGRAM_RELATIONSHIPS_FETCH_FAILED",
        details:
          error instanceof Error
            ? error.message
            : "알 수 없는 오류가 발생했습니다.",
      },
    };
    res.status(500).json(response);
  }
}
