import { Request, Response } from "express";
import logger from "../utils/logger";
import { ExternalDbConnectionPoolService } from "../services/externalDbConnectionPoolService";

// 외부 DB 커넥터를 가져오는 헬퍼 함수 (연결 풀 사용)
export async function getExternalDbConnector(connectionId: number) {
  const poolService = ExternalDbConnectionPoolService.getInstance();

  // 연결 풀 래퍼를 반환 (executeQuery 메서드를 가진 객체)
  return {
    executeQuery: async (sql: string, params?: any[]) => {
      const result = await poolService.executeQuery(connectionId, sql, params);
      return { rows: result };
    },
  };
}

// 동적 계층 구조 데이터 조회 (범용)
export const getHierarchyData = async (
  req: Request,
  res: Response
): Promise<Response> => {
  try {
    const { externalDbConnectionId, hierarchyConfig } = req.body;

    if (!externalDbConnectionId || !hierarchyConfig) {
      return res.status(400).json({
        success: false,
        message: "외부 DB 연결 ID와 계층 구조 설정이 필요합니다.",
      });
    }

    const connector = await getExternalDbConnector(
      Number(externalDbConnectionId)
    );
    const config = JSON.parse(hierarchyConfig);

    const result: any = {
      warehouse: null,
      levels: [],
      materials: [],
    };

    // 창고 데이터 조회
    if (config.warehouse) {
      const warehouseQuery = `SELECT * FROM ${config.warehouse.tableName} LIMIT 100`;
      const warehouseResult = await connector.executeQuery(warehouseQuery);
      result.warehouse = warehouseResult.rows;
    }

    // 각 레벨 데이터 조회
    if (config.levels && Array.isArray(config.levels)) {
      for (const level of config.levels) {
        const levelQuery = `SELECT * FROM ${level.tableName} LIMIT 1000`;
        const levelResult = await connector.executeQuery(levelQuery);

        result.levels.push({
          level: level.level,
          name: level.name,
          data: levelResult.rows,
        });
      }
    }

    // 자재 데이터 조회 (개수만)
    if (config.material) {
      const materialQuery = `
        SELECT 
          ${config.material.locationKeyColumn} as location_key,
          COUNT(*) as count
        FROM ${config.material.tableName}
        GROUP BY ${config.material.locationKeyColumn}
      `;
      const materialResult = await connector.executeQuery(materialQuery);
      result.materials = materialResult.rows;
    }

    logger.info("동적 계층 구조 데이터 조회", {
      externalDbConnectionId,
      warehouseCount: result.warehouse?.length || 0,
      levelCounts: result.levels.map((l: any) => ({
        level: l.level,
        count: l.data.length,
      })),
    });

    return res.json({
      success: true,
      data: result,
    });
  } catch (error: any) {
    logger.error("동적 계층 구조 데이터 조회 실패", error);
    return res.status(500).json({
      success: false,
      message: "데이터 조회 중 오류가 발생했습니다.",
      error: error.message,
    });
  }
};

// 특정 레벨의 하위 데이터 조회
export const getChildrenData = async (
  req: Request,
  res: Response
): Promise<Response> => {
  try {
    const { externalDbConnectionId, hierarchyConfig, parentLevel, parentKey } =
      req.body;

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

    const connector = await getExternalDbConnector(
      Number(externalDbConnectionId)
    );
    const config = JSON.parse(hierarchyConfig);

    // 다음 레벨 찾기
    const nextLevel = config.levels?.find(
      (l: any) => l.level === parentLevel + 1
    );

    if (!nextLevel) {
      return res.json({
        success: true,
        data: [],
        message: "하위 레벨이 없습니다.",
      });
    }

    // 하위 데이터 조회
    const query = `
      SELECT * FROM ${nextLevel.tableName}
      WHERE ${nextLevel.parentKeyColumn} = '${parentKey}'
      LIMIT 1000
    `;

    const result = await connector.executeQuery(query);

    logger.info("하위 데이터 조회", {
      externalDbConnectionId,
      parentLevel,
      parentKey,
      count: result.rows.length,
    });

    return res.json({
      success: true,
      data: result.rows,
    });
  } catch (error: any) {
    logger.error("하위 데이터 조회 실패", error);
    return res.status(500).json({
      success: false,
      message: "하위 데이터 조회 중 오류가 발생했습니다.",
      error: error.message,
    });
  }
};

// 창고 목록 조회 (사용자 지정 테이블) - 레거시, 호환성 유지
export const getWarehouses = async (
  req: Request,
  res: Response
): Promise<Response> => {
  try {
    const { externalDbConnectionId, tableName } = req.query;

    if (!externalDbConnectionId) {
      return res.status(400).json({
        success: false,
        message: "외부 DB 연결 ID가 필요합니다.",
      });
    }

    if (!tableName) {
      return res.status(400).json({
        success: false,
        message: "테이블명이 필요합니다.",
      });
    }

    const connector = await getExternalDbConnector(
      Number(externalDbConnectionId)
    );

    // 테이블명을 사용하여 모든 컬럼 조회
    const query = `SELECT * FROM ${tableName} LIMIT 100`;

    const result = await connector.executeQuery(query);

    logger.info("창고 목록 조회", {
      externalDbConnectionId,
      tableName,
      count: result.rows.length,
      data: result.rows, // 실제 데이터 확인
    });

    return res.json({
      success: true,
      data: result.rows,
    });
  } catch (error: any) {
    logger.error("창고 목록 조회 실패", error);
    return res.status(500).json({
      success: false,
      message: "창고 목록 조회 중 오류가 발생했습니다.",
      error: error.message,
    });
  }
};

// 구역 목록 조회 (사용자 지정 테이블) - 레거시, 호환성 유지
export const getAreas = async (
  req: Request,
  res: Response
): Promise<Response> => {
  try {
    const { externalDbConnectionId, warehouseKey, tableName } = req.query;

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

    const connector = await getExternalDbConnector(
      Number(externalDbConnectionId)
    );

    const query = `
      SELECT * FROM ${tableName}
      WHERE WAREKEY = '${warehouseKey}'
      LIMIT 1000
    `;

    const result = await connector.executeQuery(query);

    logger.info("구역 목록 조회", {
      externalDbConnectionId,
      tableName,
      warehouseKey,
      count: result.rows.length,
    });

    return res.json({
      success: true,
      data: result.rows,
    });
  } catch (error: any) {
    logger.error("구역 목록 조회 실패", error);
    return res.status(500).json({
      success: false,
      message: "구역 목록 조회 중 오류가 발생했습니다.",
      error: error.message,
    });
  }
};

// 위치 목록 조회 (사용자 지정 테이블) - 레거시, 호환성 유지
export const getLocations = async (
  req: Request,
  res: Response
): Promise<Response> => {
  try {
    const { externalDbConnectionId, areaKey, tableName } = req.query;

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

    const connector = await getExternalDbConnector(
      Number(externalDbConnectionId)
    );

    const query = `
      SELECT * FROM ${tableName}
      WHERE AREAKEY = '${areaKey}'
      LIMIT 1000
    `;

    const result = await connector.executeQuery(query);

    logger.info("위치 목록 조회", {
      externalDbConnectionId,
      tableName,
      areaKey,
      count: result.rows.length,
    });

    return res.json({
      success: true,
      data: result.rows,
    });
  } catch (error: any) {
    logger.error("위치 목록 조회 실패", error);
    return res.status(500).json({
      success: false,
      message: "위치 목록 조회 중 오류가 발생했습니다.",
      error: error.message,
    });
  }
};

// 자재 목록 조회 (동적 컬럼 매핑 지원)
export const getMaterials = async (
  req: Request,
  res: Response
): Promise<Response> => {
  try {
    const {
      externalDbConnectionId,
      locaKey,
      tableName,
      keyColumn,
      locationKeyColumn,
      layerColumn,
    } = req.query;

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

    const connector = await getExternalDbConnector(
      Number(externalDbConnectionId)
    );

    // 동적 쿼리 생성
    const orderByClause = layerColumn ? `ORDER BY ${layerColumn}` : "";
    const query = `
      SELECT * FROM ${tableName}
      WHERE ${locationKeyColumn} = '${locaKey}'
      ${orderByClause}
      LIMIT 1000
    `;

    logger.info(`자재 조회 쿼리: ${query}`);

    const result = await connector.executeQuery(query);

    logger.info("자재 목록 조회", {
      externalDbConnectionId,
      tableName,
      locaKey,
      count: result.rows.length,
    });

    return res.json({
      success: true,
      data: result.rows,
    });
  } catch (error: any) {
    logger.error("자재 목록 조회 실패", error);
    return res.status(500).json({
      success: false,
      message: "자재 목록 조회 중 오류가 발생했습니다.",
      error: error.message,
    });
  }
};

// 자재 개수 조회 (여러 Location 일괄) - 레거시, 호환성 유지
export const getMaterialCounts = async (
  req: Request,
  res: Response
): Promise<Response> => {
  try {
    const { externalDbConnectionId, locationKeys, tableName } = req.body;

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

    const connector = await getExternalDbConnector(
      Number(externalDbConnectionId)
    );

    const keysString = locationKeys.map((key: string) => `'${key}'`).join(",");

    const query = `
      SELECT 
        LOCAKEY as location_key,
        COUNT(*) as count
      FROM ${tableName}
      WHERE LOCAKEY IN (${keysString})
      GROUP BY LOCAKEY
    `;

    const result = await connector.executeQuery(query);

    logger.info("자재 개수 조회", {
      externalDbConnectionId,
      tableName,
      locationCount: locationKeys.length,
    });

    return res.json({
      success: true,
      data: result.rows,
    });
  } catch (error: any) {
    logger.error("자재 개수 조회 실패", error);
    return res.status(500).json({
      success: false,
      message: "자재 개수 조회 중 오류가 발생했습니다.",
      error: error.message,
    });
  }
};
