export type SortDirection = "asc" | "desc";

export function nextSort<T extends string>(
  current: { column: T; direction: SortDirection } | null,
  column: T,
): { column: T; direction: SortDirection } {
  if (current?.column === column) {
    return { column, direction: current.direction === "asc" ? "desc" : "asc" };
  }
  return { column, direction: "asc" };
}

export function sortIndicator(
  current: { column: string; direction: SortDirection } | null,
  column: string,
): string {
  if (current?.column !== column) return "";
  return current.direction === "asc" ? " ↑" : " ↓";
}

export function compareText(a: string, b: string, direction: SortDirection): number {
  const result = a.localeCompare(b, undefined, { sensitivity: "base", numeric: true });
  return direction === "asc" ? result : -result;
}

export function compareNumber(
  a: number | null | undefined,
  b: number | null | undefined,
  direction: SortDirection,
): number {
  const aMissing = a == null || Number.isNaN(a);
  const bMissing = b == null || Number.isNaN(b);
  if (aMissing && bMissing) return 0;
  if (aMissing) return 1;
  if (bMissing) return -1;
  const result = a - b;
  return direction === "asc" ? result : -result;
}

export function sortBy<T>(
  items: readonly T[],
  direction: SortDirection,
  getValue: (item: T) => string | number | null | undefined,
): T[] {
  return [...items].sort((left, right) => {
    const a = getValue(left);
    const b = getValue(right);
    if (typeof a === "number" || typeof b === "number") {
      return compareNumber(typeof a === "number" ? a : null, typeof b === "number" ? b : null, direction);
    }
    return compareText(String(a ?? ""), String(b ?? ""), direction);
  });
}
