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

// 타입 정의
interface CreateDataflowDiagramData {
  diagram_name: string;
  relationships: Record<string, unknown>; // JSON 데이터
  node_positions?: Record<string, unknown> | null; // JSON 데이터 (노드 위치 정보)

  // 🔥 수정: 배열 구조로 변경된 조건부 연결 관련 필드
  control?: Array<Record<string, unknown>> | null; // JSON 배열 (각 관계별 조건 설정)
  category?: Array<Record<string, unknown>> | null; // JSON 배열 (각 관계별 연결 종류)
  plan?: Array<Record<string, unknown>> | null; // JSON 배열 (각 관계별 실행 계획)

  company_code: string;
  created_by: string;
  updated_by: string;
}

interface UpdateDataflowDiagramData {
  diagram_name?: string;
  relationships?: Record<string, unknown>; // JSON 데이터
  node_positions?: Record<string, unknown> | null; // JSON 데이터 (노드 위치 정보)

  // 🔥 수정: 배열 구조로 변경된 조건부 연결 관련 필드
  control?: Array<Record<string, unknown>> | null; // JSON 배열 (각 관계별 조건 설정)
  category?: Array<Record<string, unknown>> | null; // JSON 배열 (각 관계별 연결 종류)
  plan?: Array<Record<string, unknown>> | null; // JSON 배열 (각 관계별 실행 계획)

  updated_by: string;
}

/**
 * 관계도 목록 조회 (페이지네이션)
 */
export const getDataflowDiagrams = async (
  companyCode: string,
  page: number = 1,
  size: number = 20,
  searchTerm?: string
) => {
  try {
    const offset = (page - 1) * size;

    const whereConditions: string[] = [];
    const values: any[] = [];
    let paramIndex = 1;

    // company_code가 '*'가 아닌 경우에만 필터링
    if (companyCode !== "*") {
      whereConditions.push(`company_code = $${paramIndex++}`);
      values.push(companyCode);
    }

    if (searchTerm) {
      whereConditions.push(`diagram_name ILIKE $${paramIndex++}`);
      values.push(`%${searchTerm}%`);
    }

    const whereClause =
      whereConditions.length > 0
        ? `WHERE ${whereConditions.join(" AND ")}`
        : "";

    // 총 개수 조회
    const countResult = await queryOne<{ count: string }>(
      `SELECT COUNT(*) as count FROM dataflow_diagrams ${whereClause}`,
      values
    );
    const total = parseInt(countResult?.count || "0");

    // 데이터 조회
    const diagrams = await query<any>(
      `SELECT * FROM dataflow_diagrams 
       ${whereClause}
       ORDER BY updated_at DESC
       LIMIT $${paramIndex++} OFFSET $${paramIndex++}`,
      [...values, size, offset]
    );

    const totalPages = Math.ceil(total / size);

    return {
      diagrams,
      pagination: {
        page,
        size,
        total,
        totalPages,
      },
    };
  } catch (error) {
    logger.error("관계도 목록 조회 서비스 오류:", error);
    throw error;
  }
};

/**
 * 특정 관계도 조회
 */
export const getDataflowDiagramById = async (
  diagramId: number,
  companyCode: string
) => {
  try {
    const whereConditions: string[] = ["diagram_id = $1"];
    const values: any[] = [diagramId];

    // company_code가 '*'가 아닌 경우에만 필터링
    if (companyCode !== "*") {
      whereConditions.push("company_code = $2");
      values.push(companyCode);
    }

    const whereClause = `WHERE ${whereConditions.join(" AND ")}`;

    const diagram = await queryOne<any>(
      `SELECT * FROM dataflow_diagrams ${whereClause} LIMIT 1`,
      values
    );

    return diagram;
  } catch (error) {
    logger.error("관계도 조회 서비스 오류:", error);
    throw error;
  }
};

/**
 * 새로운 관계도 생성
 */
export const createDataflowDiagram = async (
  data: CreateDataflowDiagramData
) => {
  try {
    const newDiagram = await queryOne<any>(
      `INSERT INTO dataflow_diagrams 
       (diagram_name, relationships, node_positions, category, control, plan, 
        company_code, created_by, updated_by, created_at, updated_at)
       VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, NOW(), NOW())
       RETURNING *`,
      [
        data.diagram_name,
        JSON.stringify(data.relationships),
        data.node_positions ? JSON.stringify(data.node_positions) : null,
        data.category ? JSON.stringify(data.category) : null,
        data.control ? JSON.stringify(data.control) : null,
        data.plan ? JSON.stringify(data.plan) : null,
        data.company_code,
        data.created_by,
        data.updated_by,
      ]
    );

    return newDiagram;
  } catch (error) {
    logger.error("관계도 생성 서비스 오류:", error);
    throw error;
  }
};

/**
 * 관계도 수정
 */
export const updateDataflowDiagram = async (
  diagramId: number,
  data: UpdateDataflowDiagramData,
  companyCode: string
) => {
  try {
    logger.info(
      `관계도 수정 서비스 시작 - ID: ${diagramId}, Company: ${companyCode}`
    );

    // 먼저 해당 관계도가 존재하는지 확인
    const whereConditions: string[] = ["diagram_id = $1"];
    const checkValues: any[] = [diagramId];

    if (companyCode !== "*") {
      whereConditions.push("company_code = $2");
      checkValues.push(companyCode);
    }

    const existingDiagram = await queryOne<any>(
      `SELECT * FROM dataflow_diagrams WHERE ${whereConditions.join(" AND ")} LIMIT 1`,
      checkValues
    );

    logger.info(
      `기존 관계도 조회 결과:`,
      existingDiagram ? `ID ${existingDiagram.diagram_id} 발견` : "관계도 없음"
    );

    if (!existingDiagram) {
      logger.warn(
        `관계도 ID ${diagramId}를 찾을 수 없음 - Company: ${companyCode}`
      );
      return null;
    }

    // 동적 UPDATE 쿼리 생성
    const updateFields: string[] = ["updated_by = $1", "updated_at = NOW()"];
    const values: any[] = [data.updated_by];
    let paramIndex = 2;

    if (data.diagram_name) {
      updateFields.push(`diagram_name = $${paramIndex++}`);
      values.push(data.diagram_name);
    }
    if (data.relationships) {
      updateFields.push(`relationships = $${paramIndex++}`);
      values.push(JSON.stringify(data.relationships));
    }
    if (data.node_positions !== undefined) {
      updateFields.push(`node_positions = $${paramIndex++}`);
      values.push(
        data.node_positions ? JSON.stringify(data.node_positions) : null
      );
    }
    if (data.category !== undefined) {
      updateFields.push(`category = $${paramIndex++}`);
      values.push(data.category ? JSON.stringify(data.category) : null);
    }
    if (data.control !== undefined) {
      updateFields.push(`control = $${paramIndex++}`);
      values.push(data.control ? JSON.stringify(data.control) : null);
    }
    if (data.plan !== undefined) {
      updateFields.push(`plan = $${paramIndex++}`);
      values.push(data.plan ? JSON.stringify(data.plan) : null);
    }

    const updatedDiagram = await queryOne<any>(
      `UPDATE dataflow_diagrams 
       SET ${updateFields.join(", ")}
       WHERE diagram_id = $${paramIndex}
       RETURNING *`,
      [...values, diagramId]
    );

    return updatedDiagram;
  } catch (error) {
    logger.error("관계도 수정 서비스 오류:", error);
    throw error;
  }
};

/**
 * 관계도 삭제
 */
export const deleteDataflowDiagram = async (
  diagramId: number,
  companyCode: string
) => {
  try {
    // 먼저 해당 관계도가 존재하는지 확인
    const whereConditions: string[] = ["diagram_id = $1"];
    const values: any[] = [diagramId];

    if (companyCode !== "*") {
      whereConditions.push("company_code = $2");
      values.push(companyCode);
    }

    const existingDiagram = await queryOne<any>(
      `SELECT * FROM dataflow_diagrams WHERE ${whereConditions.join(" AND ")} LIMIT 1`,
      values
    );

    if (!existingDiagram) {
      return false;
    }

    // 삭제 실행
    await query(`DELETE FROM dataflow_diagrams WHERE diagram_id = $1`, [
      diagramId,
    ]);

    return true;
  } catch (error) {
    logger.error("관계도 삭제 서비스 오류:", error);
    throw error;
  }
};

/**
 * 관계도 복제
 */
export const copyDataflowDiagram = async (
  diagramId: number,
  companyCode: string,
  newName?: string,
  userId: string = "SYSTEM"
) => {
  try {
    // 원본 관계도 조회
    const whereConditions: string[] = ["diagram_id = $1"];
    const values: any[] = [diagramId];

    if (companyCode !== "*") {
      whereConditions.push("company_code = $2");
      values.push(companyCode);
    }

    const originalDiagram = await queryOne<any>(
      `SELECT * FROM dataflow_diagrams WHERE ${whereConditions.join(" AND ")} LIMIT 1`,
      values
    );

    if (!originalDiagram) {
      return null;
    }

    // 새로운 이름 생성 (제공되지 않은 경우)
    let copyName = newName;
    if (!copyName) {
      // 기존 이름에서 (n) 패턴을 찾아서 증가
      const baseNameMatch = originalDiagram.diagram_name.match(
        /^(.+?)(\s*\((\d+)\))?$/
      );
      const baseName = baseNameMatch
        ? baseNameMatch[1]
        : originalDiagram.diagram_name;

      // 같은 패턴의 이름들을 찾아서 가장 큰 번호 찾기
      const copyWhereConditions: string[] = ["diagram_name LIKE $1"];
      const copyValues: any[] = [`${baseName}%`];

      if (companyCode !== "*") {
        copyWhereConditions.push("company_code = $2");
        copyValues.push(companyCode);
      }

      const existingCopies = await query<{ diagram_name: string }>(
        `SELECT diagram_name FROM dataflow_diagrams 
         WHERE ${copyWhereConditions.join(" AND ")}`,
        copyValues
      );

      let maxNumber = 0;
      existingCopies.forEach((copy) => {
        const match = copy.diagram_name.match(/\((\d+)\)$/);
        if (match) {
          const num = parseInt(match[1]);
          if (num > maxNumber) {
            maxNumber = num;
          }
        }
      });

      copyName = `${baseName} (${maxNumber + 1})`;
    }

    // 새로운 관계도 생성
    const copiedDiagram = await queryOne<any>(
      `INSERT INTO dataflow_diagrams 
       (diagram_name, relationships, node_positions, category, company_code, 
        created_by, updated_by, created_at, updated_at)
       VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())
       RETURNING *`,
      [
        copyName,
        JSON.stringify(originalDiagram.relationships),
        originalDiagram.node_positions
          ? JSON.stringify(originalDiagram.node_positions)
          : null,
        originalDiagram.category || null,
        companyCode,
        userId,
        userId,
      ]
    );

    return copiedDiagram;
  } catch (error) {
    logger.error("관계도 복제 서비스 오류:", error);
    throw error;
  }
};

/**
 * 🔥 전체 관계 목록 조회 (버튼 제어용)
 * dataflow_diagrams 테이블에서 관계도 데이터를 조회 (데이터 흐름 관계 화면과 동일)
 */
export const getAllRelationshipsForButtonControl = async (
  companyCode: string
): Promise<
  Array<{
    id: string;
    name: string;
    sourceTable: string;
    targetTable: string;
    category: string;
  }>
> => {
  try {
    logger.info(`전체 관계 목록 조회 시작 - companyCode: ${companyCode}`);

    // dataflow_diagrams 테이블에서 관계도들을 조회
    const diagrams = await query<{
      diagram_id: number;
      diagram_name: string;
      relationships: any;
    }>(
      `SELECT diagram_id, diagram_name, relationships 
       FROM dataflow_diagrams 
       WHERE company_code = $1
       ORDER BY updated_at DESC`,
      [companyCode]
    );

    const allRelationships = diagrams.map((diagram) => {
      // relationships 구조에서 테이블 정보 추출
      const relationships = (diagram.relationships as any) || {};

      // 테이블 정보 추출
      let sourceTable = "";
      let targetTable = "";

      if (relationships.fromTable?.tableName) {
        sourceTable = relationships.fromTable.tableName;
      }
      if (relationships.toTable?.tableName) {
        targetTable = relationships.toTable.tableName;
      }

      return {
        id: diagram.diagram_id.toString(),
        name: diagram.diagram_name || `관계 ${diagram.diagram_id}`,
        sourceTable: sourceTable,
        targetTable: targetTable,
        category: "데이터 흐름",
      };
    });

    logger.info(`전체 관계 ${allRelationships.length}개 조회 완료`);
    return allRelationships;
  } catch (error) {
    logger.error("전체 관계 목록 조회 서비스 오류:", error);
    throw error;
  }
};
