import { createIdGenerator } from "@giselles-ai/utils";
import * as z from "zod/v4";

export const InputId = createIdGenerator("inp");
export type InputId = z.infer<typeof InputId.schema>;

export const Input = z.object({
	id: InputId.schema,
	label: z.string(),
	accessor: z
		.string()
		.describe(
			"Field used for data access. When not provided, defaults to the label value.",
		),
	isRequired: z.optional(z.boolean().default(false)),
});
export type Input = z.infer<typeof Input>;

export const OutputId = createIdGenerator("otp");
export type OutputId = z.infer<typeof OutputId.schema>;

export const Output = z.object({
	id: OutputId.schema,
	label: z.string(),
	accessor: z
		.string()
		.describe(
			"Field used for data access. Used to link properties of information generated by operation nodes such as TextGeneration with Outputs. For example, in TextGeneration node, Output accessors would be generated-text, reasoning, source.",
		),
});
export type Output = z.infer<typeof Output>;

export const NodeId = createIdGenerator("nd");
export type NodeId = z.infer<typeof NodeId.schema>;

export const NodeBase = z.object({
	id: NodeId.schema,
	name: z.string().optional(),
	type: z.string(),
	inputs: z.array(Input),
	outputs: z.array(Output),
});
export type NodeBase = z.infer<typeof NodeBase>;

export const Position = z.object({
	x: z.number(),
	y: z.number(),
});

export const NodeUIState = z.object({
	position: Position,
	selected: z.boolean().default(false).optional(),
	tab: z.string().optional(),
	showError: z.boolean().default(false).optional(),
	highlighted: z.boolean().default(false).optional(),
	measured: z
		.object({
			width: z.number().optional(),
			height: z.number().optional(),
		})
		.optional(),
});
export type NodeUIState = z.infer<typeof NodeUIState>;

export const NodeReferenceBase = z.object({
	id: NodeId.schema,
	type: z.string(),
});
export type NodeReferenceBase = z.infer<typeof NodeReferenceBase>;
