"use client";

import {
  FormEvent,
  ReactNode,
  useMemo,
  type ComponentPropsWithoutRef,
} from "react";
import type { LucideIcon } from "lucide-react";
import { Plus, RotateCcw, Search } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Pagination,
  PaginationContent,
  PaginationEllipsis,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { cn } from "@/lib/utils";

export type TableQueryColumn<T extends Record<string, unknown> = Record<string, unknown>> = {
  key: keyof T | string;
  label: string;
  width?: string;
  minWidth?: string;
  maxWidth?: string;
  align?: "left" | "center" | "right";
  className?: string;
  headerClassName?: string;
  /** 默认 true：单行省略；与 wrap 互斥时 wrap 优先 */
  ellipsis?: boolean;
  /** true 时允许多行换行展示 */
  wrap?: boolean;
  render?: (value: unknown, row: T, index: number) => ReactNode;
};

export type TableQueryPagination = {
  page: number;
  pageSize: number;
  total: number;
  totalPages?: number;
  hasNext?: boolean;
  hasPrev?: boolean;
};

export type QueryFormContext = {
  queriedAt?: Date | string | number | null;
};

export type QueryFormSectionProps = {
  queryForm?: ReactNode;
  renderQueryForm?: (context: QueryFormContext) => ReactNode;
  onSearch?: () => void;
  onReset?: () => void;
  /** 最近一次查询时间，展示在操作区左侧 */
  queriedAt?: Date | string | number | null;
  showQueriedAt?: boolean;
  queryActions?: ReactNode;
  hideDefaultActions?: boolean;
  /** brapi：与 crop 等字典页一致的简洁搜索栏；card：卡片式查询区 */
  variant?: "brapi" | "card";
  className?: string;
  formClassName?: string;
  actionsClassName?: string;
};

export type TableQueryStatBadge = {
  label: string;
  value: number | string;
  className?: string;
};

export type TableQueryPageHeaderProps = {
  title?: ReactNode;
  description?: ReactNode;
  icon?: LucideIcon;
  iconBg?: string;
  /** 右侧操作区，如「新增」按钮；优先级高于 addLabel */
  actions?: ReactNode;
  /** 快捷渲染右侧新增按钮 */
  addLabel?: string;
  onAdd?: () => void;
  stats?: TableQueryStatBadge[];
  className?: string;
  headerClassName?: string;
  titleClassName?: string;
  descriptionClassName?: string;
};

export type TableQueryPanelProps<T extends Record<string, unknown> = Record<string, unknown>> =
  QueryFormSectionProps &
    TableQueryPageHeaderProps & {
    columns: TableQueryColumn<T>[];
    data: T[];
    loading?: boolean;
    emptyText?: string;
    rowKey?: keyof T | ((row: T, index: number) => string);
    pagination?: TableQueryPagination;
    pageSizeOptions?: number[];
    onPageChange?: (page: number) => void;
    onPageSizeChange?: (pageSize: number) => void;
    /** crop 字典页风格，默认 brapi */
    variant?: "brapi" | "card";
    className?: string;
    tableClassName?: string;
    tableWrapperClassName?: string;
    paginationClassName?: string;
    showIndex?: boolean;
    indexLabel?: string;
    toolbar?: ReactNode;
  };

function formatQueriedAt(value: Date | string | number): string {
  const date = value instanceof Date ? value : new Date(value);
  if (Number.isNaN(date.getTime())) {
    return String(value);
  }

  return date.toLocaleString("zh-CN", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
  });
}

function getCellText(value: unknown) {
  if (value === null || value === undefined || value === "") {
    return "-";
  }
  return String(value);
}

function alignClass(align?: TableQueryColumn["align"]) {
  if (align === "center") return "text-center";
  if (align === "right") return "text-right";
  return "text-left";
}

function getRowKey<T extends Record<string, unknown>>(
  row: T,
  index: number,
  rowKey?: TableQueryPanelProps<T>["rowKey"]
) {
  if (typeof rowKey === "function") return rowKey(row, index);
  if (rowKey) return String(row[rowKey] ?? index);
  return String(row.id ?? row.key ?? index);
}

function getPageItems(currentPage: number, totalPages: number): Array<number | "ellipsis"> {
  if (totalPages <= 7) {
    return Array.from({ length: totalPages }, (_, index) => index + 1);
  }

  const items: Array<number | "ellipsis"> = [1];

  if (currentPage > 3) {
    items.push("ellipsis");
  }

  const start = Math.max(2, currentPage - 1);
  const end = Math.min(totalPages - 1, currentPage + 1);

  for (let page = start; page <= end; page += 1) {
    items.push(page);
  }

  if (currentPage < totalPages - 2) {
    items.push("ellipsis");
  }

  items.push(totalPages);
  return items;
}

export function TableQueryPageHeader({
  title,
  description,
  icon: Icon,
  iconBg,
  actions,
  addLabel,
  onAdd,
  stats,
  className,
  headerClassName,
  titleClassName,
  descriptionClassName,
}: TableQueryPageHeaderProps) {
  const headerActions =
    actions ??
    (addLabel ? (
      <Button type="button" onClick={onAdd} className="shrink-0 gap-2">
        <Plus className="h-4 w-4" />
        {addLabel}
      </Button>
    ) : null);

  const showHeader = title || description || headerActions || Icon;
  const showStats = Boolean(stats?.length);

  if (!showHeader && !showStats) {
    return null;
  }

  return (
    <>
      {showHeader ? (
        <div
          className={cn(
            "mb-5 flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between",
            className,
            headerClassName
          )}
        >
          <div className="flex min-w-0 items-center gap-3">
            {Icon ? (
              <div
                className={cn(
                  "shrink-0 rounded-xl p-2.5",
                  iconBg ?? "bg-gradient-to-br from-slate-600 to-slate-800"
                )}
              >
                <Icon className="h-5 w-5 text-white" />
              </div>
            ) : null}
            <div className="min-w-0 space-y-1">
              {title ? (
                <h2
                  className={cn(
                    "truncate text-lg font-semibold text-slate-900 dark:text-slate-50",
                    titleClassName
                  )}
                  title={typeof title === "string" ? title : undefined}
                >
                  {title}
                </h2>
              ) : null}
              {description ? (
                <p
                  className={cn(
                    "text-sm leading-6 text-slate-500 dark:text-slate-400",
                    descriptionClassName
                  )}
                >
                  {description}
                </p>
              ) : null}
            </div>
          </div>
          {headerActions ? <div className="shrink-0">{headerActions}</div> : null}
        </div>
      ) : null}

      {showStats ? (
        <div className="mb-4 flex flex-wrap gap-2">
          {stats!.map((stat) => (
            <span
              key={stat.label}
              className={cn(
                "rounded-full px-3 py-1 text-xs",
                stat.className ??
                  "bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-300"
              )}
            >
              {stat.value} {stat.label}
            </span>
          ))}
        </div>
      ) : null}
    </>
  );
}

export function QueryFormSection({
  queryForm,
  renderQueryForm,
  onSearch,
  onReset,
  queriedAt,
  showQueriedAt = true,
  queryActions,
  hideDefaultActions = false,
  variant = "brapi",
  className,
  formClassName,
  actionsClassName,
}: QueryFormSectionProps) {
  const showActions = !hideDefaultActions && (onSearch || onReset || queryActions);
  const queryContent = queryForm ?? renderQueryForm?.({ queriedAt });

  if (!queryContent && !showActions) {
    return null;
  }

  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    onSearch?.();
  };

  if (variant === "brapi") {
    return (
      <form
        onSubmit={handleSubmit}
        className={cn("mb-4", className, formClassName)}
      >
        <div className="flex flex-col gap-3 sm:flex-row sm:items-center">
          {queryContent ? <div className="min-w-0 flex-1">{queryContent}</div> : null}
          {showActions ? (
            <div className={cn("flex shrink-0 flex-wrap justify-end gap-2", actionsClassName)}>
              {queryActions}
              {onReset ? (
                <Button type="button" variant="outline" size="sm" onClick={onReset}>
                  <RotateCcw className="h-4 w-4" />
                  重置
                </Button>
              ) : null}
              {onSearch ? (
                <Button type="submit" size="sm">
                  <Search className="h-4 w-4" />
                  查询
                </Button>
              ) : null}
            </div>
          ) : null}
        </div>
        {showQueriedAt && queriedAt ? (
          <p className="mt-2 text-xs text-slate-400">
            最近查询：{formatQueriedAt(queriedAt)}
          </p>
        ) : null}
      </form>
    );
  }

  return (
    <form
      onSubmit={handleSubmit}
      className={cn(
        "rounded-2xl border border-border bg-card p-4 shadow-sm",
        className,
        formClassName
      )}
    >
      {queryContent ? <div className="min-w-0">{queryContent}</div> : null}

      {showActions ? (
        <div
          className={cn(
            "mt-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
            !queryContent && "mt-0",
            actionsClassName
          )}
        >
          {showQueriedAt && queriedAt ? (
            <p className="text-xs text-muted-foreground">
              最近查询：{formatQueriedAt(queriedAt)}
            </p>
          ) : (
            <span className="hidden sm:block" />
          )}

          <div className="flex flex-wrap justify-end gap-2">
            {queryActions}
            {onReset ? (
              <Button type="button" variant="outline" onClick={onReset}>
                <RotateCcw className="h-4 w-4" />
                重置
              </Button>
            ) : null}
            {onSearch ? (
              <Button type="submit">
                <Search className="h-4 w-4" />
                查询
              </Button>
            ) : null}
          </div>
        </div>
      ) : null}
    </form>
  );
}

type TableQueryPaginationBarProps = {
  pagination: TableQueryPagination;
  pageSizeOptions: number[];
  onPageChange?: (page: number) => void;
  onPageSizeChange?: (pageSize: number) => void;
  className?: string;
};

function TableQueryPaginationBar({
  pagination,
  pageSizeOptions,
  onPageChange,
  onPageSizeChange,
  className,
  variant = "brapi",
}: TableQueryPaginationBarProps & { variant?: "brapi" | "card" }) {
  const totalPages = Math.max(
    1,
    pagination.totalPages ?? Math.ceil(pagination.total / Math.max(pagination.pageSize, 1))
  );
  const currentPage = pagination.page;
  const hasPrev = pagination.hasPrev ?? currentPage > 1;
  const hasNext = pagination.hasNext ?? currentPage < totalPages;

  if (variant === "brapi") {
    const visiblePages = Array.from({ length: Math.min(totalPages, 5) }, (_, index) => index + 1);

    return (
      <div
        className={cn(
          "mt-3 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
          className
        )}
      >
        <p className="text-xs text-slate-400">
          共 {pagination.total} 条记录，第 {currentPage}/{totalPages} 页
        </p>
        <div className="flex items-center gap-3">
          <Select
            value={String(pagination.pageSize)}
            onValueChange={(value) => onPageSizeChange?.(Number(value))}
          >
            <SelectTrigger className="h-8 w-[110px]">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              {pageSizeOptions.map((size) => (
                <SelectItem key={size} value={String(size)}>
                  {size} / 页
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Pagination className="mx-0 w-auto justify-end">
            <PaginationContent>
              <PaginationItem>
                <PaginationPrevious
                  onClick={() => onPageChange?.(Math.max(1, currentPage - 1))}
                  disabled={!hasPrev}
                />
              </PaginationItem>
              {visiblePages.map((pageNumber) => (
                <PaginationItem key={pageNumber}>
                  <PaginationLink
                    isActive={pageNumber === currentPage}
                    onClick={() => onPageChange?.(pageNumber)}
                  >
                    {pageNumber}
                  </PaginationLink>
                </PaginationItem>
              ))}
              <PaginationItem>
                <PaginationNext
                  onClick={() => onPageChange?.(Math.min(totalPages, currentPage + 1))}
                  disabled={!hasNext}
                />
              </PaginationItem>
            </PaginationContent>
          </Pagination>
        </div>
      </div>
    );
  }

  const pageItems = getPageItems(currentPage, totalPages);

  return (
    <div
      className={cn(
        "flex flex-col gap-3 border-t border-border px-4 py-3 text-sm text-muted-foreground sm:flex-row sm:items-center sm:justify-between",
        className
      )}
    >
      <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
        <span>共 {pagination.total} 条</span>
        <span className="hidden sm:inline">/</span>
        <span>
          第 {currentPage} / {totalPages} 页
        </span>
      </div>

      <div className="flex flex-wrap items-center gap-2">
        <Select
          value={String(pagination.pageSize)}
          onValueChange={(value) => onPageSizeChange?.(Number(value))}
        >
          <SelectTrigger className="h-9 w-[108px] bg-background">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            {pageSizeOptions.map((size) => (
              <SelectItem key={size} value={String(size)}>
                {size} 条/页
              </SelectItem>
            ))}
          </SelectContent>
        </Select>

        <Pagination className="mx-0 w-auto justify-end">
          <PaginationContent>
            <PaginationItem>
              <PaginationPrevious
                onClick={() => onPageChange?.(Math.max(1, currentPage - 1))}
                disabled={!hasPrev}
              />
            </PaginationItem>

            {pageItems.map((item, index) =>
              item === "ellipsis" ? (
                <PaginationItem key={`ellipsis-${index}`}>
                  <PaginationEllipsis />
                </PaginationItem>
              ) : (
                <PaginationItem key={item}>
                  <PaginationLink
                    isActive={item === currentPage}
                    onClick={() => onPageChange?.(item)}
                  >
                    {item}
                  </PaginationLink>
                </PaginationItem>
              )
            )}

            <PaginationItem>
              <PaginationNext
                onClick={() => onPageChange?.(Math.min(totalPages, currentPage + 1))}
                disabled={!hasNext}
              />
            </PaginationItem>
          </PaginationContent>
        </Pagination>
      </div>
    </div>
  );
}

export function TableQueryPanel<T extends Record<string, unknown> = Record<string, unknown>>({
  title,
  description,
  icon,
  iconBg,
  actions,
  addLabel,
  onAdd,
  stats,
  headerClassName,
  titleClassName,
  descriptionClassName,
  queryForm,
  renderQueryForm,
  onSearch,
  onReset,
  queriedAt,
  showQueriedAt,
  queryActions,
  hideDefaultActions,
  variant = "brapi",
  className,
  formClassName,
  actionsClassName,
  columns,
  data,
  loading = false,
  emptyText = "暂无数据",
  rowKey,
  pagination,
  pageSizeOptions = [10, 20, 50],
  onPageChange,
  onPageSizeChange,
  tableClassName,
  tableWrapperClassName,
  paginationClassName,
  showIndex = false,
  indexLabel = "#",
  toolbar,
}: TableQueryPanelProps<T>) {
  const isBrapi = variant === "brapi";

  const tableMinWidth = useMemo(() => {
    if (!isBrapi || !columns.length) return undefined;

    const total = columns.reduce((sum, column) => {
      const raw = column.width || column.minWidth || "160px";
      const number = Number.parseInt(raw, 10);
      return sum + (Number.isFinite(number) ? number : 160);
    }, 0);

    return `${Math.max(total + (showIndex ? 56 : 0), 720)}px`;
  }, [columns, isBrapi, showIndex]);

  const visibleColumnCount = columns.length + (showIndex ? 1 : 0);

  return (
    <section className={cn(isBrapi ? "flex min-h-0 flex-1 flex-col" : "space-y-4", className)}>
      <TableQueryPageHeader
        title={title}
        description={description}
        icon={icon}
        iconBg={iconBg}
        actions={actions}
        addLabel={addLabel}
        onAdd={onAdd}
        stats={stats}
        className={headerClassName}
        titleClassName={titleClassName}
        descriptionClassName={descriptionClassName}
      />

      <QueryFormSection
        queryForm={queryForm}
        renderQueryForm={renderQueryForm}
        onSearch={onSearch}
        onReset={onReset}
        queriedAt={queriedAt}
        showQueriedAt={showQueriedAt}
        queryActions={queryActions}
        hideDefaultActions={hideDefaultActions}
        variant={variant}
        formClassName={formClassName}
        actionsClassName={actionsClassName}
      />

      {toolbar ? <div className="mb-4 min-w-0">{toolbar}</div> : null}

      <div
        className={cn(
          isBrapi
            ? "min-h-0 flex-1 overflow-hidden rounded-xl border border-slate-200 bg-white transition-colors duration-300 ease-out dark:border-slate-800 dark:bg-slate-950"
            : "overflow-hidden rounded-2xl border border-border bg-card shadow-sm",
          tableWrapperClassName
        )}
      >
        <Table
          className={cn(!isBrapi && "table-fixed", tableClassName)}
          style={tableMinWidth ? { minWidth: tableMinWidth } : undefined}
        >
          <TableHeader>
            <TableRow
              className={
                isBrapi
                  ? "border-slate-200 bg-slate-50 transition-colors duration-300 ease-out dark:border-slate-800 dark:bg-slate-900"
                  : "bg-muted/70 hover:bg-muted/70"
              }
            >
              {showIndex ? (
                <TableHead
                  className={
                    isBrapi
                      ? "w-10 text-xs font-medium text-slate-400 dark:text-slate-500"
                      : "h-11 w-14 px-4 text-xs font-bold text-muted-foreground"
                  }
                >
                  {indexLabel}
                </TableHead>
              ) : null}
              {columns.map((column) => (
                <TableHead
                  key={String(column.key)}
                  className={cn(
                    isBrapi
                      ? "text-xs font-medium text-slate-500 transition-colors duration-300 ease-out dark:text-slate-300"
                      : "h-11 whitespace-nowrap px-4 text-xs font-bold text-muted-foreground",
                    alignClass(column.align),
                    column.headerClassName
                  )}
                  style={{
                    width: column.width,
                    minWidth: column.minWidth,
                    maxWidth: column.maxWidth,
                  }}
                  title={column.label}
                >
                  {isBrapi ? column.label : <span className="block truncate">{column.label}</span>}
                </TableHead>
              ))}
            </TableRow>
          </TableHeader>

          <TableBody>
            {loading ? (
              <TableRow className={isBrapi ? "border-slate-100 dark:border-slate-800" : undefined}>
                <TableCell
                  colSpan={visibleColumnCount}
                  className={cn(
                    "h-32 text-center text-sm",
                    isBrapi ? "text-slate-400" : "text-muted-foreground"
                  )}
                >
                  正在加载数据...
                </TableCell>
              </TableRow>
            ) : data.length === 0 ? (
              <TableRow className={isBrapi ? "border-slate-100 dark:border-slate-800" : undefined}>
                <TableCell
                  colSpan={visibleColumnCount}
                  className={cn(
                    isBrapi ? "py-16 text-center text-sm text-slate-400" : "h-32 text-center text-sm text-muted-foreground"
                  )}
                >
                  {emptyText}
                </TableCell>
              </TableRow>
            ) : (
              data.map((row, rowIndex) => (
                <TableRow
                  key={getRowKey(row, rowIndex, rowKey)}
                  className={
                    isBrapi
                      ? "border-slate-100 hover:bg-slate-50/80 dark:border-slate-800 dark:hover:bg-slate-900/80"
                      : undefined
                  }
                >
                  {showIndex ? (
                    <TableCell className={isBrapi ? "text-xs text-slate-400" : "px-4 py-3 text-xs text-muted-foreground"}>
                      {pagination
                        ? (pagination.page - 1) * pagination.pageSize + rowIndex + 1
                        : rowIndex + 1}
                    </TableCell>
                  ) : null}
                  {columns.map((column) => {
                    const value = row[column.key as keyof T];
                    const content = column.render
                      ? column.render(value, row, rowIndex)
                      : getCellText(value);
                    const shouldWrap = isBrapi ? column.wrap !== false : column.wrap === true;
                    const shouldEllipsis = !shouldWrap && column.ellipsis !== false;
                    const titleText =
                      typeof content === "string" || typeof content === "number"
                        ? String(content)
                        : getCellText(value);

                    return (
                      <TableCell
                        key={String(column.key)}
                        className={cn(
                          isBrapi
                            ? "max-w-[24rem] whitespace-normal break-words text-sm text-slate-700 dark:text-slate-200"
                            : "px-4 py-3 text-sm align-top",
                          !isBrapi && alignClass(column.align),
                          !isBrapi && shouldWrap && "whitespace-normal break-words",
                          !isBrapi && shouldEllipsis && "max-w-0",
                          column.className
                        )}
                        style={
                          isBrapi
                            ? undefined
                            : {
                                width: column.width,
                                minWidth: column.minWidth,
                                maxWidth: column.maxWidth,
                              }
                        }
                        title={shouldEllipsis ? titleText : undefined}
                      >
                        {shouldEllipsis ? (
                          <div className="truncate">{content}</div>
                        ) : isBrapi && (value === null || value === undefined || value === "") && !column.render ? (
                          <span className="text-slate-300">—</span>
                        ) : (
                          content
                        )}
                      </TableCell>
                    );
                  })}
                </TableRow>
              ))
            )}
          </TableBody>
        </Table>
      </div>

      {pagination ? (
        <TableQueryPaginationBar
          pagination={pagination}
          pageSizeOptions={pageSizeOptions}
          onPageChange={onPageChange}
          onPageSizeChange={onPageSizeChange}
          className={paginationClassName}
          variant={variant}
        />
      ) : null}
    </section>
  );
}

/** @deprecated 请改用 QueryFormSection 或 TableQueryPanel */
export function CropQueryForm(props: ComponentPropsWithoutRef<typeof QueryFormSection>) {
  return <QueryFormSection {...props} />;
}
