import { FieldType, type BlueprintFieldDefinition } from "@capakraken/shared";

export interface CustomFieldValidationError {
  key: string;
  message: string;
}

/**
 * Validates a `dynamicFields` record against an array of BlueprintFieldDefinitions.
 * Returns an array of errors (empty = valid).
 */
export function validateCustomFields(
  fieldDefs: BlueprintFieldDefinition[],
  dynamicFields: Record<string, unknown>,
): CustomFieldValidationError[] {
  const errors: CustomFieldValidationError[] = [];

  for (const def of fieldDefs) {
    const value = dynamicFields[def.key];
    const isEmpty = value === undefined || value === null || value === "";

    if (def.required && isEmpty) {
      errors.push({ key: def.key, message: `${def.label} is required` });
      continue;
    }

    if (isEmpty) continue;

    switch (def.type) {
      case FieldType.NUMBER: {
        if (typeof value !== "number" && isNaN(Number(value))) {
          errors.push({ key: def.key, message: `${def.label} must be a number` });
        }
        const validation = def.validation;
        if (validation) {
          const num = Number(value);
          if (validation.min !== undefined && num < validation.min) {
            errors.push({ key: def.key, message: `${def.label} must be at least ${validation.min}` });
          }
          if (validation.max !== undefined && num > validation.max) {
            errors.push({ key: def.key, message: `${def.label} must be at most ${validation.max}` });
          }
        }
        break;
      }

      case FieldType.BOOLEAN:
        if (value !== true && value !== false && value !== "true" && value !== "false") {
          errors.push({ key: def.key, message: `${def.label} must be a boolean` });
        }
        break;

      case FieldType.SELECT:
        if (def.options && def.options.length > 0) {
          const valid = def.options.some((o) => o.value === value);
          if (!valid) {
            const allowed = def.options.map((o) => o.label || o.value).join(", ");
            errors.push({ key: def.key, message: `${def.label} must be one of: ${allowed}` });
          }
        }
        break;

      case FieldType.MULTI_SELECT:
        if (Array.isArray(value) && def.options && def.options.length > 0) {
          const validSet = new Set(def.options.map((o) => o.value));
          const invalid = (value as string[]).filter((v) => !validSet.has(v));
          if (invalid.length > 0) {
            errors.push({ key: def.key, message: `${def.label} contains invalid values: ${invalid.join(", ")}` });
          }
        }
        break;

      case FieldType.URL:
        try {
          new URL(String(value));
        } catch {
          errors.push({ key: def.key, message: `${def.label} must be a valid URL` });
        }
        break;

      case FieldType.EMAIL:
        if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value))) {
          errors.push({ key: def.key, message: `${def.label} must be a valid email address` });
        }
        break;

      // TEXT, TEXTAREA, DATE — no structural validation beyond required
    }
  }

  return errors;
}
