import { QueryResult, ChartConfig, ChartData, ChartDataset } from "../types";

/**
 * 쿼리 결과를 차트 데이터로 변환
 */
export function transformQueryResultToChartData(queryResult: QueryResult, config: ChartConfig): ChartData | null {
  if (!queryResult || !queryResult.rows.length || !config.xAxis) {
    return null;
  }

  let rows = queryResult.rows;

  // 그룹핑 처리
  if (config.groupBy && config.groupBy !== "__none__") {
    rows = applyGrouping(rows, config.groupBy, config.aggregation, config.yAxis);
  }

  // X축 라벨 추출
  const labels = rows.map((row) => String(row[config.xAxis!] || ""));

  // Y축 데이터 추출
  const yAxisFields = Array.isArray(config.yAxis) ? config.yAxis : config.yAxis ? [config.yAxis] : [];

  // 집계 함수가 COUNT이고 Y축이 없으면 자동으로 count 필드 추가
  if (config.aggregation === "count" && yAxisFields.length === 0) {
    const datasets: ChartDataset[] = [
      {
        label: "개수",
        data: rows.map((row) => {
          const value = row["count"];
          return typeof value === "number" ? value : parseFloat(String(value)) || 0;
        }),
        color: config.colors?.[0],
      },
    ];

    return {
      labels,
      datasets,
    };
  }

  if (yAxisFields.length === 0) {
    return null;
  }

  // 각 Y축 필드에 대해 데이터셋 생성
  const datasets: ChartDataset[] = yAxisFields.map((field, index) => {
    const data = rows.map((row) => {
      const value = row[field];
      return typeof value === "number" ? value : parseFloat(String(value)) || 0;
    });

    return {
      label: field,
      data,
      color: config.colors?.[index],
    };
  });

  return {
    labels,
    datasets,
  };
}

/**
 * 그룹핑 및 집계 처리
 */
function applyGrouping(
  rows: Record<string, any>[],
  groupByField: string,
  aggregation?: "sum" | "avg" | "count" | "max" | "min",
  yAxis?: string | string[],
): Record<string, any>[] {
  // 그룹별로 데이터 묶기
  const groups = new Map<string, Record<string, any>[]>();

  rows.forEach((row) => {
    const key = String(row[groupByField] || "");
    if (!groups.has(key)) {
      groups.set(key, []);
    }
    groups.get(key)!.push(row);
  });

  // 각 그룹에 대해 집계 수행
  const aggregatedRows: Record<string, any>[] = [];

  groups.forEach((groupRows, key) => {
    const aggregatedRow: Record<string, any> = {
      [groupByField]: key,
    };

    // Y축 필드에 대해 집계
    const yAxisFields = Array.isArray(yAxis) ? yAxis : yAxis ? [yAxis] : [];

    if (aggregation === "count") {
      // COUNT: 그룹의 행 개수
      aggregatedRow["count"] = groupRows.length;
    } else if (yAxisFields.length > 0) {
      yAxisFields.forEach((field) => {
        const values = groupRows.map((row) => {
          const value = row[field];
          return typeof value === "number" ? value : parseFloat(String(value)) || 0;
        });

        switch (aggregation) {
          case "sum":
            aggregatedRow[field] = values.reduce((a, b) => a + b, 0);
            break;
          case "avg":
            aggregatedRow[field] = values.reduce((a, b) => a + b, 0) / values.length;
            break;
          case "max":
            aggregatedRow[field] = Math.max(...values);
            break;
          case "min":
            aggregatedRow[field] = Math.min(...values);
            break;
          default:
            // 집계 없으면 첫 번째 값 사용
            aggregatedRow[field] = values[0];
        }
      });
    }

    aggregatedRows.push(aggregatedRow);
  });

  return aggregatedRows;
}

/**
 * API 응답을 차트 데이터로 변환
 */
export function transformApiResponseToChartData(
  apiData: Record<string, unknown>[],
  config: ChartConfig,
): ChartData | null {
  // API 응답을 QueryResult 형식으로 변환
  if (!apiData || apiData.length === 0 || !config.xAxis) {
    return null;
  }

  const queryResult: QueryResult = {
    columns: Object.keys(apiData[0]),
    rows: apiData,
    totalRows: apiData.length,
    executionTime: 0,
  };

  return transformQueryResultToChartData(queryResult, config);
}
