/**
 * Real Estate Property Service
 * Provides property search and listing operations.
 */

import { prisma } from "@/lib/db";

interface SearchCriteria {
  pageSize?: number;
  sort?: string;
  status?: string;
  propertyType?: string;
  listingType?: string;
  city?: string;
  district?: string;
  minPrice?: number;
  maxPrice?: number;
  bedrooms?: number;
  minArea?: number;
  maxArea?: number;
}

interface PropertyResult {
  id: string;
  titleEn: string;
  titleAr: string | null;
  propertyType: string;
  listingType: string;
  status: string;
  price: number | null;
  currency: string;
  bedrooms: number | null;
  bathrooms: number | null;
  builtUpArea: number | null;
  city: string;
  district: string | null;
  referenceNumber: string | null;
}

export async function searchProperties(
  userId: string,
  criteria: SearchCriteria,
): Promise<{ properties: PropertyResult[]; total: number }> {
  const where: Record<string, unknown> = { userId };

  if (criteria.status) where.status = criteria.status;
  if (criteria.propertyType) where.propertyType = criteria.propertyType;
  if (criteria.listingType) where.listingType = criteria.listingType;
  if (criteria.city)
    where.city = { contains: criteria.city, mode: "insensitive" };
  if (criteria.district)
    where.district = { contains: criteria.district, mode: "insensitive" };
  if (criteria.bedrooms) where.bedrooms = criteria.bedrooms;

  if (criteria.minPrice || criteria.maxPrice) {
    const priceFilter: Record<string, number> = {};
    if (criteria.minPrice) priceFilter.gte = criteria.minPrice;
    if (criteria.maxPrice) priceFilter.lte = criteria.maxPrice;
    where.price = priceFilter;
  }

  if (criteria.minArea || criteria.maxArea) {
    const areaFilter: Record<string, number> = {};
    if (criteria.minArea) areaFilter.gte = criteria.minArea;
    if (criteria.maxArea) areaFilter.lte = criteria.maxArea;
    where.builtUpArea = areaFilter;
  }

  const orderBy: Record<string, string> =
    criteria.sort === "price"
      ? { price: "asc" }
      : criteria.sort === "oldest"
        ? { createdAt: "asc" }
        : { createdAt: "desc" };

  const take = Math.min(criteria.pageSize ?? 20, 100);

  const [properties, total] = await Promise.all([
    prisma.property.findMany({
      where,
      orderBy,
      take,
    }),
    prisma.property.count({ where }),
  ]);

  return {
    properties: properties.map((p) => ({
      id: p.id,
      titleEn: p.titleEn,
      titleAr: p.titleAr,
      propertyType: p.propertyType,
      listingType: p.listingType,
      status: p.status,
      price: p.price ? Number(p.price) : null,
      currency: p.currency,
      bedrooms: p.bedrooms,
      bathrooms: p.bathrooms,
      builtUpArea: p.builtUpArea ? Number(p.builtUpArea) : null,
      city: p.city,
      district: p.district,
      referenceNumber: p.referenceNumber,
    })),
    total,
  };
}
