import * as React from "react";

import { cn } from "@/lib/utils";

export type KumoTableLayout = "auto" | "fixed";
export type KumoTableRowVariant = "default" | "selected";

type TableProps = React.TableHTMLAttributes<HTMLTableElement> & {
  layout?: KumoTableLayout;
};

type TableHeaderProps = React.HTMLAttributes<HTMLTableSectionElement> & {
  sticky?: boolean;
  variant?: "default" | "compact";
};

type StickyColumn = "left" | "right";

type TableHeadProps = React.ThHTMLAttributes<HTMLTableCellElement> & {
  sticky?: StickyColumn;
};

type TableRowProps = React.HTMLAttributes<HTMLTableRowElement> & {
  variant?: KumoTableRowVariant;
};

type TableCellProps = React.TdHTMLAttributes<HTMLTableCellElement> & {
  sticky?: StickyColumn;
};

function stickyClass(sticky?: StickyColumn): string | undefined {
  if (sticky === "left") {
    return "sticky left-0 z-10 bg-kumo-base";
  }

  if (sticky === "right") {
    return "sticky right-0 z-10 bg-kumo-base";
  }

  return undefined;
}

const TableRoot = React.forwardRef<HTMLTableElement, TableProps>(function Table(
  { className, layout = "auto", ...props },
  ref,
): React.ReactElement {
  return (
    <table
      ref={ref}
      className={cn("teatea-table border-collapse text-kumo-default", layout === "fixed" && "table-fixed", className)}
      {...props}
    />
  );
});

const TableHeader = React.forwardRef<HTMLTableSectionElement, TableHeaderProps>(function TableHeader(
  { className, sticky, variant, ...props },
  ref,
): React.ReactElement {
  return (
    <thead
      ref={ref}
      className={cn(
        "border-b border-kumo-line",
        sticky && "sticky top-0 z-20",
        variant === "compact" && "text-xs",
        className,
      )}
      {...props}
    />
  );
});

const TableHead = React.forwardRef<HTMLTableCellElement, TableHeadProps>(function TableHead(
  { className, sticky, ...props },
  ref,
): React.ReactElement {
  return (
    <th
      ref={ref}
      className={cn("text-left font-medium text-kumo-subtle", stickyClass(sticky), className)}
      {...props}
    />
  );
});

const TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(
  function TableBody({ className, ...props }, ref): React.ReactElement {
    return <tbody ref={ref} className={cn("divide-y divide-kumo-line", className)} {...props} />;
  },
);

const TableRow = React.forwardRef<HTMLTableRowElement, TableRowProps>(function TableRow(
  { className, variant = "default", ...props },
  ref,
): React.ReactElement {
  return (
    <tr
      ref={ref}
      className={cn(
        "transition-colors",
        variant === "selected" && "bg-kumo-tint",
        className,
      )}
      {...props}
    />
  );
});

const TableCell = React.forwardRef<HTMLTableCellElement, TableCellProps>(function TableCell(
  { className, sticky, ...props },
  ref,
): React.ReactElement {
  return <td ref={ref} className={cn("text-kumo-default", stickyClass(sticky), className)} {...props} />;
});

const TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(
  function TableFooter({ className, ...props }, ref): React.ReactElement {
    return <tfoot ref={ref} className={cn("border-t border-kumo-line bg-kumo-recessed", className)} {...props} />;
  },
);

const TableResizeHandle = React.forwardRef<HTMLButtonElement, React.ButtonHTMLAttributes<HTMLButtonElement>>(
  function TableResizeHandle({ className, type = "button", ...props }, ref): React.ReactElement {
    return (
      <button
        ref={ref}
        className={cn("h-full w-1 cursor-col-resize bg-transparent hover:bg-kumo-line", className)}
        type={type}
        {...props}
      />
    );
  },
);

type TableComponent = typeof TableRoot & {
  Header: typeof TableHeader;
  Head: typeof TableHead;
  Row: typeof TableRow;
  Body: typeof TableBody;
  Cell: typeof TableCell;
  Footer: typeof TableFooter;
  ResizeHandle: typeof TableResizeHandle;
};

export const Table = Object.assign(TableRoot, {
  Header: TableHeader,
  Head: TableHead,
  Row: TableRow,
  Body: TableBody,
  Cell: TableCell,
  Footer: TableFooter,
  ResizeHandle: TableResizeHandle,
}) satisfies TableComponent;
