import type { Clarizen, EntityDescription, EntityId } from "@arco/clarizen-lib";
import { buildWhereCondition, type EntityFilter } from "./filter.js";
import { resolveDisplayField } from "./resolve-display-field.js";

export interface EntityRecord {
  id: EntityId;
  displayName?: string;
}

const PAGE_SIZE = 5000;

export async function fetchAllEntities(
  clarizen: Clarizen,
  typeName: string,
  entityMeta: EntityDescription,
  filter: EntityFilter = { kind: "all" },
  onProgress?: (count: number) => void,
): Promise<EntityRecord[]> {
  const displayField = resolveDisplayField(entityMeta);
  const where = buildWhereCondition(filter);
  const records: EntityRecord[] = [];
  let from = 0;

  while (true) {
    const result = await clarizen.data.entityQuery({
      typeName,
      fields: [displayField],
      ...(where ? { where } : {}),
      paging: { from, limit: PAGE_SIZE },
    });

    for (const entity of result.entities) {
      if (!entity.id) continue;
      const displayName = extractDisplayName(
        entity as Record<string, unknown>,
        displayField,
      );
      records.push({ id: entity.id, displayName });
    }

    onProgress?.(records.length);

    if (!result.paging?.hasMore) break;
    from += PAGE_SIZE;
  }

  return records;
}

function extractDisplayName(
  entity: Record<string, unknown>,
  displayField: string,
): string | undefined {
  const objectFields = entity.objectFields as Record<string, unknown> | undefined;
  const value = entity[displayField] ?? objectFields?.[displayField];
  if (value === null || value === undefined) return undefined;
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
    return String(value);
  }
  if (typeof value === "object" && value !== null && "name" in value) {
    const name = (value as { name?: unknown }).name;
    if (name !== null && name !== undefined) return String(name);
  }
  return undefined;
}
