const BLOCK_TYPES = new Set([
	"header",
	"section",
	"divider",
	"fields",
	"table",
	"actions",
	"stats",
	"form",
	"image",
	"context",
	"columns",
	"chart",
	"banner",
	"meter",
	"code",
]);

const ELEMENT_TYPES = new Set([
	"button",
	"text_input",
	"number_input",
	"select",
	"toggle",
	"secret_input",
	"checkbox",
	"radio",
	"date_input",
	"combobox",
]);

const COLUMN_FORMATS = new Set(["text", "badge", "relative_time", "number", "code"]);

const CODE_LANGUAGES = new Set(["ts", "tsx", "jsonc", "bash", "css"]);

const BUTTON_STYLES = new Set(["primary", "danger", "secondary"]);
const TREND_VALUES = new Set(["up", "down", "neutral"]);
const BANNER_VARIANTS = new Set(["default", "alert", "error"]);

/**
 * Validate option uniqueness and that initial_value references a valid option.
 * Used by select, radio, combobox, and checkbox element validation.
 */
function validateOptionValues(
	options: unknown[],
	path: string,
	errors: ValidationError[],
): Set<string> {
	const seen = new Set<string>();
	for (let i = 0; i < options.length; i++) {
		const opt = options[i];
		if (isRecord(opt) && typeof opt.value === "string") {
			if (seen.has(opt.value)) {
				errors.push({
					path: `${path}[${i}].value`,
					message: `Duplicate option value '${opt.value}'`,
				});
			}
			seen.add(opt.value);
		}
	}
	return seen;
}

function validateInitialValueInOptions(
	initialValue: unknown,
	validValues: Set<string>,
	path: string,
	errors: ValidationError[],
): void {
	if (typeof initialValue === "string" && validValues.size > 0 && !validValues.has(initialValue)) {
		errors.push({
			path: `${path}.initial_value`,
			message: `initial_value '${initialValue}' does not match any option value`,
		});
	}
}

interface ValidationError {
	path: string;
	message: string;
}

function isRecord(v: unknown): v is Record<string, unknown> {
	return typeof v === "object" && v !== null && !Array.isArray(v);
}

function validateConfirmDialog(value: unknown, path: string, errors: ValidationError[]): void {
	if (!isRecord(value)) {
		errors.push({ path, message: "Confirm dialog must be an object" });
		return;
	}
	if (typeof value.title !== "string") {
		errors.push({
			path: `${path}.title`,
			message: "Required field 'title' must be a string",
		});
	}
	if (typeof value.text !== "string") {
		errors.push({
			path: `${path}.text`,
			message: "Required field 'text' must be a string",
		});
	}
	if (typeof value.confirm !== "string") {
		errors.push({
			path: `${path}.confirm`,
			message: "Required field 'confirm' must be a string",
		});
	}
	if (typeof value.deny !== "string") {
		errors.push({
			path: `${path}.deny`,
			message: "Required field 'deny' must be a string",
		});
	}
	if (value.style !== undefined && value.style !== "danger") {
		errors.push({
			path: `${path}.style`,
			message: "Field 'style' must be \"danger\" if provided",
		});
	}
}

function validateElement(value: unknown, path: string, errors: ValidationError[]): void {
	if (!isRecord(value)) {
		errors.push({ path, message: "Element must be an object" });
		return;
	}

	const type = value.type;
	if (typeof type !== "string" || !ELEMENT_TYPES.has(type)) {
		errors.push({
			path: `${path}.type`,
			message: `Unknown element type '${String(type)}'. Expected one of: ${[...ELEMENT_TYPES].join(", ")}`,
		});
		return;
	}

	if (typeof value.action_id !== "string") {
		errors.push({
			path: `${path}.action_id`,
			message: "Required field 'action_id' must be a string",
		});
	}
	if (typeof value.label !== "string") {
		errors.push({
			path: `${path}.label`,
			message: "Required field 'label' must be a string",
		});
	}

	switch (type) {
		case "button": {
			if (
				value.style !== undefined &&
				(typeof value.style !== "string" || !BUTTON_STYLES.has(value.style))
			) {
				errors.push({
					path: `${path}.style`,
					message: `Field 'style' must be one of: ${[...BUTTON_STYLES].join(", ")}`,
				});
			}
			if (value.confirm !== undefined) {
				validateConfirmDialog(value.confirm, `${path}.confirm`, errors);
			}
			break;
		}
		case "text_input": {
			if (value.placeholder !== undefined && typeof value.placeholder !== "string") {
				errors.push({
					path: `${path}.placeholder`,
					message: "Field 'placeholder' must be a string",
				});
			}
			if (value.initial_value !== undefined && typeof value.initial_value !== "string") {
				errors.push({
					path: `${path}.initial_value`,
					message: "Field 'initial_value' must be a string",
				});
			}
			if (value.multiline !== undefined && typeof value.multiline !== "boolean") {
				errors.push({
					path: `${path}.multiline`,
					message: "Field 'multiline' must be a boolean",
				});
			}
			break;
		}
		case "number_input": {
			if (value.initial_value !== undefined && typeof value.initial_value !== "number") {
				errors.push({
					path: `${path}.initial_value`,
					message: "Field 'initial_value' must be a number",
				});
			}
			if (value.min !== undefined && typeof value.min !== "number") {
				errors.push({
					path: `${path}.min`,
					message: "Field 'min' must be a number",
				});
			}
			if (value.max !== undefined && typeof value.max !== "number") {
				errors.push({
					path: `${path}.max`,
					message: "Field 'max' must be a number",
				});
			}
			break;
		}
		case "select": {
			let selectValidValues = new Set<string>();
			if (!Array.isArray(value.options)) {
				errors.push({
					path: `${path}.options`,
					message: "Required field 'options' must be an array",
				});
			} else if (value.options.length === 0) {
				errors.push({
					path: `${path}.options`,
					message: "Field 'options' must not be empty",
				});
			} else {
				for (let i = 0; i < value.options.length; i++) {
					const opt = value.options[i] as unknown;
					if (!isRecord(opt)) {
						errors.push({
							path: `${path}.options[${i}]`,
							message: "Option must be an object",
						});
						continue;
					}
					if (typeof opt.label !== "string") {
						errors.push({
							path: `${path}.options[${i}].label`,
							message: "Option 'label' must be a string",
						});
					}
					if (typeof opt.value !== "string") {
						errors.push({
							path: `${path}.options[${i}].value`,
							message: "Option 'value' must be a string",
						});
					}
				}
				selectValidValues = validateOptionValues(value.options, `${path}.options`, errors);
			}
			if (value.initial_value !== undefined && typeof value.initial_value !== "string") {
				errors.push({
					path: `${path}.initial_value`,
					message: "Field 'initial_value' must be a string",
				});
			}
			if (value.initial_value !== undefined) {
				validateInitialValueInOptions(value.initial_value, selectValidValues, path, errors);
			}
			break;
		}
		case "toggle": {
			if (value.description !== undefined && typeof value.description !== "string") {
				errors.push({
					path: `${path}.description`,
					message: "Field 'description' must be a string",
				});
			}
			if (value.initial_value !== undefined && typeof value.initial_value !== "boolean") {
				errors.push({
					path: `${path}.initial_value`,
					message: "Field 'initial_value' must be a boolean",
				});
			}
			break;
		}
		case "secret_input": {
			if (value.placeholder !== undefined && typeof value.placeholder !== "string") {
				errors.push({
					path: `${path}.placeholder`,
					message: "Field 'placeholder' must be a string",
				});
			}
			if (value.has_value !== undefined && typeof value.has_value !== "boolean") {
				errors.push({
					path: `${path}.has_value`,
					message: "Field 'has_value' must be a boolean",
				});
			}
			break;
		}
		case "checkbox": {
			let checkboxValidValues = new Set<string>();
			if (!Array.isArray(value.options)) {
				errors.push({
					path: `${path}.options`,
					message: "Required field 'options' must be an array",
				});
			} else if (value.options.length === 0) {
				errors.push({ path: `${path}.options`, message: "Field 'options' must not be empty" });
			} else {
				for (let i = 0; i < value.options.length; i++) {
					const opt = value.options[i] as unknown;
					if (!isRecord(opt)) {
						errors.push({ path: `${path}.options[${i}]`, message: "Option must be an object" });
						continue;
					}
					if (typeof opt.label !== "string") {
						errors.push({
							path: `${path}.options[${i}].label`,
							message: "Option 'label' must be a string",
						});
					}
					if (typeof opt.value !== "string") {
						errors.push({
							path: `${path}.options[${i}].value`,
							message: "Option 'value' must be a string",
						});
					}
				}
				checkboxValidValues = validateOptionValues(value.options, `${path}.options`, errors);
			}
			if (value.initial_value !== undefined) {
				if (!Array.isArray(value.initial_value)) {
					errors.push({
						path: `${path}.initial_value`,
						message: "Field 'initial_value' must be an array of strings",
					});
				} else {
					for (let i = 0; i < value.initial_value.length; i++) {
						const item = value.initial_value[i];
						if (typeof item !== "string") {
							errors.push({
								path: `${path}.initial_value[${i}]`,
								message: "Each initial_value entry must be a string",
							});
							break;
						}
						if (checkboxValidValues.size > 0 && !checkboxValidValues.has(item)) {
							errors.push({
								path: `${path}.initial_value[${i}]`,
								message: `initial_value '${item}' does not match any option value`,
							});
						}
					}
				}
			}
			break;
		}
		case "radio": {
			let radioValidValues = new Set<string>();
			if (!Array.isArray(value.options)) {
				errors.push({
					path: `${path}.options`,
					message: "Required field 'options' must be an array",
				});
			} else if (value.options.length === 0) {
				errors.push({ path: `${path}.options`, message: "Field 'options' must not be empty" });
			} else {
				for (let i = 0; i < value.options.length; i++) {
					const opt = value.options[i] as unknown;
					if (!isRecord(opt)) {
						errors.push({ path: `${path}.options[${i}]`, message: "Option must be an object" });
						continue;
					}
					if (typeof opt.label !== "string") {
						errors.push({
							path: `${path}.options[${i}].label`,
							message: "Option 'label' must be a string",
						});
					}
					if (typeof opt.value !== "string") {
						errors.push({
							path: `${path}.options[${i}].value`,
							message: "Option 'value' must be a string",
						});
					}
				}
				radioValidValues = validateOptionValues(value.options, `${path}.options`, errors);
			}
			if (value.initial_value !== undefined && typeof value.initial_value !== "string") {
				errors.push({
					path: `${path}.initial_value`,
					message: "Field 'initial_value' must be a string",
				});
			}
			if (value.initial_value !== undefined) {
				validateInitialValueInOptions(value.initial_value, radioValidValues, path, errors);
			}
			break;
		}
		case "date_input": {
			if (value.initial_value !== undefined && typeof value.initial_value !== "string") {
				errors.push({
					path: `${path}.initial_value`,
					message: "Field 'initial_value' must be a string",
				});
			}
			if (value.placeholder !== undefined && typeof value.placeholder !== "string") {
				errors.push({
					path: `${path}.placeholder`,
					message: "Field 'placeholder' must be a string",
				});
			}
			break;
		}
		case "combobox": {
			let comboboxValidValues = new Set<string>();
			if (!Array.isArray(value.options)) {
				errors.push({
					path: `${path}.options`,
					message: "Required field 'options' must be an array",
				});
			} else if (value.options.length === 0) {
				errors.push({ path: `${path}.options`, message: "Field 'options' must not be empty" });
			} else {
				for (let i = 0; i < value.options.length; i++) {
					const opt = value.options[i] as unknown;
					if (!isRecord(opt)) {
						errors.push({ path: `${path}.options[${i}]`, message: "Option must be an object" });
						continue;
					}
					if (typeof opt.label !== "string") {
						errors.push({
							path: `${path}.options[${i}].label`,
							message: "Option 'label' must be a string",
						});
					}
					if (typeof opt.value !== "string") {
						errors.push({
							path: `${path}.options[${i}].value`,
							message: "Option 'value' must be a string",
						});
					}
				}
				comboboxValidValues = validateOptionValues(value.options, `${path}.options`, errors);
			}
			if (value.initial_value !== undefined && typeof value.initial_value !== "string") {
				errors.push({
					path: `${path}.initial_value`,
					message: "Field 'initial_value' must be a string",
				});
			}
			if (value.initial_value !== undefined) {
				validateInitialValueInOptions(value.initial_value, comboboxValidValues, path, errors);
			}
			if (value.placeholder !== undefined && typeof value.placeholder !== "string") {
				errors.push({
					path: `${path}.placeholder`,
					message: "Field 'placeholder' must be a string",
				});
			}
			break;
		}
	}
}

function validateFormField(value: unknown, path: string, errors: ValidationError[]): void {
	validateElement(value, path, errors);

	if (!isRecord(value)) return;

	if (value.condition !== undefined) {
		const cond = value.condition;
		if (!isRecord(cond)) {
			errors.push({
				path: `${path}.condition`,
				message: "Field 'condition' must be an object",
			});
		} else if (typeof cond.field !== "string") {
			errors.push({
				path: `${path}.condition.field`,
				message: "Condition 'field' must be a string",
			});
		} else if (!("eq" in cond) && !("neq" in cond)) {
			errors.push({
				path: `${path}.condition`,
				message: "Condition must have either 'eq' or 'neq'",
			});
		}
	}
}

const CHART_TYPES = new Set(["timeseries", "custom"]);
const CHART_STYLES = new Set(["line", "bar"]);

function validateChartSeries(value: unknown, path: string, errors: ValidationError[]): void {
	if (!isRecord(value)) {
		errors.push({ path, message: "Chart series must be an object" });
		return;
	}
	if (typeof value.name !== "string") {
		errors.push({
			path: `${path}.name`,
			message: "Required field 'name' must be a string",
		});
	}
	if (!Array.isArray(value.data)) {
		errors.push({
			path: `${path}.data`,
			message: "Required field 'data' must be an array of [timestamp, value] tuples",
		});
	} else {
		for (let i = 0; i < value.data.length; i++) {
			const point = value.data[i] as unknown;
			if (
				!Array.isArray(point) ||
				point.length !== 2 ||
				typeof point[0] !== "number" ||
				typeof point[1] !== "number"
			) {
				errors.push({
					path: `${path}.data[${i}]`,
					message: "Each data point must be a [number, number] tuple",
				});
				break; // One error is enough for malformed data arrays
			}
		}
	}
	if (value.color !== undefined && typeof value.color !== "string") {
		errors.push({
			path: `${path}.color`,
			message: "Field 'color' must be a string if provided",
		});
	}
}

function validateChartConfig(value: unknown, path: string, errors: ValidationError[]): void {
	if (!isRecord(value)) {
		errors.push({ path, message: "Required field 'config' must be an object" });
		return;
	}

	const chartType = value.chart_type;
	if (typeof chartType !== "string" || !CHART_TYPES.has(chartType)) {
		errors.push({
			path: `${path}.chart_type`,
			message: `Field 'chart_type' must be one of: ${[...CHART_TYPES].join(", ")}`,
		});
		return;
	}

	if (value.height !== undefined) {
		if (typeof value.height !== "number") {
			errors.push({
				path: `${path}.height`,
				message: "Field 'height' must be a number if provided",
			});
		} else if (value.height <= 0) {
			errors.push({
				path: `${path}.height`,
				message: "Field 'height' must be a positive number",
			});
		}
	}

	switch (chartType) {
		case "timeseries": {
			if (
				value.style !== undefined &&
				(typeof value.style !== "string" || !CHART_STYLES.has(value.style))
			) {
				errors.push({
					path: `${path}.style`,
					message: `Field 'style' must be one of: ${[...CHART_STYLES].join(", ")}`,
				});
			}
			if (!Array.isArray(value.series)) {
				errors.push({
					path: `${path}.series`,
					message: "Required field 'series' must be an array",
				});
			} else if (value.series.length === 0) {
				errors.push({
					path: `${path}.series`,
					message: "Field 'series' must not be empty",
				});
			} else {
				for (let i = 0; i < value.series.length; i++) {
					validateChartSeries(value.series[i], `${path}.series[${i}]`, errors);
				}
			}
			if (value.x_axis_name !== undefined && typeof value.x_axis_name !== "string") {
				errors.push({
					path: `${path}.x_axis_name`,
					message: "Field 'x_axis_name' must be a string if provided",
				});
			}
			if (value.y_axis_name !== undefined && typeof value.y_axis_name !== "string") {
				errors.push({
					path: `${path}.y_axis_name`,
					message: "Field 'y_axis_name' must be a string if provided",
				});
			}
			if (value.gradient !== undefined && typeof value.gradient !== "boolean") {
				errors.push({
					path: `${path}.gradient`,
					message: "Field 'gradient' must be a boolean if provided",
				});
			}
			break;
		}
		case "custom": {
			if (!isRecord(value.options)) {
				errors.push({
					path: `${path}.options`,
					message: "Required field 'options' must be an object",
				});
			}
			break;
		}
	}
}

function validateBlock(value: unknown, path: string, errors: ValidationError[]): void {
	if (!isRecord(value)) {
		errors.push({ path, message: "Block must be an object" });
		return;
	}

	const type = value.type;
	if (typeof type !== "string" || !BLOCK_TYPES.has(type)) {
		errors.push({
			path: `${path}.type`,
			message: `Unknown block type '${String(type)}'. Expected one of: ${[...BLOCK_TYPES].join(", ")}`,
		});
		return;
	}

	if (value.block_id !== undefined && typeof value.block_id !== "string") {
		errors.push({
			path: `${path}.block_id`,
			message: "Field 'block_id' must be a string if provided",
		});
	}

	switch (type) {
		case "header": {
			if (typeof value.text !== "string") {
				errors.push({
					path: `${path}.text`,
					message: "Required field 'text' must be a string",
				});
			}
			break;
		}
		case "section": {
			if (typeof value.text !== "string") {
				errors.push({
					path: `${path}.text`,
					message: "Required field 'text' must be a string",
				});
			}
			if (value.accessory !== undefined) {
				validateElement(value.accessory, `${path}.accessory`, errors);
			}
			break;
		}
		case "divider": {
			// No required fields
			break;
		}
		case "fields": {
			if (!Array.isArray(value.fields)) {
				errors.push({
					path: `${path}.fields`,
					message: "Required field 'fields' must be an array",
				});
			} else {
				for (let i = 0; i < value.fields.length; i++) {
					const f = value.fields[i] as unknown;
					if (!isRecord(f)) {
						errors.push({
							path: `${path}.fields[${i}]`,
							message: "Field entry must be an object",
						});
						continue;
					}
					if (typeof f.label !== "string") {
						errors.push({
							path: `${path}.fields[${i}].label`,
							message: "Required field 'label' must be a string",
						});
					}
					if (typeof f.value !== "string") {
						errors.push({
							path: `${path}.fields[${i}].value`,
							message: "Required field 'value' must be a string",
						});
					}
				}
			}
			break;
		}
		case "table": {
			if (!Array.isArray(value.columns)) {
				errors.push({
					path: `${path}.columns`,
					message: "Required field 'columns' must be an array",
				});
			} else {
				for (let i = 0; i < value.columns.length; i++) {
					const col = value.columns[i] as unknown;
					if (!isRecord(col)) {
						errors.push({
							path: `${path}.columns[${i}]`,
							message: "Column must be an object",
						});
						continue;
					}
					if (typeof col.key !== "string") {
						errors.push({
							path: `${path}.columns[${i}].key`,
							message: "Required field 'key' must be a string",
						});
					}
					if (typeof col.label !== "string") {
						errors.push({
							path: `${path}.columns[${i}].label`,
							message: "Required field 'label' must be a string",
						});
					}
					if (
						col.format !== undefined &&
						(typeof col.format !== "string" || !COLUMN_FORMATS.has(col.format))
					) {
						errors.push({
							path: `${path}.columns[${i}].format`,
							message: `Field 'format' must be one of: ${[...COLUMN_FORMATS].join(", ")}`,
						});
					}
					if (col.sortable !== undefined && typeof col.sortable !== "boolean") {
						errors.push({
							path: `${path}.columns[${i}].sortable`,
							message: "Field 'sortable' must be a boolean",
						});
					}
				}
			}
			if (!Array.isArray(value.rows)) {
				errors.push({
					path: `${path}.rows`,
					message: "Required field 'rows' must be an array",
				});
			} else {
				for (let i = 0; i < value.rows.length; i++) {
					if (!isRecord(value.rows[i] as unknown)) {
						errors.push({
							path: `${path}.rows[${i}]`,
							message: "Row must be an object",
						});
					}
				}
			}
			if (typeof value.page_action_id !== "string") {
				errors.push({
					path: `${path}.page_action_id`,
					message: "Required field 'page_action_id' must be a string",
				});
			}
			if (value.next_cursor !== undefined && typeof value.next_cursor !== "string") {
				errors.push({
					path: `${path}.next_cursor`,
					message: "Field 'next_cursor' must be a string if provided",
				});
			}
			if (value.empty_text !== undefined && typeof value.empty_text !== "string") {
				errors.push({
					path: `${path}.empty_text`,
					message: "Field 'empty_text' must be a string if provided",
				});
			}
			break;
		}
		case "actions": {
			if (!Array.isArray(value.elements)) {
				errors.push({
					path: `${path}.elements`,
					message: "Required field 'elements' must be an array",
				});
			} else {
				for (let i = 0; i < value.elements.length; i++) {
					validateElement(value.elements[i], `${path}.elements[${i}]`, errors);
				}
			}
			break;
		}
		case "stats": {
			if (!Array.isArray(value.items)) {
				errors.push({
					path: `${path}.items`,
					message: "Required field 'items' must be an array",
				});
			} else {
				for (let i = 0; i < value.items.length; i++) {
					const item = value.items[i] as unknown;
					if (!isRecord(item)) {
						errors.push({
							path: `${path}.items[${i}]`,
							message: "Stat item must be an object",
						});
						continue;
					}
					if (typeof item.label !== "string") {
						errors.push({
							path: `${path}.items[${i}].label`,
							message: "Required field 'label' must be a string",
						});
					}
					if (typeof item.value !== "string" && typeof item.value !== "number") {
						errors.push({
							path: `${path}.items[${i}].value`,
							message: "Required field 'value' must be a string or number",
						});
					}
					if (item.description !== undefined && typeof item.description !== "string") {
						errors.push({
							path: `${path}.items[${i}].description`,
							message: "Field 'description' must be a string",
						});
					}
					if (
						item.trend !== undefined &&
						(typeof item.trend !== "string" || !TREND_VALUES.has(item.trend))
					) {
						errors.push({
							path: `${path}.items[${i}].trend`,
							message: `Field 'trend' must be one of: ${[...TREND_VALUES].join(", ")}`,
						});
					}
				}
			}
			break;
		}
		case "form": {
			if (!Array.isArray(value.fields)) {
				errors.push({
					path: `${path}.fields`,
					message: "Required field 'fields' must be an array",
				});
			} else {
				for (let i = 0; i < value.fields.length; i++) {
					validateFormField(value.fields[i], `${path}.fields[${i}]`, errors);
				}
			}
			if (!isRecord(value.submit)) {
				errors.push({
					path: `${path}.submit`,
					message: "Required field 'submit' must be an object",
				});
			} else {
				if (typeof value.submit.label !== "string") {
					errors.push({
						path: `${path}.submit.label`,
						message: "Required field 'label' must be a string",
					});
				}
				if (typeof value.submit.action_id !== "string") {
					errors.push({
						path: `${path}.submit.action_id`,
						message: "Required field 'action_id' must be a string",
					});
				}
			}
			break;
		}
		case "image": {
			if (typeof value.url !== "string") {
				errors.push({
					path: `${path}.url`,
					message: "Required field 'url' must be a string",
				});
			}
			if (typeof value.alt !== "string") {
				errors.push({
					path: `${path}.alt`,
					message: "Required field 'alt' must be a string",
				});
			}
			if (value.title !== undefined && typeof value.title !== "string") {
				errors.push({
					path: `${path}.title`,
					message: "Field 'title' must be a string if provided",
				});
			}
			break;
		}
		case "context": {
			if (typeof value.text !== "string") {
				errors.push({
					path: `${path}.text`,
					message: "Required field 'text' must be a string",
				});
			}
			break;
		}
		case "columns": {
			if (!Array.isArray(value.columns)) {
				errors.push({
					path: `${path}.columns`,
					message: "Required field 'columns' must be an array",
				});
			} else if (value.columns.length < 2 || value.columns.length > 3) {
				errors.push({
					path: `${path}.columns`,
					message: "Field 'columns' must contain 2-3 column arrays",
				});
			} else {
				for (let i = 0; i < value.columns.length; i++) {
					const col = value.columns[i];
					if (!Array.isArray(col)) {
						errors.push({
							path: `${path}.columns[${i}]`,
							message: "Each column must be an array of blocks",
						});
						continue;
					}
					for (let j = 0; j < col.length; j++) {
						validateBlock(col[j], `${path}.columns[${i}][${j}]`, errors);
					}
				}
			}
			break;
		}
		case "chart": {
			validateChartConfig(value.config, `${path}.config`, errors);
			break;
		}
		case "meter": {
			if (typeof value.label !== "string") {
				errors.push({ path: `${path}.label`, message: "Required field 'label' must be a string" });
			}
			if (typeof value.value !== "number") {
				errors.push({ path: `${path}.value`, message: "Required field 'value' must be a number" });
			}
			if (value.max !== undefined && typeof value.max !== "number") {
				errors.push({ path: `${path}.max`, message: "Field 'max' must be a number if provided" });
			}
			if (value.min !== undefined && typeof value.min !== "number") {
				errors.push({ path: `${path}.min`, message: "Field 'min' must be a number if provided" });
			}
			if (
				typeof value.min === "number" &&
				typeof value.max === "number" &&
				value.min >= value.max
			) {
				errors.push({ path, message: "Field 'min' must be less than 'max'" });
			}
			if (value.custom_value !== undefined && typeof value.custom_value !== "string") {
				errors.push({
					path: `${path}.custom_value`,
					message: "Field 'custom_value' must be a string if provided",
				});
			}
			break;
		}
		case "code": {
			if (typeof value.code !== "string") {
				errors.push({ path: `${path}.code`, message: "Required field 'code' must be a string" });
			}
			if (
				value.language !== undefined &&
				(typeof value.language !== "string" || !CODE_LANGUAGES.has(value.language))
			) {
				errors.push({
					path: `${path}.language`,
					message: `Field 'language' must be one of: ${[...CODE_LANGUAGES].join(", ")}`,
				});
			}
			break;
		}
		case "banner": {
			if (value.title !== undefined && typeof value.title !== "string") {
				errors.push({
					path: `${path}.title`,
					message: "Field 'title' must be a string if provided",
				});
			}
			if (value.description !== undefined && typeof value.description !== "string") {
				errors.push({
					path: `${path}.description`,
					message: "Field 'description' must be a string if provided",
				});
			}
			if (value.title === undefined && value.description === undefined) {
				errors.push({
					path,
					message: "Banner must have at least 'title' or 'description'",
				});
			}
			if (
				value.variant !== undefined &&
				(typeof value.variant !== "string" || !BANNER_VARIANTS.has(value.variant))
			) {
				errors.push({
					path: `${path}.variant`,
					message: `Field 'variant' must be one of: ${[...BANNER_VARIANTS].join(", ")}`,
				});
			}
			break;
		}
	}
}

export function validateBlocks(blocks: unknown): {
	valid: boolean;
	errors: ValidationError[];
} {
	const errors: ValidationError[] = [];

	if (!Array.isArray(blocks)) {
		errors.push({ path: "blocks", message: "Blocks must be an array" });
		return { valid: false, errors };
	}

	for (let i = 0; i < blocks.length; i++) {
		validateBlock(blocks[i], `blocks[${i}]`, errors);
	}

	return { valid: errors.length === 0, errors };
}
