import { z } from "zod";

export const propertyImageSchema = z.object({
  url: z.string().url("Invalid image URL"),
  storagePath: z.string().optional().nullable().default(""),
  caption: z.string().max(255).optional().nullable(),
  isPrimary: z.boolean().default(false),
  displayOrder: z.number().int().default(0),
});

export const propertyDocumentSchema = z.object({
  title: z.string().min(1, "Document title is required").max(150),
  documentType: z.enum(["TITLE_DEED", "SURVEY_PLAN", "LAYOUT", "ID_CARD", "OTHER"]),
  storagePath: z.string().min(1, "Storage path is required"),
  fileSizeBytes: z.number().int().positive(),
  mimeType: z.string(),
  isPrivateToModerators: z.boolean().default(true),
});

export const propertyTypeSchema = z.preprocess((val) => {
  if (typeof val === "string") {
    const upper = val.toUpperCase().trim();
    if (upper === "APARTMENT" || upper === "FLAT" || upper === "LUXURY_APARTMENT" || upper === "SERVICED_APARTMENT") return "APARTMENT_FLAT";
    if (upper === "SEMI_DETACHED" || upper === "SEMI_DETACHED_DUPLEX") return "SEMI_DETACHED_DUPLEX";
    if (upper === "TERRACE_DUPLEX" || upper === "TERRACED_DUPLEX") return "TERRACED_DUPLEX";
    if (upper === "LAND" || upper === "LAND_RESIDENTIAL" || upper === "RESIDENTIAL_LAND") return "LAND_RESIDENTIAL";
    if (upper === "LAND_COMMERCIAL" || upper === "COMMERCIAL_LAND") return "LAND_COMMERCIAL";
    if (upper === "COMMERCIAL" || upper === "COMMERCIAL_OFFICE" || upper === "COMMERCIAL_BUILDING" || upper === "OFFICE") return "COMMERCIAL_OFFICE";
    if (upper === "SHORTLET" || upper === "SERVICED") return "APARTMENT_FLAT";
    if (upper === "PENTHOUSE" || upper === "MAISONETTE") return "MANSION";
  }
  return val;
}, z.enum([
  "APARTMENT_FLAT",
  "DETACHED_DUPLEX",
  "SEMI_DETACHED_DUPLEX",
  "TERRACED_DUPLEX",
  "MANSION",
  "BUNGALOW",
  "COMMERCIAL_OFFICE",
  "RETAIL_SHOP",
  "WAREHOUSE",
  "LAND_RESIDENTIAL",
  "LAND_COMMERCIAL",
  "MIXED_USE",
]));

export const titleTypeSchema = z.preprocess((val) => {
  if (typeof val === "string") {
    const upper = val.toUpperCase().trim();
    if (upper === "C_OF_O" || upper === "COFO" || upper === "CERTIFICATE_OF_OCCUPANCY") return "CERTIFICATE_OF_OCCUPANCY";
    if (upper === "COURT_JUDGMENT" || upper === "COURT_JUDGEMENT") return "COURT_JUDGEMENT";
    if (upper === "FREEHOLD" || upper === "SURVEY" || upper === "REGISTERED_SURVEY" || upper === "REGISTERED_SURVEY_PLAN") return "REGISTERED_SURVEY_PLAN";
    if (upper === "R_OF_O" || upper === "RIGHT_OF_OCCUPANCY") return "RIGHT_OF_OCCUPANCY";
    if (upper === "GOVERNORS_CONSENT" || upper === "GOVERNOR_CONSENT") return "GOVERNORS_CONSENT";
    if (upper === "DEED_OF_ASSIGNMENT" || upper === "DEED") return "DEED_OF_ASSIGNMENT";
    if (upper === "GAZETTE") return "GAZETTE";
    if (upper === "EXCISION") return "EXCISION";
    if (upper === "OTHER") return "OTHER";
  }
  return val;
}, z.enum([
  "CERTIFICATE_OF_OCCUPANCY",
  "GOVERNORS_CONSENT",
  "DEED_OF_ASSIGNMENT",
  "GAZETTE",
  "EXCISION",
  "REGISTERED_SURVEY_PLAN",
  "COURT_JUDGEMENT",
  "RIGHT_OF_OCCUPANCY",
  "OTHER",
  "NONE",
]).default("NONE"));

export const createPropertySchema = z.object({
  title: z
    .string()
    .min(5, "Title must be at least 5 characters")
    .max(255, "Title cannot exceed 255 characters"),
  description: z
    .string()
    .min(20, "Please provide a detailed description (at least 20 characters)"),
  listingType: z.enum(["FOR_SALE", "FOR_RENT", "SHORTLET", "JOINT_VENTURE"]),
  propertyType: propertyTypeSchema,
  price: z.number().positive("Price must be greater than 0"),
  currency: z.string().default("NGN"),
  pricePrefix: z.string().max(50).optional().nullable(),
  rentalFrequency: z.enum(["YEARLY", "MONTHLY", "DAILY"]).optional().nullable(),
  serviceCharge: z.number().nonnegative().default(0),
  cautionFee: z.number().nonnegative().default(0),
  legalFeePercentage: z.number().min(0).max(100).default(0),
  agencyFeePercentage: z.number().min(0).max(100).default(0),
  isNegotiable: z.boolean().default(false),

  // Specs
  bedrooms: z.number().int().min(0).default(0),
  bathrooms: z.number().int().min(0).default(0),
  toilets: z.number().int().min(0).default(0),
  parkingSpaces: z.number().int().min(0).default(0),
  totalAreaSqm: z.number().positive().optional().nullable(),
  plotSizePlots: z.number().positive().optional().nullable(),

  // Nigerian Title & Construction
  titleType: titleTypeSchema,
  isOffPlan: z.boolean().default(false),
  yearBuilt: z.number().int().min(1900).max(2100).optional().nullable(),

  // Location
  stateId: z.number().int().positive("Please select a Nigerian State"),
  lgaId: z.number().int().positive("Please select a Local Government Area (LGA)"),
  districtId: z.number().int().positive().optional().nullable(),
  streetAddress: z.string().max(255).optional().nullable(),
  landmark: z.string().max(255).optional().nullable(),
  latitude: z.number().min(-90, "Latitude must be between -90 and 90").max(90, "Latitude must be between -90 and 90").optional().nullable(),
  longitude: z.number().min(-180, "Longitude must be between -180 and 180").max(180, "Longitude must be between -180 and 180").optional().nullable(),
  hideExactAddress: z.boolean().default(false),

  // Attribution
  agencyId: z.string().uuid().optional().nullable(),

  // Status & Flags
  status: z.enum(["DRAFT", "PENDING_REVIEW", "PUBLISHED"]).default("DRAFT"),

  // Amenities & Media
  amenityIds: z.array(z.string()).default([]),
  images: z.array(propertyImageSchema).min(1, "Please upload at least 1 property photo"),
  documents: z.array(propertyDocumentSchema).default([]),
});

export const updatePropertySchema = createPropertySchema.partial();

export const propertyFilterSchema = z.object({
  search: z.string().optional(),
  listingType: z.enum(["FOR_SALE", "FOR_RENT", "SHORTLET", "JOINT_VENTURE"]).optional(),
  propertyType: z.string().optional(),
  stateId: z.coerce.number().optional(),
  lgaId: z.coerce.number().optional(),
  districtId: z.coerce.number().optional(),
  minPrice: z.coerce.number().optional(),
  maxPrice: z.coerce.number().optional(),
  bedrooms: z.coerce.number().optional(),
  bathrooms: z.coerce.number().optional(),
  titleType: z.string().optional(),
  amenities: z.array(z.string()).optional(),
  status: z.string().optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().positive().default(12),
  sortBy: z.enum(["newest", "price_asc", "price_desc", "views"]).default("newest"),
});

export type CreatePropertyInput = z.infer<typeof createPropertySchema>;
export type UpdatePropertyInput = z.infer<typeof updatePropertySchema>;
export type PropertyFilterInput = z.infer<typeof propertyFilterSchema>;
