export interface FormErrors {
  fieldErrors: Record<string, string>;
  formErrors: string[];
}

export class ValidationError extends Error {
  fieldErrors: Record<string, string>;
  formErrors: string[];

  constructor(message: string, errors: FormErrors) {
    super(message);
    this.name = "ValidationError";
    this.fieldErrors = errors.fieldErrors;
    this.formErrors = errors.formErrors;
  }
}

/**
 * Extract form and field level errors from a 400 response, if present.
 */
export async function getFormErrors(response: Response): Promise<FormErrors | null> {
  if (response.status < 400 || response.status >= 500) {
    return null;
  }

  const fieldErrors: Record<string, string> = {};
  const formErrors: string[] = [];

  try {
    const payload = await response.clone().json();
    const detail = payload?.detail ?? payload;

    const appendFormError = (message: unknown) => {
      if (message == null) return;
      formErrors.push(String(message));
    };

    const setFieldError = (field: string | undefined, message: unknown) => {
      if (!field || field === "__root__") {
        appendFormError(message ?? "Invalid input");
        return;
      }
      if (fieldErrors[field] == null && message != null) {
        fieldErrors[field] = String(message);
      }
    };

    if (typeof detail === "string") {
      appendFormError(detail);
    } else if (Array.isArray(detail)) {
      for (const error of detail) {
        const loc = Array.isArray(error?.loc) ? error.loc : [];
        const message =
          error?.msg ??
          error?.message ??
          error?.detail ??
          (typeof error === "string" ? error : "Invalid input");
        const field = loc.filter((part: unknown) => part !== "body").pop();
        setFieldError(typeof field === "string" ? field : undefined, message);
      }
    } else if (detail && typeof detail === "object") {
      for (const [field, message] of Object.entries(detail)) {
        setFieldError(field, message);
      }
    }
  } catch (error) {
    console.error("[FORM_VALIDATION] Failed to parse form errors", error);
  }

  if (Object.keys(fieldErrors).length === 0 && formErrors.length === 0) {
    return null;
  }

  return { fieldErrors, formErrors };
}
