import { QueryResult } from "../types";

/**
 * JSON Path를 사용하여 객체에서 데이터 추출
 * @param obj JSON 객체
 * @param path 경로 (예: "data.results", "items")
 * @returns 추출된 데이터
 */
export function extractDataFromJsonPath(obj: any, path: string): any {
  if (!path || path.trim() === "") {
    return obj;
  }

  const keys = path.split(".");
  let result = obj;

  for (const key of keys) {
    if (result === null || result === undefined) {
      return null;
    }
    result = result[key];
  }

  return result;
}

/**
 * API 응답을 QueryResult 형식으로 변환
 * @param data API 응답 데이터
 * @param jsonPath JSON Path (선택)
 * @returns QueryResult
 */
export function transformApiResponseToQueryResult(data: any, jsonPath?: string): QueryResult {
  try {
    // JSON Path가 있으면 데이터 추출
    let extractedData = jsonPath ? extractDataFromJsonPath(data, jsonPath) : data;

    // 배열이 아니면 배열로 변환
    if (!Array.isArray(extractedData)) {
      // 객체인 경우 키-값 쌍을 배열로 변환
      if (typeof extractedData === "object" && extractedData !== null) {
        extractedData = Object.entries(extractedData).map(([key, value]) => ({
          key,
          value,
        }));
      } else {
        throw new Error("데이터가 배열 또는 객체 형식이 아닙니다");
      }
    }

    if (extractedData.length === 0) {
      return {
        columns: [],
        rows: [],
        totalRows: 0,
        executionTime: 0,
      };
    }

    // 첫 번째 행에서 컬럼 추출
    const firstRow = extractedData[0];
    const columns = Object.keys(firstRow);

    return {
      columns,
      rows: extractedData,
      totalRows: extractedData.length,
      executionTime: 0,
    };
  } catch (error) {
    throw new Error(`API 응답 변환 실패: ${error instanceof Error ? error.message : "알 수 없는 오류"}`);
  }
}

/**
 * 데이터 소스가 유효한지 검증
 * @param type 데이터 소스 타입
 * @param connectionType 커넥션 타입 (DB일 때)
 * @param externalConnectionId 외부 커넥션 ID (외부 DB일 때)
 * @param query SQL 쿼리 (DB일 때)
 * @param endpoint API URL (API일 때)
 * @returns 유효성 검증 결과
 */
export function validateDataSource(
  type: "database" | "api",
  connectionType?: "current" | "external",
  externalConnectionId?: string,
  query?: string,
  endpoint?: string,
): { valid: boolean; message?: string } {
  if (type === "database") {
    // DB 검증
    if (!connectionType) {
      return { valid: false, message: "데이터베이스 타입을 선택하세요" };
    }

    if (connectionType === "external" && !externalConnectionId) {
      return { valid: false, message: "외부 커넥션을 선택하세요" };
    }

    if (!query || query.trim() === "") {
      return { valid: false, message: "SQL 쿼리를 입력하세요" };
    }

    // SELECT 쿼리인지 검증 (간단한 검증)
    const trimmedQuery = query.trim().toLowerCase();
    if (!trimmedQuery.startsWith("select")) {
      return { valid: false, message: "SELECT 쿼리만 허용됩니다" };
    }

    // 위험한 키워드 체크
    const dangerousKeywords = ["drop", "delete", "insert", "update", "truncate", "alter", "create", "exec", "execute"];
    for (const keyword of dangerousKeywords) {
      if (trimmedQuery.includes(keyword)) {
        return {
          valid: false,
          message: `보안상 ${keyword.toUpperCase()} 명령은 사용할 수 없습니다`,
        };
      }
    }

    return { valid: true };
  } else if (type === "api") {
    // API 검증
    if (!endpoint || endpoint.trim() === "") {
      return { valid: false, message: "API URL을 입력하세요" };
    }

    // URL 형식 검증
    try {
      new URL(endpoint);
    } catch {
      return { valid: false, message: "올바른 URL 형식이 아닙니다" };
    }

    return { valid: true };
  }

  return { valid: false, message: "알 수 없는 데이터 소스 타입입니다" };
}

/**
 * 쿼리 파라미터를 URL에 추가
 * @param baseUrl 기본 URL
 * @param params 쿼리 파라미터 객체
 * @returns 쿼리 파라미터가 추가된 URL
 */
export function buildUrlWithParams(baseUrl: string, params?: Record<string, string>): string {
  if (!params || Object.keys(params).length === 0) {
    return baseUrl;
  }

  const url = new URL(baseUrl);
  Object.entries(params).forEach(([key, value]) => {
    if (key && value) {
      url.searchParams.append(key, value);
    }
  });

  return url.toString();
}

/**
 * 컬럼 데이터 타입 추론
 * @param rows 데이터 행
 * @param columnName 컬럼명
 * @returns 데이터 타입 ('string' | 'number' | 'date' | 'boolean')
 */
export function inferColumnType(rows: Record<string, any>[], columnName: string): string {
  if (rows.length === 0) {
    return "string";
  }

  const sampleValue = rows[0][columnName];

  if (typeof sampleValue === "number") {
    return "number";
  }

  if (typeof sampleValue === "boolean") {
    return "boolean";
  }

  if (typeof sampleValue === "string") {
    // 날짜 형식인지 확인
    if (!isNaN(Date.parse(sampleValue))) {
      return "date";
    }
    return "string";
  }

  return "string";
}
