import type { Clarizen, FieldDescription } from "@arco/clarizen-lib";
import { resolveDisplayField } from "../query/resolve-display-field.js";

const PAGE_SIZE = 500;

export interface FieldWithRefs extends FieldDescription {
  referencedEntities?: string[];
}

export interface PickListOption {
  id: string;
  label: string;
}

export function isPickListField(field: FieldWithRefs): boolean {
  return field.presentationType === "PickList";
}

export function getPickListEntityType(field: FieldWithRefs): string | undefined {
  return field.referencedEntities?.[0];
}

function extractLabel(
  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;
}

function idSuffix(id: string): string {
  return id.includes("/") ? id.split("/").pop()! : id;
}

export async function fetchPickListOptions(
  clarizen: Clarizen,
  pickListTypeName: string,
  onProgress?: (count: number) => void,
): Promise<PickListOption[]> {
  const meta = await clarizen.metadata.describeMetadata({
    typeNames: [pickListTypeName],
    flags: ["fields"],
  });
  const entityMeta = meta.entityDescriptions?.find(
    (e) => e.typeName === pickListTypeName,
  );
  if (!entityMeta) {
    throw new Error(`Metadata não encontrada para picklist ${pickListTypeName}.`);
  }

  const displayField = resolveDisplayField(entityMeta);
  const options: PickListOption[] = [];
  let from = 0;

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

    for (const entity of result.entities) {
      if (!entity.id) continue;
      const id = String(entity.id);
      const label =
        extractLabel(entity as Record<string, unknown>, displayField) ??
        idSuffix(id);
      options.push({ id, label });
    }

    onProgress?.(options.length);

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

  return options.sort((a, b) => a.label.localeCompare(b.label, "pt-BR"));
}

export function formatPickListOptionLabel(option: PickListOption): string {
  return `${option.label} (${option.id})`;
}
