import * as React from "react";
import { Download } from "lucide-react";
import { Button, type ButtonProps } from "@/components/ui/button";
import { defaultCsvFilename, downloadCsv, toCsv, type CsvColumn } from "@/lib/csv";
import { cn } from "@/lib/utils";

export type ExportCsvButtonProps<T> = {
  /** Rows to serialize. Empty rows → button disabled with a tooltip. */
  rows: T[];
  /** Column descriptors (header + per-row extractor). */
  columns: CsvColumn<T>[];
  /** Override the download filename. Defaults to `{prefix}-{YYYY-MM-DD}.csv`. */
  filename?: string;
  /** Filename prefix when no explicit filename is provided. */
  filenamePrefix?: string;
  /** Visible label. Defaults to "Export CSV". */
  label?: string;
  /** Render an icon-only button with `aria-label="Export as CSV"`. */
  iconOnly?: boolean;
  /** Forwarded to the underlying Button. */
  disabled?: boolean;
  /** Forwarded to the underlying Button for layout tweaks. */
  className?: string;
} & Omit<ButtonProps, "onClick" | "children" | "disabled">;

/**
 * One-line CSV export: a page passes `rows` + `columns`, we serialize and
 * trigger a download. Disabled (with a tooltip) when there's nothing to
 * export. The "Exporting..." state is decorative — `downloadCsv` is sync —
 * but it gives the click tactile feedback so the action feels deliberate.
 */
export function ExportCsvButton<T>({
  rows,
  columns,
  filename,
  filenamePrefix = "export",
  label = "Export CSV",
  iconOnly = false,
  disabled,
  className,
  variant = "outline",
  size,
  type = "button",
  ...buttonProps
}: ExportCsvButtonProps<T>) {
  const [busy, setBusy] = React.useState(false);
  const nothingToExport = rows.length === 0;
  const isDisabled = disabled || nothingToExport;

  const handleClick = React.useCallback(() => {
    if (isDisabled) return;
    const csv = toCsv(rows, columns);
    const finalName = filename ?? defaultCsvFilename(filenamePrefix);
    setBusy(true);
    try {
      downloadCsv(finalName, csv);
    } finally {
      // Reset on the next tick so the user sees the busy state flash.
      queueMicrotask(() => setBusy(false));
    }
  }, [columns, filename, filenamePrefix, isDisabled, rows]);

  const tooltip = nothingToExport ? "No rows to export" : undefined;

  return (
    <Button
      variant={variant}
      size={size ?? (iconOnly ? "icon" : "sm")}
      type={type}
      disabled={isDisabled || busy}
      onClick={handleClick}
      title={tooltip}
      aria-label={iconOnly ? "Export as CSV" : undefined}
      data-busy={busy || undefined}
      className={cn(busy && "cursor-progress", className)}
      {...buttonProps}
    >
      <Download className="h-3.5 w-3.5" strokeWidth={1.75} aria-hidden />
      {iconOnly ? null : (
        <span>{busy ? "Exporting…" : label}</span>
      )}
    </Button>
  );
}