import type { ReactNode, ThHTMLAttributes } from "react";
import {
  commonStickyTableHeaderClass,
  commonTableHeadClass,
} from "../../../ui/table";
import type { SortConfig } from "../../utils";

export const sortableTableHeadBaseClassName = commonTableHeadClass;

export const sortableTableHeaderClassName = commonStickyTableHeaderClass;

function SortAscendingIcon() {
  return (
    <svg
      aria-hidden="true"
      viewBox="0 0 24 24"
      className="h-3.5 w-3.5"
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
      strokeLinecap="round"
      strokeLinejoin="round"
    >
      <path d="m12 5-5 5" />
      <path d="m12 5 5 5" />
      <path d="M12 19V5" />
    </svg>
  );
}

function SortDescendingIcon() {
  return (
    <svg
      aria-hidden="true"
      viewBox="0 0 24 24"
      className="h-3.5 w-3.5"
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
      strokeLinecap="round"
      strokeLinejoin="round"
    >
      <path d="m12 19-5-5" />
      <path d="m12 19 5-5" />
      <path d="M12 5v14" />
    </svg>
  );
}

function SortIdleIcon() {
  return (
    <svg
      aria-hidden="true"
      viewBox="0 0 24 24"
      className="ml-1 h-3.5 w-3.5 opacity-50"
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
      strokeLinecap="round"
      strokeLinejoin="round"
    >
      <path d="m7 15 5 5 5-5" />
      <path d="m7 9 5-5 5 5" />
    </svg>
  );
}

type SortableTableHeadAlign = "left" | "center" | "right";

function alignClassName(align: SortableTableHeadAlign) {
  switch (align) {
    case "center":
      return "text-center";
    case "right":
      return "text-right";
    default:
      return "text-left";
  }
}

function buttonAlignClassName(align: SortableTableHeadAlign) {
  switch (align) {
    case "center":
      return "justify-center";
    case "right":
      return "justify-end";
    default:
      return "justify-start";
  }
}

function sortAriaValue(
  isActive: boolean,
  direction: "asc" | "desc" | null,
): ThHTMLAttributes<HTMLTableCellElement>["aria-sort"] {
  if (!isActive || direction === null) {
    return "none";
  }
  return direction === "asc" ? "ascending" : "descending";
}

type SortableTableHeadProps<Key extends string> = Omit<
  ThHTMLAttributes<HTMLTableCellElement>,
  "children"
> & {
  align?: SortableTableHeadAlign;
  contentClassName?: string;
  disabled?: boolean;
  label: ReactNode;
  onSort: (key: Key) => void;
  sortConfig: SortConfig<Key> | null;
  sortKey: Key;
};

export function SortableTableHead<Key extends string>({
  align = "left",
  className = "",
  contentClassName = "",
  disabled = false,
  label,
  onSort,
  sortConfig,
  sortKey,
  ...props
}: SortableTableHeadProps<Key>) {
  const isActive = sortConfig?.key === sortKey;
  const direction = isActive ? (sortConfig?.direction ?? null) : null;

  return (
    <th
      aria-sort={sortAriaValue(isActive, direction)}
      className={[
        sortableTableHeadBaseClassName,
        alignClassName(align),
        disabled ? "" : "transition-colors hover:bg-muted/50",
        className,
      ]
        .filter(Boolean)
        .join(" ")}
      {...props}
    >
      <button
        type="button"
        onClick={() => onSort(sortKey)}
        disabled={disabled}
        className={[
          "flex w-full items-center font-inherit",
          buttonAlignClassName(align),
          disabled ? "cursor-default opacity-70" : "cursor-pointer",
          contentClassName,
        ]
          .filter(Boolean)
          .join(" ")}
      >
        <span>{label}</span>
        {direction === "asc" ? (
          <span className="ml-1 inline-flex">
            <SortAscendingIcon />
          </span>
        ) : direction === "desc" ? (
          <span className="ml-1 inline-flex">
            <SortDescendingIcon />
          </span>
        ) : (
          <SortIdleIcon />
        )}
      </button>
    </th>
  );
}
