'use client';

import type { ColumnDef } from '@tanstack/react-table';
import { useMemo } from 'react';

import * as columnBuilders from '@/app/components/ui/data-table/column-builders';
import type { Doc, TableNames } from '@/convex/_generated/dataModel';
import { useT } from '@/lib/i18n/client';
import type { Namespace } from '@/lib/i18n/types';

type TranslationFn = (key: string) => string;

/**
 * Default first-page size for entity list tables. Exported so route loaders can
 * prime the paginated cache with the same count the table renders.
 */
export const DEFAULT_TABLE_PAGE_SIZE = 20;

interface TableConfigMetadata {
  searchPlaceholder: string;
  stickyLayout: boolean;
  pageSize: number;
  defaultSort: string;
  defaultSortDesc: boolean;
  infiniteScroll: boolean;
}

interface TableConfig<TData> extends TableConfigMetadata {
  columns: ColumnDef<TData>[];
}

interface CreateTableConfigOptions<TTableName extends TableNames> {
  /** Translation namespace for entity-specific translations */
  entityNamespace: Namespace;
  /** Additional translation namespaces (e.g., ['common']) */
  additionalNamespaces?: Namespace[];
  /** Default sort field */
  defaultSort: keyof Doc<TTableName> | (string & {});
  /** Sort descending by default (default: true) */
  defaultSortDesc?: boolean;
  /** Page size (default: {@link DEFAULT_TABLE_PAGE_SIZE}) */
  pageSize?: number;
  /** Enable sticky layout (default: true) */
  stickyLayout?: boolean;
  /** Enable infinite scroll (default: true) */
  infiniteScroll?: boolean;
}

interface ColumnBuilderContext {
  /** Translation function for 'tables' namespace */
  tTables: TranslationFn;
  /** Translation function for entity-specific namespace */
  tEntity: TranslationFn;
  /** Additional translation functions keyed by namespace */
  t: Record<string, TranslationFn>;
  /** Pre-built column builders */
  builders: typeof columnBuilders;
}

type ColumnsBuilder<TData> = (ctx: ColumnBuilderContext) => ColumnDef<TData>[];

/**
 * Factory function to create table configuration hooks.
 *
 * Reduces boilerplate by providing:
 * - Automatic translation hook setup
 * - Pre-built column builders for common patterns
 * - Consistent return type structure
 *
 * @example
 * ```tsx
 * export const useCustomersTableConfig = createTableConfigHook<'customers'>(
 *   {
 *     entityNamespace: 'customers',
 *     defaultSort: '_creationTime',
 *   },
 *   ({ tTables, tEntity, builders }) => [
 *     {
 *       accessorKey: 'name',
 *       header: tTables('headers.name'),
 *       size: 278,
 *       cell: ({ row }) => <NameCell name={row.original.name} />,
 *     },
 *     builders.createSourceColumn(tTables),
 *     builders.createLocaleColumn(),
 *     builders.createCreationTimeColumn(tTables),
 *     builders.createActionsColumn(CustomerRowActions, 'customer'),
 *   ],
 * );
 * ```
 */
export function createTableConfigHook<TTableName extends TableNames>(
  options: CreateTableConfigOptions<TTableName>,
  columnsBuilder: ColumnsBuilder<Doc<TTableName>>,
): () => TableConfig<Doc<TTableName>> {
  const {
    entityNamespace,
    additionalNamespaces = [],
    defaultSort,
    defaultSortDesc = true,
    pageSize = DEFAULT_TABLE_PAGE_SIZE,
    stickyLayout = true,
    infiniteScroll = true,
  } = options;

  return function useTableConfig(): TableConfig<Doc<TTableName>> {
    const { t: tTables } = useT('tables');
    const { t: tEntity } = useT(entityNamespace);

    const t0 = useT(additionalNamespaces[0] ?? 'common');
    const t1 = useT(additionalNamespaces[1] ?? 'common');
    const t2 = useT(additionalNamespaces[2] ?? 'common');

    const extraTranslations = useMemo(() => {
      const result: Record<string, TranslationFn> = {};
      if (additionalNamespaces[0]) result[additionalNamespaces[0]] = t0.t;
      if (additionalNamespaces[1]) result[additionalNamespaces[1]] = t1.t;
      if (additionalNamespaces[2]) result[additionalNamespaces[2]] = t2.t;
      return result;
    }, [t0.t, t1.t, t2.t]);

    const columns = useMemo(
      () =>
        columnsBuilder({
          tTables,
          tEntity,
          t: extraTranslations,
          builders: columnBuilders,
        }),
      [tTables, tEntity, extraTranslations],
    );

    return {
      columns,
      searchPlaceholder: tEntity('searchPlaceholder'),
      stickyLayout,
      pageSize,
      // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- keyof Doc<TTableName> is always string; narrowing for TableConfig interface
      defaultSort: defaultSort as string,
      defaultSortDesc,
      infiniteScroll,
    };
  };
}

export type { TableConfig, CreateTableConfigOptions };
