import { z, ZodObject, ZodRawShape, ZodIssueCode } from "zod";

// Helper function to check if a value is non-empty for strings, arrays, and numbers (converted to string)
const isNonEmpty = (v: unknown): boolean => {
  if (typeof v === "string") {
    return v.trim().length > 0;
  }
  if (Array.isArray(v)) {
    return v.length > 0;
  }
  // For Zod's .coerce.string() types (like budget, propertySize),
  // they might come in as strings. We'll treat all non-null/undefined
  // values that pass the string/array checks as potentially non-empty,
  // but explicitly check strings for trim().
  if (v !== null && v !== undefined) {
    // If it's a number coerced to string, it's generally non-empty unless 0.
    // However, since we expect strings from the form input after coercion,
    // the initial string check should cover most cases.
    // Let's stick to the string/array checks for required fields.
    return true; // Assume if it's not string/array, and not null/undefined, it's valid (e.g., boolean or enum 'yes/no')
  }
  return false;
};

// 1) Base schema (no superRefine here)
const baseLeadFormSchema = z.object({
  // Bank Account Fields
  bankName: z.string().optional(),
  accountNumber: z.string().optional(),
  ifscCode: z.string().optional(),
  branch: z.string().optional(),
  accountType: z.enum(["savings", "current"]).default("savings"),
  status: z.enum(["active", "inactive"]).default("active"),

  contact: z.string({
    required_error: "Please select a contact",
  }),
  source: z
    .string({
      required_error: "Please select a source",
    })
    .min(1, "Please select a source"),
  leadStage: z
    .string({
      required_error: "Please select a lead stage",
    })
    .min(1, "Please select a lead stage"),
  priority: z
    .string({
      required_error: "Please select a priority",
    })
    .min(1, "Please select a priority"),
  assignedTo: z
    .string({
      required_error: "Please select a assign user",
    })
    .min(1, "Please select a assign user"),
  cpContact: z.string().optional().nullable(),
  interestType: z.string({
    required_error: "Please select an interest type",
  }),
  // buyingPreference is optional at the schema level, but required conditionally
  buyingPreference: z.string().optional(),
  project: z.string().optional(),
  unit: z.string().optional(),
  loanRequired: z.enum(["yes", "no"]).optional(),
  loanStage: z.string().optional(),
  purpose: z.string().optional(),

  // These can be string or string array
  propertyTypeBuy: z.array(z.string()).or(z.string()).optional(),
  propertyType: z.array(z.string()).or(z.string()).optional(),
  configuration: z.array(z.string()).or(z.string()).optional(),

  // ... (other fields remain the same)
  category: z.string().optional(),
  preferredState: z.string().optional(),
  preferredCity: z.string().optional(),
  preferredLocalities: z.array(z.string()).optional(),
  budget: z.coerce.string().optional(),
  propertyAddress: z.string().optional(),
  propertyCity: z.string().optional(),
  propertyLocality: z.string().optional(),
  propertySize: z.coerce.string().optional(),
  propertyBedrooms: z.coerce.string().optional(),
  propertyAge: z.string().optional(),
  askingPrice: z.coerce.string().optional(),
  sellPropertyType: z.string().optional(),
  furnishingStatus: z.string().optional(),
  rentAmount: z.coerce.string().optional(),
  securityDeposit: z.coerce.string().optional(),
  availableFrom: z.string().optional(),
  leaseTermYears: z.string().optional(),
  leaseAmount: z.coerce.string().optional(),
  leaseDeposit: z.coerce.string().optional(),
  addressLine1: z.string().optional(),
  addressLine2: z.string().optional(),
  landmark: z.string().optional(),
  pincode: z.coerce.string().optional(),
});

export const customFieldsSchemaOptional = z.object({
  customFields: z.record(z.any()).optional(),
});

// 2) Conditional validation logic
const withConditionalRules = <T extends z.ZodTypeAny>(schema: T) =>
  schema.superRefine((data: any, ctx) => {
    // Normalize interestType for easy comparison
    const interestType = data.interestType?.toLowerCase();

    const isBuy = interestType === "buy";
    const isRent = interestType === "rent";
    const isLease = interestType === "lease";
    const isOpenToSuggestion =
      data.buyingPreference?.toLowerCase() === "open_to_suggestions";
    const isPreferredProject =
      data.buyingPreference?.toLowerCase() === "preferred_project";

    const isLoanRequired = data.loanRequired?.toLowerCase() === "yes";

    // --- RULE 1: `buyingPreference` is required if `interestType` is 'buy' ---
    // The key correction is checking if buyingPreference is missing/empty.
    if (isBuy && !data.buyingPreference) {
      ctx.addIssue({
        code: ZodIssueCode.custom,
        path: ["buyingPreference"],
        message: "Please select a buying preference",
      });
    }

    if (isBuy && isPreferredProject && !isNonEmpty(data.project)) {
      ctx.addIssue({
        code: ZodIssueCode.custom,
        path: ["project"],
        message: "Please select a project",
      });
    }

    if (isPreferredProject && isLoanRequired && !isNonEmpty(data.loanStage)) {
      ctx.addIssue({
        code: ZodIssueCode.custom,
        path: ["loanStage"],
        message: "Please select a loan stage",
      });
    }

    if (isPreferredProject && !isNonEmpty(data.purpose)) {
      ctx.addIssue({
        code: ZodIssueCode.custom,
        path: ["purpose"],
        message: "Please select a purpose",
      });
    }

    const needLocationAndPropertyDetails = isRent || isLease;

    if (needLocationAndPropertyDetails) {
      // --- Fields required for ALL three cases (Open, Rent, Lease) ---

      if (!isNonEmpty(data.category)) {
        ctx.addIssue({
          code: ZodIssueCode.custom,
          path: ["category"],
          message: "Please select a category",
        });
      }

      if (!isNonEmpty(data.configuration)) {
        ctx.addIssue({
          code: ZodIssueCode.custom,
          path: ["configuration"],
          message: "Please select a configuration",
        });
      }

      if (!isNonEmpty(data.preferredState)) {
        ctx.addIssue({
          code: ZodIssueCode.custom,
          path: ["preferredState"],
          message: "Please select a preferred state",
        });
      }

      if (!isNonEmpty(data.preferredCity)) {
        ctx.addIssue({
          code: ZodIssueCode.custom,
          path: ["preferredCity"],
          message: "Please select a preferred city",
        });
      }

      if (!isNonEmpty(data.preferredLocalities)) {
        ctx.addIssue({
          code: ZodIssueCode.custom,
          path: ["preferredLocalities"],
          message: "Please select a preferred locality",
        });
      }
    }

    // 1. Validation for Rent or Lease (Requires a specific existing property locality)
    if (isRent || isLease) {
      if (!isNonEmpty(data.propertyType)) {
        ctx.addIssue({
          code: ZodIssueCode.custom,
          path: ["propertyType"],
          message: "Please select a property type",
        });
      }
    }

    // 2. Validation for Open to Suggestion (Requires preferred localities)
    else if (isOpenToSuggestion && isBuy) {
      if (!isNonEmpty(data.preferredLocalities)) {
        ctx.addIssue({
          code: ZodIssueCode.custom,
          path: ["preferredLocalities"],
          message: "Please select a preferred locality",
        });
      }

      if (!isNonEmpty(data.propertyTypeBuy)) {
        ctx.addIssue({
          code: ZodIssueCode.custom,
          path: ["propertyTypeBuy"],
          message: "Please select a property type",
        });
      }

      if (!isNonEmpty(data.preferredCity)) {
        ctx.addIssue({
          code: ZodIssueCode.custom,
          path: ["preferredCity"],
          message: "Please select a city",
        });
      }

      if (!isNonEmpty(data.budget)) {
        ctx.addIssue({
          code: ZodIssueCode.custom,
          path: ["budget"],
          message: "Please select a budget",
        });
      }
    }
    // --- RULE 3: `leaseTermYears` is required if `interestType` is 'lease' ---
    if (isLease && !isNonEmpty(data.leaseTermYears)) {
      ctx.addIssue({
        code: ZodIssueCode.custom,
        path: ["leaseTermYears"],
        message: "Please select a lease term",
      });
    }
  });

export const buildLeadFormSchema = (
  dynamicCustomFieldsSchema?: ZodObject<ZodRawShape>,
) => {
  const objectSchema = dynamicCustomFieldsSchema
    ? baseLeadFormSchema.merge(dynamicCustomFieldsSchema)
    : baseLeadFormSchema;

  return withConditionalRules(objectSchema);
};

export const leadFormSchema = buildLeadFormSchema();
