import payloadConfig from "@/payload.config";
import { CardPropertyData } from "@/schema/property";
import { FetchPropertyDetailParams, FetchPropertyParams } from "@/schema/services/property";
import { formatDate } from "@/utils/datetime";
import { formatCurrency, getRandomNumber } from "@/utils/general";
import { getPayload, Where } from "payload";

export async function fetchProperty({
  page,
  name = "",
  location,
  min_price,
  max_price,
  min_area,
  max_area,
  property_type,
}: FetchPropertyParams = {}) {
  const payload = await getPayload({ config: payloadConfig });

  const queryCondition: Where = {
    _status: { equals: "published" },
  };

  if (!!property_type) {
    queryCondition["property_type"] = {
      equals: property_type,
    };
  }
  if (!!name) {
    queryCondition["name"] = {
      contains: name,
    };
  }
  if (!!min_price) {
    queryCondition["base_price"] = {
      greater_than_equal: min_price,
    };
  }
  if (!!max_price) {
    queryCondition["base_price"] = {
      less_than_equal: max_price,
    };
  }
  if (!!min_area) {
    queryCondition["aboutGroup.area"] = {
      greater_than_equal: min_area,
    };
  }
  if (!!max_area) {
    queryCondition["aboutGroup.area"] = {
      less_than_equal: max_area,
    };
  }
  if (!!location) {
    queryCondition["addressGroup.state_code"] = {
      equals: location,
    };
  }

  const dataQuery = await payload.find({
    collection: "properties",
    page,
    pagination: true,
    limit: 10,
    where: queryCondition,
  });

  const formattedData: CardPropertyData[] = dataQuery.docs.map((item) => {
    return {
      slug: item.slug ?? "",
      title: item.name,
      price: item.base_price,
      area: item.aboutGroup.area,
      propertyType: item.property_type,
      bathrooms_count: item.aboutGroup.bathrooms_count,
      bedrooms_count: item.aboutGroup.bedrooms_count,
      images: item.images.map((img) =>
        typeof img !== "number" ? { url: img?.url ?? "", alt: img.alt } : { url: "", alt: "" }
      ),
      posted_at: formatDate(item.createdAt),
    };
  });

  return {
    ...dataQuery,
    formattedData,
  };
}

export async function fetchPropertySuggestion() {
  const payload = await getPayload({ config: payloadConfig });
  const limitPerPage = 2;
  const countrQuery = await payload.count({
    collection: "properties",
    where: { _status: { equals: "published" } },
  });

  // randomize page
  let page = 1;
  const totalDocs = countrQuery.totalDocs;
  if (totalDocs > limitPerPage) {
    const totalPage = Math.ceil(totalDocs / limitPerPage);
    page = getRandomNumber(totalPage);
  }

  const dataQuery = await payload.find({
    collection: "properties",
    page,
    limit: limitPerPage,
  });

  const formattedData: CardPropertyData[] = dataQuery.docs.map((item) => {
    return {
      slug: item.slug ?? "",
      title: item.name,
      price: item.base_price,
      area: item.aboutGroup.area,
      propertyType: item.property_type,
      bathrooms_count: item.aboutGroup.bathrooms_count,
      bedrooms_count: item.aboutGroup.bedrooms_count,
      images: item.images.map((img) =>
        typeof img !== "number" ? { url: img?.url ?? "", alt: img.alt } : { url: "", alt: "" }
      ),
      posted_at: formatDate(item.createdAt),
    };
  });

  return {
    ...dataQuery,
    formattedData,
  };
}

export async function fetchPropertyDetail({ slug }: FetchPropertyDetailParams) {
  const payload = await getPayload({ config: payloadConfig });

  const queryCondition: Where = {
    _status: { equals: "published" },
    slug: { equals: slug },
  };

  const dataQuery = await payload.find({
    collection: "properties",
    where: queryCondition,
    limit: 1,
    pagination: false,
  });

  if (!dataQuery?.docs?.[0]) return null;

  const data = dataQuery?.docs?.[0];
  const postedAt = formatDate(data.createdAt);
  const images = data.images.map((img) =>
    typeof img !== "number" ? { url: img?.url ?? "", alt: img.alt } : { url: "", alt: "" }
  );

  const formattedBasePrice = formatCurrency(data.base_price);
  const additionalPrice: { name: string; price: string }[] = [];
  let totalPrice = 0;
  if (Array.isArray(data.additional_price)) {
    for (const p of data.additional_price) {
      additionalPrice.push({
        name: p.name,
        price: formatCurrency(p.price),
      });
      totalPrice += p.price;
    }
  }
  const formattedTotalPrice = formatCurrency(data.base_price + totalPrice);

  return {
    data,
    formattedData: {
      price: formattedBasePrice,
      additionalPrice,
      totalPrice: formattedTotalPrice,
      images,
      postedAt,
    },
  };
}

export async function fetchPropertyLatest() {
  const payload = await getPayload({ config: payloadConfig });
  const limitPerPage = 6;
  const dataQuery = await payload.find({
    collection: "properties",
    limit: limitPerPage,
  });

  const formattedData: CardPropertyData[] = dataQuery.docs.map((item) => {
    return {
      slug: item.slug ?? "",
      title: item.name,
      price: item.base_price,
      area: item.aboutGroup.area,
      propertyType: item.property_type,
      bathrooms_count: item.aboutGroup.bathrooms_count,
      bedrooms_count: item.aboutGroup.bedrooms_count,
      images: item.images.map((img) =>
        typeof img !== "number" ? { url: img?.url ?? "", alt: img.alt } : { url: "", alt: "" }
      ),
      posted_at: formatDate(item.createdAt),
    };
  });

  return {
    ...dataQuery,
    formattedData,
  };
}
