import { z, ZodObject } from "zod";
import { CustomField } from "@/redux/api/customFieldApi";

export const buildZodSchema = (fields: CustomField[]): ZodObject<any> => {
  const shape: Record<string, any> = {};

  for (const field of fields) {
    // Build the base schema for the type first
    let baseSchema: z.ZodTypeAny;

    switch (field.type) {
      case "text":
      case "textarea":
      case "dropdown":
      case "radio":
        baseSchema = z.string();
        break;

      case "email":
        baseSchema = z.string().email(`${field.label} must be a valid email`);
        break;

      case "number":
        if (field.required) {
          baseSchema = z.preprocess(
            (val) => {
              if (val === "" || val === null || val === undefined) {
                return val;
              }

              const num = Number(val);
              return Number.isNaN(num) ? NaN : num;
            },
            z.number({
              required_error: `${field.label} is required`,
              invalid_type_error: `${field.label} must be a number`,
            })
          );
        } else {
          baseSchema = z.preprocess(
            (val) => {
              if (
                val === "" ||
                val === null ||
                val === undefined ||
                Number.isNaN(Number(val))
              ) {
                return undefined;
              }
              return Number(val);
            },
            z
              .number({
                invalid_type_error: `${field.label} must be a number`,
              })
              .optional()
          );
        }
        break;

      case "phone":
        baseSchema = z
          .string()
          .regex(
            /^\+?\d{6,15}$/,
            `${field.label} must be a valid phone number`
          );
        break;

      case "checkbox":
        baseSchema = z.array(z.string());
        break;

      case "date":
        if (field.required) {
          baseSchema = z
            .string({
              required_error: `${field.label} is required`,
            })
            .refine((v) => !isNaN(Date.parse(v)), {
              message: `${field.label} must be a valid date`,
            });
        } else {
          baseSchema = z.preprocess(
            (val) => {
              if (val === "" || val === null || val === undefined) {
                return undefined;
              }
              return val;
            },
            z
              .string()
              .refine((v) => !isNaN(Date.parse(v)), {
                message: `${field.label} must be a valid date`,
              })
              .optional()
          );
        }
        break;

      default:
        baseSchema = z.any();
    }

    // Apply "required" rules that rely on the underlying type BEFORE refine/effects
    let schema = baseSchema;

    if (
      field.type === "text" ||
      field.type === "textarea" ||
      field.type === "dropdown" ||
      field.type === "radio" ||
      field.type === "email" ||
      field.type === "phone" ||
      field.type === "date"
    ) {
      if (field.required) {
        schema = (schema as z.ZodArray<z.ZodString>).refine(
          (val) => val.length > 0,
          {
            message: `${field.label} is required`,
          }
        );
      }
    } else if (field.type === "checkbox") {
      if (field.required) {
        schema = (schema as z.ZodArray<z.ZodString>).refine(
          (val) => val.length > 0,
          {
            message: `${field.label} is required`,
          }
        );
      }
    }

    if (field.type === "date") {
      schema = (schema as z.ZodString).refine((v) => !isNaN(Date.parse(v)), {
        message: `${field.label} must be a valid date`,
      });
    }

    if (!field.required) {
      schema = schema.optional();
    }

    shape[field.key] = schema;
  }

  return z.object({ customFields: z.object(shape) });
};
