import type { Clarizen, JsonValue } from "@arco/clarizen-lib"; import { isCancel, select, spinner, text } from "@clack/prompts"; import { formatFieldHint } from "../metadata/field-hints.js"; import { fetchPickListOptions, formatPickListOptionLabel, getPickListEntityType, type FieldWithRefs, } from "../metadata/picklist.js"; import { pickFromFiltered } from "../metadata/picker.js"; import { parseFieldValue, ValueParseError } from "./value.js"; export interface FieldValueSelection { value: JsonValue; displayLabel?: string; } async function pickPickListOption( field: FieldWithRefs, options: Array<{ value: string; label: string }>, ): Promise { const fieldLabel = field.label ?? field.name ?? "valor"; return pickFromFiltered( `Escolha o valor para ${fieldLabel}`, options, "Como deseja buscar na lista?", ); } async function promptPickListSelection( clarizen: Clarizen, field: FieldWithRefs, pickListTypeName: string, ): Promise { const loadSpinner = spinner(); loadSpinner.start(`Carregando opções de ${pickListTypeName}...`); const pickListOptions = await fetchPickListOptions( clarizen, pickListTypeName, (count) => { loadSpinner.message( `Carregando opções de ${pickListTypeName}... (${count})`, ); }, ); loadSpinner.stop(`${pickListOptions.length} opção(ões) carregada(s).`); if (pickListOptions.length === 0) { console.log( `\nNenhuma opção encontrada para ${pickListTypeName}. Informe o ID manualmente.\n`, ); return promptManualEntityValue(field); } const selectOptions = pickListOptions.map((o) => ({ value: o.id, label: formatPickListOptionLabel(o), })); const selectedId = await pickPickListOption(field, selectOptions); if (isCancel(selectedId)) return selectedId; const match = pickListOptions.find((o) => o.id === selectedId); return { value: { id: selectedId }, displayLabel: match ? `${match.label} (${match.id})` : String(selectedId), }; } async function promptManualEntityValue( field: FieldWithRefs, ): Promise { while (true) { const raw = await text({ message: "Informe o ID da entidade (ex: /Tipo/guid)", validate: (value) => (!value?.trim() ? "Valor obrigatório." : undefined), }); if (isCancel(raw)) return raw; try { const value = parseFieldValue(raw, field); return { value, displayLabel: formatEntityDisplayLabel(value) }; } catch (err) { if (err instanceof ValueParseError) { console.error(`\n Erro: ${err.message}\n`); continue; } throw err; } } } function formatEntityDisplayLabel(value: JsonValue): string | undefined { if (value && typeof value === "object" && "id" in value) { const id = (value as { id?: unknown }).id; if (typeof id === "string") return id; } return undefined; } export async function promptPickListValue( clarizen: Clarizen, field: FieldWithRefs, ): Promise { console.log("\n" + formatFieldHint(field) + "\n"); if (field.nullable) { const action = await select({ message: "O que deseja fazer com este campo?", options: [ { value: "set", label: "Definir um valor" }, { value: "clear", label: "Limpar campo (null)" }, ], }); if (isCancel(action)) return action; if (action === "clear") { return { value: null, displayLabel: "(vazio / null)" }; } } const pickListTypeName = getPickListEntityType(field); if (!pickListTypeName) { console.log( "\nPicklist sem tipo de referência na metadata. Informe o ID manualmente.\n", ); return promptManualEntityValue(field); } return promptPickListSelection(clarizen, field, pickListTypeName); }