/**
 * PivotGrid 집계 함수 유틸리티
 * 다양한 집계 연산을 수행합니다.
 */

import { getFormatRules } from "@/lib/formatting";

import { AggregationType, PivotFieldFormat } from "../types";

// ==================== 집계 함수 ====================

/**
 * 합계 계산
 */
export function sum(values: number[]): number {
  return values.reduce((acc, val) => acc + (val || 0), 0);
}

/**
 * 개수 계산
 */
export function count(values: any[]): number {
  return values.length;
}

/**
 * 평균 계산
 */
export function avg(values: number[]): number {
  if (values.length === 0) return 0;
  return sum(values) / values.length;
}

/**
 * 최소값 계산
 */
export function min(values: number[]): number {
  if (values.length === 0) return 0;
  return Math.min(...values.filter((v) => v !== null && v !== undefined));
}

/**
 * 최대값 계산
 */
export function max(values: number[]): number {
  if (values.length === 0) return 0;
  return Math.max(...values.filter((v) => v !== null && v !== undefined));
}

/**
 * 고유값 개수 계산
 */
export function countDistinct(values: any[]): number {
  return new Set(values.filter((v) => v !== null && v !== undefined)).size;
}

/**
 * 집계 타입에 따른 집계 수행
 */
export function aggregate(
  values: any[],
  type: AggregationType = "sum"
): number {
  const numericValues = values
    .map((v) => (typeof v === "number" ? v : parseFloat(v)))
    .filter((v) => !isNaN(v));

  switch (type) {
    case "sum":
      return sum(numericValues);
    case "count":
      return count(values);
    case "avg":
      return avg(numericValues);
    case "min":
      return min(numericValues);
    case "max":
      return max(numericValues);
    case "countDistinct":
      return countDistinct(values);
    default:
      return sum(numericValues);
  }
}

// ==================== 포맷 함수 ====================

/**
 * 숫자 포맷팅
 */
export function formatNumber(
  value: number | null | undefined,
  format?: PivotFieldFormat
): string {
  if (value === null || value === undefined) return "-";

  const {
    type = "number",
    precision = 0,
    thousandSeparator = true,
    prefix = "",
    suffix = "",
  } = format || {};

  let formatted: string;

  const locale = getFormatRules().number.locale;

  switch (type) {
    case "currency":
      formatted = value.toLocaleString(locale, {
        minimumFractionDigits: precision,
        maximumFractionDigits: precision,
      });
      break;

    case "percent":
      formatted = (value * 100).toLocaleString(locale, {
        minimumFractionDigits: precision,
        maximumFractionDigits: precision,
      });
      break;

    case "number":
    default:
      if (thousandSeparator) {
        formatted = value.toLocaleString(locale, {
          minimumFractionDigits: precision,
          maximumFractionDigits: precision,
        });
      } else {
        formatted = value.toFixed(precision);
      }
      break;
  }

  return `${prefix}${formatted}${suffix}`;
}

/**
 * 날짜 포맷팅
 */
export function formatDate(
  value: Date | string | null | undefined,
  format: string = getFormatRules().date.display
): string {
  if (!value) return "-";

  const date = typeof value === "string" ? new Date(value) : value;

  if (isNaN(date.getTime())) return "-";

  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  const quarter = Math.ceil((date.getMonth() + 1) / 3);

  return format
    .replace("YYYY", String(year))
    .replace("MM", month)
    .replace("DD", day)
    .replace("Q", `Q${quarter}`);
}

/**
 * 집계 타입 라벨 반환
 */
export function getAggregationLabel(type: AggregationType): string {
  const labels: Record<AggregationType, string> = {
    sum: "합계",
    count: "개수",
    avg: "평균",
    min: "최소",
    max: "최대",
    countDistinct: "고유값",
  };
  return labels[type] || "합계";
}


