/*
 * Copyright 2025 Palantir Technologies, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { useOsdkClient } from "@osdk/react";
import { useCallback, useMemo } from "react";
import { DEFAULT_PAGE_SIZE, SELECTION_COLUMN_ID } from "../utils/constants.js";
import { buildPagedObjectSets, extractFunctionLocators } from "../utils/functionColumns.js";
import { buildSnapshotRow, DEFAULT_SNAPSHOT_ROW_LIMIT, fetchFunctionColumnValues } from "../utils/objectTableSnapshot.js";
/**
 * Builds the {@link ObjectTableHandle} exposed via `ObjectTable`'s `tableRef`.
 *
 * `getSnapshot` reads the table's currently visible columns to decide what to
 * export, rejects up front when the set's `totalCount` exceeds `rowLimit`,
 * otherwise paginates the entire resolved object set, and resolves
 * function-backed column values for the loaded rows.
 */
export function useObjectTableSnapshot({
  objectOrInterfaceType,
  table,
  columnDefinitions,
  objectSet,
  pageSize = DEFAULT_PAGE_SIZE,
  totalCount,
  orderBy
}) {
  const client = useOsdkClient();
  const functionLocators = useMemo(() => extractFunctionLocators(columnDefinitions), [columnDefinitions]);
  const customColumnIds = useMemo(() => new Set(columnDefinitions?.filter(definition => definition.locator.type === "custom").map(definition => String(definition.locator.id)) ?? []), [columnDefinitions]);
  const getSnapshot = useCallback(async options => {
    const rowLimit = options?.rowLimit ?? DEFAULT_SNAPSHOT_ROW_LIMIT;
    const rowLimitExceededError = `Error in getSnapshot: total row count exceeds row limit of ${rowLimit}.`;

    // Fail fast when the caller's row cap is smaller than the matching set.
    // `totalCount` is only available once the list payload has resolved; we
    // skip the check otherwise rather than guess.
    if (totalCount != null) {
      const total = Number(totalCount);
      if (Number.isFinite(total) && total > rowLimit) {
        return Promise.reject(rowLimitExceededError);
      }
    }
    const columns = table.getVisibleLeafColumns().filter(column => column.id !== SELECTION_COLUMN_ID && !customColumnIds.has(column.id)).map(column => {
      const meta = column.columnDef.meta;
      const header = column.columnDef.header;
      const name = typeof header === "string" ? header : meta?.columnName ?? column.id;
      return {
        id: column.id,
        name
      };
    });
    const columnIds = columns.map(column => column.id);
    const columnIdsSet = new Set(columnIds);
    const loadedObjects = [];
    if (objectSet != null && columnIds.length > 0 && rowLimit > 0) {
      for await (const object of objectSet.asyncIter({
        $orderBy: orderBy
      })) {
        loadedObjects.push(object);
        // Bound the in-memory load even when `totalCount` was unavailable for
        // the fail-fast check above: once we've pulled more rows than the
        // caller allows, stop and reject rather than draining the whole set.
        if (loadedObjects.length > rowLimit) {
          return Promise.reject(rowLimitExceededError);
        }
      }
    }
    const visibleFunctionLocators = functionLocators.filter(locator => columnIdsSet.has(String(locator.id)));
    let functionColumnValues;
    if (visibleFunctionLocators.length > 0 && loadedObjects.length > 0) {
      const pages = buildPagedObjectSets(client, objectOrInterfaceType, loadedObjects, pageSize);
      if (pages.length > 0) {
        functionColumnValues = await fetchFunctionColumnValues(visibleFunctionLocators, pages, (queryDefinition, params) => client(queryDefinition).executeFunction(params));
      }
    }
    const rows = loadedObjects.map(object => buildSnapshotRow(object, columnIds, visibleFunctionLocators, functionColumnValues));
    return {
      columns,
      rows,
      totalCount
    };
  }, [table, objectSet, objectOrInterfaceType, functionLocators, customColumnIds, client, pageSize, totalCount, orderBy]);
  return useMemo(() => ({
    getSnapshot
  }), [getSnapshot]);
}
//# sourceMappingURL=useObjectTableSnapshot.js.map