import { query, queryOne, transaction } from "../database/db";
import { logger } from "../utils/logger";

// 테이블 관계 생성 데이터 타입
interface CreateTableRelationshipData {
  diagramId?: number; // 기존 관계도에 추가하는 경우
  relationshipName: string;
  fromTableName: string;
  fromColumnName: string;
  toTableName: string;
  toColumnName: string;
  relationshipType: string;
  connectionType: string;
  companyCode: string;
  settings: any;
  createdBy: string;
}

// 테이블 관계 수정 데이터 타입
interface UpdateTableRelationshipData {
  relationshipName?: string;
  fromTableName?: string;
  fromColumnName?: string;
  toTableName?: string;
  toColumnName?: string;
  relationshipType?: string;
  connectionType?: string;
  settings?: any;
  updatedBy: string;
}

export class DataflowService {
  /**
   * 테이블 관계 생성
   */
  async createTableRelationship(data: CreateTableRelationshipData) {
    try {
      logger.info("DataflowService: 테이블 관계 생성 시작", data);

      // diagram_id 결정 로직
      let diagramId = data.diagramId;

      if (!diagramId) {
        // 새로운 관계도인 경우, 새로운 diagram_id 생성
        // 현재 최대 diagram_id + 1
        const maxDiagramId = await queryOne<{ diagram_id: number }>(
          `SELECT diagram_id FROM table_relationships 
           WHERE company_code = $1 
           ORDER BY diagram_id DESC 
           LIMIT 1`,
          [data.companyCode]
        );

        diagramId = (maxDiagramId?.diagram_id || 0) + 1;
      }

      // 중복 관계 확인 (같은 diagram_id 내에서)
      const existingRelationship = await queryOne(
        `SELECT * FROM table_relationships 
         WHERE diagram_id = $1 
           AND from_table_name = $2 
           AND from_column_name = $3 
           AND to_table_name = $4 
           AND to_column_name = $5 
           AND company_code = $6 
           AND is_active = 'Y'`,
        [
          diagramId,
          data.fromTableName,
          data.fromColumnName,
          data.toTableName,
          data.toColumnName,
          data.companyCode,
        ]
      );

      if (existingRelationship) {
        throw new Error(
          `이미 존재하는 관계입니다: ${data.fromTableName}.${data.fromColumnName} → ${data.toTableName}.${data.toColumnName}`
        );
      }

      // 새 관계 생성
      const relationship = await queryOne(
        `INSERT INTO table_relationships (
          diagram_id, relationship_name, from_table_name, from_column_name,
          to_table_name, to_column_name, relationship_type, connection_type,
          company_code, settings, created_by, updated_by, created_at, updated_at
        ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, now(), now())
        RETURNING *`,
        [
          diagramId,
          data.relationshipName,
          data.fromTableName,
          data.fromColumnName,
          data.toTableName,
          data.toColumnName,
          data.relationshipType,
          data.connectionType,
          data.companyCode,
          JSON.stringify(data.settings),
          data.createdBy,
          data.createdBy,
        ]
      );

      logger.info(
        `DataflowService: 테이블 관계 생성 완료 - ID: ${relationship.relationship_id}, Diagram ID: ${relationship.diagram_id}`
      );
      return relationship;
    } catch (error) {
      logger.error("DataflowService: 테이블 관계 생성 실패", error);
      throw error;
    }
  }

  /**
   * 회사별 테이블 관계 목록 조회
   */
  async getTableRelationships(companyCode: string) {
    try {
      logger.info(
        `DataflowService: 테이블 관계 목록 조회 시작 - 회사코드: ${companyCode}`
      );

      // 관리자는 모든 회사의 관계를 볼 수 있음
      let queryText = `SELECT * FROM table_relationships WHERE is_active = 'Y'`;
      const params: any[] = [];

      if (companyCode !== "*") {
        queryText += ` AND company_code = $1`;
        params.push(companyCode);
      }

      queryText += ` ORDER BY created_date DESC`;
      const relationships = await query(queryText, params);

      logger.info(
        `DataflowService: 테이블 관계 목록 조회 완료 - ${relationships.length}개`
      );
      return relationships;
    } catch (error) {
      logger.error("DataflowService: 테이블 관계 목록 조회 실패", error);
      throw error;
    }
  }

  /**
   * 특정 테이블 관계 조회
   */
  async getTableRelationship(relationshipId: number, companyCode: string) {
    try {
      logger.info(
        `DataflowService: 테이블 관계 조회 시작 - ID: ${relationshipId}, 회사코드: ${companyCode}`
      );

      let queryText = `SELECT * FROM table_relationships WHERE relationship_id = $1 AND is_active = 'Y'`;
      const params: any[] = [relationshipId];

      // 관리자가 아닌 경우 회사코드 제한
      if (companyCode !== "*") {
        queryText += ` AND company_code = $2`;
        params.push(companyCode);
      }

      const relationship = await queryOne(queryText, params);

      if (relationship) {
        logger.info(
          `DataflowService: 테이블 관계 조회 완료 - ID: ${relationshipId}`
        );
      } else {
        logger.warn(
          `DataflowService: 테이블 관계를 찾을 수 없음 - ID: ${relationshipId}`
        );
      }

      return relationship;
    } catch (error) {
      logger.error("DataflowService: 테이블 관계 조회 실패", error);
      throw error;
    }
  }

  /**
   * 테이블 관계 수정
   */
  async updateTableRelationship(
    relationshipId: number,
    updateData: UpdateTableRelationshipData,
    companyCode: string
  ) {
    try {
      logger.info(
        `DataflowService: 테이블 관계 수정 시작 - ID: ${relationshipId}`,
        updateData
      );

      // 기존 관계 확인
      const existingRelationship = await this.getTableRelationship(
        relationshipId,
        companyCode
      );
      if (!existingRelationship) {
        return null;
      }

      // 관계 수정
      const updates: string[] = [];
      const params: any[] = [];
      let paramIndex = 1;

      if (updateData.relationshipName !== undefined) {
        updates.push(`relationship_name = $${paramIndex++}`);
        params.push(updateData.relationshipName);
      }
      if (updateData.fromTableName !== undefined) {
        updates.push(`from_table_name = $${paramIndex++}`);
        params.push(updateData.fromTableName);
      }
      if (updateData.fromColumnName !== undefined) {
        updates.push(`from_column_name = $${paramIndex++}`);
        params.push(updateData.fromColumnName);
      }
      if (updateData.toTableName !== undefined) {
        updates.push(`to_table_name = $${paramIndex++}`);
        params.push(updateData.toTableName);
      }
      if (updateData.toColumnName !== undefined) {
        updates.push(`to_column_name = $${paramIndex++}`);
        params.push(updateData.toColumnName);
      }
      if (updateData.relationshipType !== undefined) {
        updates.push(`relationship_type = $${paramIndex++}`);
        params.push(updateData.relationshipType);
      }
      if (updateData.connectionType !== undefined) {
        updates.push(`connection_type = $${paramIndex++}`);
        params.push(updateData.connectionType);
      }
      if (updateData.settings !== undefined) {
        updates.push(`settings = $${paramIndex++}`);
        params.push(JSON.stringify(updateData.settings));
      }
      updates.push(`updated_by = $${paramIndex++}`);
      params.push(updateData.updatedBy);
      updates.push(`updated_date = now()`);

      params.push(relationshipId);

      const relationship = await queryOne(
        `UPDATE table_relationships 
         SET ${updates.join(", ")} 
         WHERE relationship_id = $${paramIndex} 
         RETURNING *`,
        params
      );

      logger.info(
        `DataflowService: 테이블 관계 수정 완료 - ID: ${relationshipId}`
      );
      return relationship;
    } catch (error) {
      logger.error("DataflowService: 테이블 관계 수정 실패", error);
      throw error;
    }
  }

  /**
   * 테이블 관계 삭제 (소프트 삭제)
   */
  async deleteTableRelationship(relationshipId: number, companyCode: string) {
    try {
      logger.info(
        `DataflowService: 테이블 관계 삭제 시작 - ID: ${relationshipId}, 회사코드: ${companyCode}`
      );

      // 기존 관계 확인
      const existingRelationship = await this.getTableRelationship(
        relationshipId,
        companyCode
      );
      if (!existingRelationship) {
        return false;
      }

      // 소프트 삭제 (is_active = 'N')
      await query(
        `UPDATE table_relationships 
         SET is_active = 'N', updated_date = now() 
         WHERE relationship_id = $1`,
        [relationshipId]
      );

      logger.info(
        `DataflowService: 테이블 관계 삭제 완료 - ID: ${relationshipId}`
      );
      return true;
    } catch (error) {
      logger.error("DataflowService: 테이블 관계 삭제 실패", error);
      throw error;
    }
  }

  /**
   * 특정 테이블과 관련된 모든 관계 조회
   */
  async getRelationshipsByTable(tableName: string, companyCode: string) {
    try {
      logger.info(
        `DataflowService: 테이블별 관계 조회 시작 - 테이블: ${tableName}, 회사코드: ${companyCode}`
      );

      let queryText = `
        SELECT * FROM table_relationships 
        WHERE (from_table_name = $1 OR to_table_name = $1) 
          AND is_active = 'Y'
      `;
      const params: any[] = [tableName];

      // 관리자가 아닌 경우 회사코드 제한
      if (companyCode !== "*") {
        queryText += ` AND company_code = $2`;
        params.push(companyCode);
      }

      queryText += ` ORDER BY created_date DESC`;
      const relationships = await query(queryText, params);

      logger.info(
        `DataflowService: 테이블별 관계 조회 완료 - ${relationships.length}개`
      );
      return relationships;
    } catch (error) {
      logger.error("DataflowService: 테이블별 관계 조회 실패", error);
      throw error;
    }
  }

  /**
   * 두 테이블 간의 조인 관계 조회 (마스터-디테일 저장용)
   * @param mainTable 메인 테이블명 (마스터)
   * @param detailTable 디테일 테이블명 (리피터)
   * @param companyCode 회사코드
   * @returns 조인 컬럼 매핑 정보
   */
  async getJoinRelationshipBetweenTables(
    mainTable: string,
    detailTable: string,
    companyCode: string
  ): Promise<{
    found: boolean;
    mainColumn?: string;
    detailColumn?: string;
    relationshipType?: string;
  }> {
    try {
      logger.info(
        `DataflowService: 테이블 간 조인 관계 조회 - 메인: ${mainTable}, 디테일: ${detailTable}`
      );

      // 양방향 조회 (from → to 또는 to → from)
      let queryText = `
        SELECT 
          from_table_name,
          from_column_name,
          to_table_name,
          to_column_name,
          relationship_type,
          settings
        FROM table_relationships 
        WHERE is_active = 'Y'
          AND (
            (from_table_name = $1 AND to_table_name = $2)
            OR (from_table_name = $2 AND to_table_name = $1)
          )
      `;
      const params: any[] = [mainTable, detailTable];

      // 관리자가 아닌 경우 회사코드 제한
      if (companyCode !== "*") {
        queryText += ` AND (company_code = $3 OR company_code = '*')`;
        params.push(companyCode);
      }

      queryText += ` LIMIT 1`;
      
      const result = await queryOne<{
        from_table_name: string;
        from_column_name: string;
        to_table_name: string;
        to_column_name: string;
        relationship_type: string;
        settings: any;
      }>(queryText, params);

      if (!result) {
        logger.info(
          `DataflowService: 테이블 간 조인 관계 없음 - ${mainTable} ↔ ${detailTable}`
        );
        return { found: false };
      }

      // 방향에 따라 컬럼 매핑 결정
      // mainTable이 from_table이면 그대로, 아니면 반대로
      let mainColumn: string;
      let detailColumn: string;

      if (result.from_table_name === mainTable) {
        // from → to 방향: mainTable.from_column → detailTable.to_column
        mainColumn = result.from_column_name;
        detailColumn = result.to_column_name;
      } else {
        // to → from 방향: mainTable.to_column → detailTable.from_column
        mainColumn = result.to_column_name;
        detailColumn = result.from_column_name;
      }

      // 쉼표로 구분된 다중 컬럼인 경우 첫 번째 컬럼만 사용
      // (추후 다중 컬럼 지원 필요시 확장)
      if (mainColumn.includes(",")) {
        mainColumn = mainColumn.split(",")[0].trim();
      }
      if (detailColumn.includes(",")) {
        detailColumn = detailColumn.split(",")[0].trim();
      }

      logger.info(
        `DataflowService: 조인 관계 발견 - ${mainTable}.${mainColumn} → ${detailTable}.${detailColumn}`
      );

      return {
        found: true,
        mainColumn,
        detailColumn,
        relationshipType: result.relationship_type,
      };
    } catch (error) {
      logger.error("DataflowService: 테이블 간 조인 관계 조회 실패", error);
      return { found: false };
    }
  }

  /**
   * 연결 타입별 관계 조회
   */
  async getRelationshipsByConnectionType(
    connectionType: string,
    companyCode: string
  ) {
    try {
      logger.info(
        `DataflowService: 연결타입별 관계 조회 시작 - 타입: ${connectionType}, 회사코드: ${companyCode}`
      );

      let queryText = `
        SELECT * FROM table_relationships 
        WHERE connection_type = $1 AND is_active = 'Y'
      `;
      const params: any[] = [connectionType];

      // 관리자가 아닌 경우 회사코드 제한
      if (companyCode !== "*") {
        queryText += ` AND company_code = $2`;
        params.push(companyCode);
      }

      queryText += ` ORDER BY created_date DESC`;
      const relationships = await query(queryText, params);

      logger.info(
        `DataflowService: 연결타입별 관계 조회 완료 - ${relationships.length}개`
      );
      return relationships;
    } catch (error) {
      logger.error("DataflowService: 연결타입별 관계 조회 실패", error);
      throw error;
    }
  }

  /**
   * 관계 통계 조회
   */
  async getRelationshipStats(companyCode: string) {
    try {
      logger.info(
        `DataflowService: 관계 통계 조회 시작 - 회사코드: ${companyCode}`
      );

      let whereClause = `WHERE is_active = 'Y'`;
      const params: any[] = [];

      // 관리자가 아닌 경우 회사코드 제한
      if (companyCode !== "*") {
        whereClause += ` AND company_code = $1`;
        params.push(companyCode);
      }

      // 전체 관계 수
      const totalCountResult = await queryOne<{ count: string }>(
        `SELECT COUNT(*) as count FROM table_relationships ${whereClause}`,
        params
      );
      const totalCount = parseInt(totalCountResult?.count || "0", 10);

      // 관계 타입별 통계
      const relationshipTypeStats = await query<{
        relationship_type: string;
        count: string;
      }>(
        `SELECT relationship_type, COUNT(*) as count 
         FROM table_relationships ${whereClause} 
         GROUP BY relationship_type`,
        params
      );

      // 연결 타입별 통계
      const connectionTypeStats = await query<{
        connection_type: string;
        count: string;
      }>(
        `SELECT connection_type, COUNT(*) as count 
         FROM table_relationships ${whereClause} 
         GROUP BY connection_type`,
        params
      );

      const stats = {
        totalCount,
        relationshipTypeStats: relationshipTypeStats.map((stat) => ({
          type: stat.relationship_type,
          count: parseInt(stat.count, 10),
        })),
        connectionTypeStats: connectionTypeStats.map((stat) => ({
          type: stat.connection_type,
          count: parseInt(stat.count, 10),
        })),
      };

      logger.info(`DataflowService: 관계 통계 조회 완료`, stats);
      return stats;
    } catch (error) {
      logger.error("DataflowService: 관계 통계 조회 실패", error);
      throw error;
    }
  }

  // ==================== 데이터 중계 관리 ====================

  /**
   * 데이터 관계 연결 생성
   */
  async createDataLink(linkData: {
    relationshipId: number;
    fromTableName: string;
    fromColumnName: string;
    toTableName: string;
    toColumnName: string;
    connectionType: string;
    companyCode: string;
    bridgeData?: any;
    createdBy: string;
  }) {
    try {
      logger.info(
        `DataflowService: 데이터 연결 생성 시작 - 관계ID: ${linkData.relationshipId}`
      );

      const bridge = await queryOne(
        `INSERT INTO data_relationship_bridge (
          relationship_id, from_table_name, from_column_name, to_table_name,
          to_column_name, connection_type, company_code, bridge_data,
          created_by, created_at
        ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, now())
        RETURNING *`,
        [
          linkData.relationshipId,
          linkData.fromTableName,
          linkData.fromColumnName,
          linkData.toTableName,
          linkData.toColumnName,
          linkData.connectionType,
          linkData.companyCode,
          JSON.stringify(linkData.bridgeData || {}),
          linkData.createdBy,
        ]
      );

      logger.info(
        `DataflowService: 데이터 연결 생성 완료 - Bridge ID: ${bridge.bridge_id}`
      );
      return bridge;
    } catch (error) {
      logger.error("DataflowService: 데이터 연결 생성 실패", error);
      throw error;
    }
  }

  /**
   * 관계별 연결된 데이터 조회
   */
  async getLinkedDataByRelationship(
    relationshipId: number,
    companyCode: string
  ) {
    try {
      logger.info(
        `DataflowService: 관계별 연결 데이터 조회 시작 - 관계ID: ${relationshipId}`
      );

      let queryText = `
        SELECT * FROM data_relationship_bridge 
        WHERE relationship_id = $1 AND is_active = 'Y'
      `;
      const params: any[] = [relationshipId];

      // 관리자가 아닌 경우 회사코드 제한
      if (companyCode !== "*") {
        queryText += ` AND company_code = $2`;
        params.push(companyCode);
      }

      queryText += ` ORDER BY created_at DESC`;
      const linkedData = await query(queryText, params);

      logger.info(
        `DataflowService: 관계별 연결 데이터 조회 완료 - ${linkedData.length}건`
      );
      return linkedData;
    } catch (error) {
      logger.error("DataflowService: 관계별 연결 데이터 조회 실패", error);
      throw error;
    }
  }

  /**
   * 특정 테이블의 연결된 데이터 조회
   */
  async getLinkedDataByTable(
    tableName: string,
    keyValue?: string,
    companyCode?: string
  ) {
    try {
      logger.info(
        `DataflowService: 테이블별 연결 데이터 조회 시작 - 테이블: ${tableName}`
      );

      let queryText = `
        SELECT * FROM data_relationship_bridge 
        WHERE (from_table_name = $1 OR to_table_name = $1) AND is_active = 'Y'
      `;
      const params: any[] = [tableName];

      // keyValue 파라미터는 더 이상 사용하지 않음 (key_value 필드 제거됨)

      // 회사코드 필터링
      if (companyCode && companyCode !== "*") {
        queryText += ` AND company_code = $2`;
        params.push(companyCode);
      }

      queryText += ` ORDER BY created_at DESC`;
      const linkedData = await query(queryText, params);

      logger.info(
        `DataflowService: 테이블별 연결 데이터 조회 완료 - ${linkedData.length}건`
      );
      return linkedData;
    } catch (error) {
      logger.error("DataflowService: 테이블별 연결 데이터 조회 실패", error);
      throw error;
    }
  }

  /**
   * 데이터 연결 수정
   */
  async updateDataLink(
    bridgeId: number,
    updateData: {
      bridgeData?: any;
      updatedBy: string;
    },
    companyCode: string
  ) {
    try {
      logger.info(
        `DataflowService: 데이터 연결 수정 시작 - Bridge ID: ${bridgeId}`
      );

      let queryText = `
        UPDATE data_relationship_bridge 
        SET bridge_data = $1, updated_by = $2, updated_at = now() 
        WHERE bridge_id = $3 AND is_active = 'Y'
      `;
      const params: any[] = [
        JSON.stringify(updateData.bridgeData),
        updateData.updatedBy,
        bridgeId,
      ];

      // 관리자가 아닌 경우 회사코드 제한
      if (companyCode !== "*") {
        queryText += ` AND company_code = $4`;
        params.push(companyCode);
      }

      queryText += ` RETURNING *`;
      const updatedBridge = await queryOne(queryText, params);

      logger.info(
        `DataflowService: 데이터 연결 수정 완료 - Bridge ID: ${bridgeId}`
      );
      return updatedBridge;
    } catch (error) {
      logger.error("DataflowService: 데이터 연결 수정 실패", error);
      throw error;
    }
  }

  /**
   * 데이터 연결 삭제 (소프트 삭제)
   */
  async deleteDataLink(
    bridgeId: number,
    companyCode: string,
    deletedBy: string
  ) {
    try {
      logger.info(
        `DataflowService: 데이터 연결 삭제 시작 - Bridge ID: ${bridgeId}`
      );

      let queryText = `
        UPDATE data_relationship_bridge 
        SET is_active = 'N', updated_at = now(), updated_by = $1 
        WHERE bridge_id = $2 AND is_active = 'Y'
      `;
      const params: any[] = [deletedBy, bridgeId];

      // 관리자가 아닌 경우 회사코드 제한
      if (companyCode !== "*") {
        queryText += ` AND company_code = $3`;
        params.push(companyCode);
      }

      await query(queryText, params);

      logger.info(
        `DataflowService: 데이터 연결 삭제 완료 - Bridge ID: ${bridgeId}`
      );
      return true;
    } catch (error) {
      logger.error("DataflowService: 데이터 연결 삭제 실패", error);
      throw error;
    }
  }

  /**
   * 관계 삭제 시 연결된 모든 데이터도 삭제
   */
  async deleteAllLinkedDataByRelationship(
    relationshipId: number,
    companyCode: string,
    deletedBy: string
  ) {
    try {
      logger.info(
        `DataflowService: 관계별 모든 데이터 연결 삭제 시작 - 관계ID: ${relationshipId}`
      );

      let queryText = `
        UPDATE data_relationship_bridge 
        SET is_active = 'N', updated_at = now(), updated_by = $1 
        WHERE relationship_id = $2 AND is_active = 'Y'
      `;
      const params: any[] = [deletedBy, relationshipId];

      // 관리자가 아닌 경우 회사코드 제한
      if (companyCode !== "*") {
        queryText += ` AND company_code = $3`;
        params.push(companyCode);
      }

      const result = await query(queryText, params);

      logger.info(
        `DataflowService: 관계별 모든 데이터 연결 삭제 완료 - ${result.length}건`
      );
      return result.length;
    } catch (error) {
      logger.error("DataflowService: 관계별 모든 데이터 연결 삭제 실패", error);
      throw error;
    }
  }

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

  /**
   * 테이블 실제 데이터 조회 (페이징)
   */
  async getTableData(
    tableName: string,
    page: number = 1,
    limit: number = 10,
    search: string = "",
    searchColumn: string = "",
    companyCode: string = "*"
  ) {
    try {
      logger.info(`DataflowService: 테이블 데이터 조회 시작 - ${tableName}`);

      // 테이블 존재 여부 확인 (정보 스키마 사용)
      const tableExists = await query(
        `SELECT table_name 
         FROM information_schema.tables 
         WHERE table_name = $1 AND table_schema = 'public'`,
        [tableName.toLowerCase()]
      );

      if (!tableExists || tableExists.length === 0) {
        throw new Error(`테이블 '${tableName}'이 존재하지 않습니다.`);
      }

      // 전체 데이터 개수 조회 및 데이터 조회
      let totalCountQuery = `SELECT COUNT(*) as total FROM "${tableName}"`;
      let dataQuery = `SELECT * FROM "${tableName}"`;
      const queryParams: any[] = [];

      // 검색 조건 추가 (SQL Injection 방지를 위해 파라미터 바인딩 사용)
      if (search && searchColumn) {
        const paramIndex = queryParams.length + 1;
        const whereCondition = `WHERE "${searchColumn}" ILIKE $${paramIndex}`;
        totalCountQuery += ` ${whereCondition}`;
        dataQuery += ` ${whereCondition}`;
        queryParams.push(`%${search}%`);
      }

      // 페이징 처리
      const offset = (page - 1) * limit;
      const limitIndex = queryParams.length + 1;
      const offsetIndex = queryParams.length + 2;
      dataQuery += ` ORDER BY 1 LIMIT $${limitIndex} OFFSET $${offsetIndex}`;

      const dataQueryParams = [...queryParams, limit, offset];

      // 실제 쿼리 실행
      const [totalResult, dataResult] = await Promise.all([
        query(totalCountQuery, queryParams.length > 0 ? queryParams : []),
        query(dataQuery, dataQueryParams),
      ]);

      const total =
        totalResult && totalResult.length > 0
          ? Number((totalResult[0] as any).total)
          : 0;

      const data = dataResult || [];

      const result = {
        data,
        pagination: {
          page,
          limit,
          total,
          totalPages: Math.ceil(total / limit),
          hasNext: page < Math.ceil(total / limit),
          hasPrev: page > 1,
        },
      };

      logger.info(
        `DataflowService: 테이블 데이터 조회 완료 - ${tableName}, 총 ${total}건 중 ${data.length}건 조회`
      );

      return result;
    } catch (error) {
      logger.error(
        `DataflowService: 테이블 데이터 조회 실패 - ${tableName}`,
        error
      );
      throw error;
    }
  }

  /**
   * 관계도 그룹 목록 조회 (diagram_id별로 그룹화)
   */
  async getDataFlowDiagrams(
    companyCode: string,
    page: number = 1,
    size: number = 20,
    searchTerm: string = ""
  ) {
    try {
      logger.info(
        `DataflowService: 관계도 목록 조회 시작 - ${companyCode}, page: ${page}, size: ${size}, search: ${searchTerm}`
      );

      // WHERE 조건 구성
      const params: any[] = [companyCode];
      let whereClause = `WHERE company_code = $1 AND is_active = 'Y'`;

      if (searchTerm) {
        whereClause += ` AND (
          relationship_name ILIKE $2 OR 
          from_table_name ILIKE $2 OR 
          to_table_name ILIKE $2
        )`;
        params.push(`%${searchTerm}%`);
      }

      // diagram_id별로 그룹화된 데이터 조회
      const relationships = await query<{
        relationship_id: number;
        diagram_id: number;
        relationship_name: string;
        from_table_name: string;
        to_table_name: string;
        connection_type: string;
        relationship_type: string;
        created_date: Date;
        created_by: string;
        updated_date: Date;
        updated_by: string;
      }>(
        `SELECT 
          relationship_id, diagram_id, relationship_name, 
          from_table_name, to_table_name, connection_type, 
          relationship_type, created_date, created_by, 
          updated_date, updated_by
         FROM table_relationships 
         ${whereClause}
         ORDER BY diagram_id ASC, created_date DESC`,
        params
      );

      // diagram_id별로 그룹화
      const diagramMap = new Map<number, any>();

      relationships.forEach((rel) => {
        const diagramId = rel.diagram_id;

        if (diagramId && !diagramMap.has(diagramId)) {
          diagramMap.set(diagramId, {
            diagramId: diagramId,
            diagramName: rel.relationship_name, // 첫 번째 관계의 이름을 사용
            connectionType: rel.connection_type,
            relationshipType: rel.relationship_type,
            tableCount: new Set<string>(),
            relationshipCount: 0,
            createdAt: rel.created_date,
            createdBy: rel.created_by,
            updatedAt: rel.updated_date,
            updatedBy: rel.updated_by,
            tables: [],
          });
        }

        if (diagramId) {
          const diagram = diagramMap.get(diagramId);
          if (diagram) {
            diagram.tableCount.add(rel.from_table_name || "");
            diagram.tableCount.add(rel.to_table_name || "");
          }
          diagram.relationshipCount++;

          // 최신 업데이트 시간 유지
          if (rel.updated_date && rel.updated_date > diagram.updatedAt) {
            diagram.updatedAt = rel.updated_date;
            diagram.updatedBy = rel.updated_by;
          }
        }
      });

      // Set을 배열로 변환하고 테이블 개수 계산
      const diagrams = Array.from(diagramMap.values()).map((diagram) => ({
        ...diagram,
        tableCount: diagram.tableCount.size,
        tables: Array.from(diagram.tableCount),
      }));

      // 페이징 처리
      const total = diagrams.length;
      const startIndex = (page - 1) * size;
      const endIndex = startIndex + size;
      const paginatedDiagrams = diagrams.slice(startIndex, endIndex);

      const result = {
        diagrams: paginatedDiagrams,
        total,
        page,
        size,
        totalPages: Math.ceil(total / size),
        hasNext: page < Math.ceil(total / size),
        hasPrev: page > 1,
      };

      logger.info(
        `DataflowService: 관계도 목록 조회 완료 - 총 ${total}개 관계도 중 ${paginatedDiagrams.length}개 조회`
      );

      return result;
    } catch (error) {
      logger.error("DataflowService: 관계도 목록 조회 실패", error);
      throw error;
    }
  }

  /**
   * 특정 관계도의 모든 관계 조회
   */
  async getDiagramRelationships(companyCode: string, diagramName: string) {
    try {
      logger.info(
        `DataflowService: 관계도 관계 조회 시작 - ${companyCode}, diagram: ${diagramName}`
      );

      const relationships = await query(
        `SELECT * FROM table_relationships
         WHERE company_code = $1 
           AND relationship_name = $2 
           AND is_active = 'Y'
         ORDER BY created_date ASC`,
        [companyCode, diagramName]
      );

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

      return relationships;
    } catch (error) {
      logger.error(
        `DataflowService: 관계도 관계 조회 실패 - ${diagramName}`,
        error
      );
      throw error;
    }
  }

  /**
   * 관계도 복사 (diagram_id 기반)
   */
  async copyDiagram(
    companyCode: string,
    originalDiagramName: string
  ): Promise<string> {
    try {
      logger.info(`DataflowService: 관계도 복사 시작 - ${originalDiagramName}`);

      // 원본 관계도의 모든 관계 조회
      const originalRelationships = await query<{
        relationship_id: number;
        diagram_id: number;
        relationship_name: string;
        from_table_name: string;
        from_column_name: string;
        to_table_name: string;
        to_column_name: string;
        relationship_type: string;
        connection_type: string;
        settings: any;
        company_code: string;
        created_by: string;
        updated_by: string;
      }>(
        `SELECT * FROM table_relationships
         WHERE company_code = $1 
           AND relationship_name = $2 
           AND is_active = 'Y'`,
        [companyCode, originalDiagramName]
      );

      if (originalRelationships.length === 0) {
        throw new Error("복사할 관계도를 찾을 수 없습니다.");
      }

      // 새로운 관계도 이름 생성 (중복 검사)
      let newDiagramName = `${originalDiagramName} (1)`;
      let counter = 1;

      while (true) {
        const existingDiagram = await queryOne(
          `SELECT relationship_id FROM table_relationships
           WHERE company_code = $1 
             AND relationship_name = $2 
             AND is_active = 'Y'
           LIMIT 1`,
          [companyCode, newDiagramName]
        );

        if (!existingDiagram) {
          break;
        }

        counter++;
        newDiagramName = `${originalDiagramName} (${counter})`;
      }

      // 새로운 diagram_id 생성
      const maxDiagramId = await queryOne<{ diagram_id: number }>(
        `SELECT diagram_id FROM table_relationships
         WHERE company_code = $1
         ORDER BY diagram_id DESC
         LIMIT 1`,
        [companyCode]
      );

      const newDiagramId = (maxDiagramId?.diagram_id || 0) + 1;

      // 트랜잭션으로 모든 관계 복사
      const copiedRelationships = await transaction(async (client) => {
        const results: any[] = [];

        for (const rel of originalRelationships) {
          const result = await client.query(
            `INSERT INTO table_relationships (
              diagram_id, relationship_name, from_table_name, from_column_name,
              to_table_name, to_column_name, relationship_type, connection_type,
              settings, company_code, is_active, created_by, updated_by, created_at, updated_at
            ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, 'Y', $11, $12, now(), now())
            RETURNING *`,
            [
              newDiagramId,
              newDiagramName,
              rel.from_table_name,
              rel.from_column_name,
              rel.to_table_name,
              rel.to_column_name,
              rel.relationship_type,
              rel.connection_type,
              rel.settings,
              rel.company_code,
              rel.created_by,
              rel.updated_by,
            ]
          );

          if (result.rows && result.rows.length > 0) {
            results.push(result.rows[0]);
          }
        }

        return results;
      });

      logger.info(
        `DataflowService: 관계도 복사 완료 - ${originalDiagramName} → ${newDiagramName} (diagram_id: ${newDiagramId}), ${copiedRelationships.length}개 관계 복사`
      );

      return newDiagramName;
    } catch (error) {
      logger.error(
        `DataflowService: 관계도 복사 실패 - ${originalDiagramName}`,
        error
      );
      throw error;
    }
  }

  /**
   * 관계도 삭제
   */
  async deleteDiagram(
    companyCode: string,
    diagramName: string
  ): Promise<number> {
    try {
      logger.info(`DataflowService: 관계도 삭제 시작 - ${diagramName}`);

      // 관계도의 모든 관계 삭제 (하드 삭제)
      const deleteResult = await query<{ count: number }>(
        `DELETE FROM table_relationships
         WHERE company_code = $1 AND relationship_name = $2
         RETURNING relationship_id`,
        [companyCode, diagramName]
      );

      const count = deleteResult.length;

      logger.info(
        `DataflowService: 관계도 삭제 완료 - ${diagramName}, ${count}개 관계 삭제`
      );

      return count;
    } catch (error) {
      logger.error(`DataflowService: 관계도 삭제 실패 - ${diagramName}`, error);
      throw error;
    }
  }

  /**
   * diagram_id로 해당 관계도의 모든 관계 조회
   */
  async getDiagramRelationshipsByDiagramId(
    companyCode: string,
    diagramId: number
  ) {
    try {
      logger.info(
        `DataflowService: diagram_id로 관계도 관계 조회 - ${diagramId}`
      );

      // diagram_id로 모든 관계 조회
      const relationships = await query(
        `SELECT * FROM table_relationships
         WHERE diagram_id = $1 
           AND company_code = $2 
           AND is_active = 'Y'
         ORDER BY relationship_id ASC`,
        [diagramId, companyCode]
      );

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

      return relationships.map((rel: any) => ({
        ...rel,
        settings: rel.settings as any,
      }));
    } catch (error) {
      logger.error(
        `DataflowService: diagram_id로 관계도 관계 조회 실패 - ${diagramId}`,
        error
      );
      throw error;
    }
  }

  /**
   * relationship_id로 해당 관계도의 모든 관계 조회 (하위 호환성 유지)
   */
  async getDiagramRelationshipsByRelationshipId(
    companyCode: string,
    relationshipId: number
  ) {
    try {
      logger.info(
        `DataflowService: relationship_id로 관계도 관계 조회 - ${relationshipId}`
      );

      // 먼저 해당 relationship_id의 diagram_id를 찾음
      const targetRelationship = await queryOne<{ diagram_id: number }>(
        `SELECT diagram_id FROM table_relationships
         WHERE relationship_id = $1 
           AND company_code = $2 
           AND is_active = 'Y'
         LIMIT 1`,
        [relationshipId, companyCode]
      );

      if (!targetRelationship) {
        throw new Error("해당 관계 ID를 찾을 수 없습니다.");
      }

      // diagram_id로 모든 관계 조회
      if (targetRelationship.diagram_id) {
        return this.getDiagramRelationshipsByDiagramId(
          companyCode,
          targetRelationship.diagram_id
        );
      } else {
        throw new Error("관계에 diagram_id가 없습니다.");
      }
    } catch (error) {
      logger.error(
        `DataflowService: relationship_id로 관계도 관계 조회 실패 - ${relationshipId}`,
        error
      );
      throw error;
    }
  }
}
