const { error, success } = require("../../handlers");
const {
  Property,
  Address,
  PropertyFeatures,
  PropertyImages,
  PayOnAccess,
  User,
  Report,
  Bookmark,
  PropertyView,
  FeaturedProperty,
  Plan,
  PropertyLead,
} = require("../../models");
const { getReqInformation, getSettings } = require("../../utils/Common");
const { updateAddress, addAddress } = require("./AddressController");
const { Op, fn, col, literal } = require("sequelize");
const {
  addPropertyFeature,
  deletePropertyFeature,
} = require("./PropertyFeatureController");
const { addImage } = require("./PropertyImageController");
const { getLatLongByAddress } = require("../../utils/GoogleMap");
const sequelize = require("../../utils/Connection");
const axios = require("axios");
const envCredential = require("../../config");
const MAP_API_KEY = envCredential.GOOGLE_MAP_API_KEY;

const index = async (req, res) => {
  try {
    let query = { propertyStatus: 1 },
      addressQuery = {};
    let properties = [];
    let recentlyAddedProperties = [];
    let trendingProperties = [];
    if (req.params?.id) {
      query = { id: req.params?.id };
      properties = await Property.findAll({
        where: query,
        order: [
          ["featured", "desc"],
          ["id", "desc"],
        ],
        attributes: [
          "id",
          "name",
          "type",
          "status",
          "addressId",
          "price",
          "image",
          "description",
          "furnishing",
          "propertyStatus",
          "payOnAccess",
          "featured",
          "listedBy",
          "propertyExtraFlags",
          "reraNumber",
          "propertyKind",
          "noOfRooms",
          "noOfBathRooms",
          "nearbyFecilities",
          "videoLink",
          "area",
          "totalFloors",
          "propertyOnFloor",
          "brochureUrl",
        ],
        include: [
          {
            model: Address,
            attributes: [
              "id",
              "street",
              "city",
              "postalCode",
              "state",
              "latitude",
              "longitude",
            ],
            // where: addressQuery,
          },
          {
            model: PropertyFeatures,
            attributes: ["id", "key", "value"],
          },
          {
            model: PropertyImages,
            attributes: ["propertyId", "id", "path"],
          },
          {
            model: User,
            attributes: [
              "firstName",
              "lastName",
              "email",
              "mobileNo",
              "userType",
              "image",
              "coverImage",
            ],
          },
          {
            model: FeaturedProperty,
            include: [
              {
                model: Plan,
              },
            ],
          },
        ],
      });
      if (req.query?.viewLongitude && req.query?.viewLatitude) {
        const url = `https://maps.googleapis.com/maps/api/geocode/json?latlng=${req.query?.viewLatitude},${req.query?.viewLongitude}&key=${MAP_API_KEY}`;
        const data = await axios.get(url);
        if(data.data){
          const result = data.data?.results[0]?.address_components;
          if(result){
            const resultData = result.find(e=> e.types.includes("locality"));
            if(resultData){
              await PropertyView.create({
                propertyId: req.params?.id,
                city: resultData?.long_name ?? req.query?.cityForView,
                longitude: req.query?.viewLongitude,
                latitude: req.query?.viewLatitude
              });
            }
          }

        }
      }
    } else {
      let payload = req?.query || {};
      if (payload?.status) {
        query["status"] = payload?.status;
      }
      if (payload?.type) {
        query["type"] = payload?.type;
      }

      if (payload?.startPrice && payload?.endPrice) {
        query["price"] = {
          [Op.lte]: payload?.endPrice,
          [Op.gte]: payload?.startPrice,
        };
      }
      if (payload?.q) {
        query = {
          ...query,
          [Op.or]: [
            {
              name: {
                [Op.like]: `%${payload?.q}%`,
              },
              description: {
                [Op.like]: `%${payload?.q}%`,
              },
            },
          ],
        };
        addressQuery = {
          [Op.or]: [
            {
              street: {
                [Op.like]: `%${payload?.q}%`,
              },
            },
            {
              city: {
                [Op.like]: `%${payload?.q}%`,
              },
            },
            {
              state: {
                [Op.like]: `%${payload?.q}%`,
              },
            },
          ],
        };
      }
      if (payload.isReraApproved != undefined) {
        query["reraNumber"] = {
          [Op.ne]: null,
        };
      }
      if (payload.noOfRooms) {
        query["noOfRooms"] = payload.noOfRooms;
      }
      if (payload.propertyKind) {
        query["propertyKind"] = payload.propertyKind;
      }
      if (payload.noOfBathRooms) {
        query["noOfBathRooms"] = payload.noOfBathRooms;
      }
      if (payload.area) {
        query["area"] = payload.area;
      }
      if (payload.furnishing) {
        query["furnishing"] = payload.furnishing;
      }
      if (payload.nearByFacilities) {
        query[`${[Op.or]}`] = payload.nearByFacilities?.map((e) => {
          return {
            nearbyFecilities: {
              [Op.like]: `%${e}%`,
            },
          };
        });
      }
      if (payload.isFeatured != null && payload.isFeatured != "") {
        query["featured"] = payload.isFeatured;
      }
      let lat = 0,
        long = 0,
        radius = 100;
      if (payload?.lat && payload?.long) {
        lat = payload?.lat;
        long = payload?.long;
      }
      if (lat && long) {
        let xyz = `(6371 * acos(cos(radians(${lat})) * cos(radians(address.latitude)) * cos(radians(address.longitude) - radians(${long})) + sin(radians(${lat})) * sin(radians(address.latitude))))`;

        properties = await Property.findAll({
          where: query,
          order: [
            [sequelize.literal(xyz), "asc"],
            ["featured", "desc"],
            ["id", "desc"],
          ],
          attributes: [
            "id",
            "name",
            "type",
            "status",
            "addressId",
            "price",
            "image",
            "description",
            "furnishing",
            "propertyStatus",
            "payOnAccess",
            "featured",
            "listedBy",
            "propertyKind",
            "videoLink",
            "propertyExtraFlags",
            "reraNumber",
            "noOfRooms",
            "noOfBathRooms",
            "nearbyFecilities",
            "area",
            "totalFloors",
            "propertyOnFloor",
            "brochureUrl",
          ],
          include: [
            {
              model: Address,
              attributes: [
                "id",
                "street",
                "city",
                "postalCode",
                "state",
                "latitude",
                "longitude",
                [sequelize.literal(xyz), "distance"],
              ],
              // where: addressQuery,
            },
            {
              model: PropertyFeatures,
              attributes: ["id", "key", "value"],
            },
            {
              model: PropertyImages,
              attributes: ["propertyId", "id", "path"],
            },
            {
              model: User,
              attributes: [
                "firstName",
                "lastName",
                "email",
                "mobileNo",
                "userType",
                "image",
                "coverImage",
              ],
            },
          ],
          having: sequelize.where(sequelize.literal(xyz), "<", radius),
        });
      } else {
        properties = await Property.findAll({
          where: query,
          order: [
            ["featured", "desc"],
            ["id", "desc"],
          ],
          attributes: [
            "id",
            "name",
            "type",
            "status",
            "addressId",
            "price",
            "image",
            "description",
            "furnishing",
            "propertyStatus",
            "payOnAccess",
            "featured",
            "listedBy",
            "propertyKind",
            "videoLink",
            "propertyExtraFlags",
            "reraNumber",
            "noOfRooms",
            "noOfBathRooms",
            "nearbyFecilities",
            "area",
            "totalFloors",
            "propertyOnFloor",
            "brochureUrl",
          ],
          include: [
            {
              model: Address,
              attributes: [
                "id",
                "street",
                "city",
                "postalCode",
                "state",
                "latitude",
                "longitude",
              ],
              // where: addressQuery,
            },
            {
              model: PropertyFeatures,
              attributes: ["id", "key", "value"],
            },
            {
              model: PropertyImages,
              attributes: ["propertyId", "id", "path"],
            },
            {
              model: User,
              attributes: [
                "firstName",
                "lastName",
                "email",
                "mobileNo",
                "userType",
                "image",
                "coverImage",
              ],
            },
          ],
        });
      }
      recentlyAddedProperties = await Property.findAll({
        where: query,
        order: [["createdAt", "desc"]],
        attributes: [
          "id",
          "name",
          "type",
          "status",
          "addressId",
          "price",
          "image",
          "description",
          "furnishing",
          "propertyStatus",
          "payOnAccess",
          "featured",
          "listedBy",
          "propertyKind",
          "videoLink",
          "propertyExtraFlags",
          "reraNumber",
          "noOfRooms",
          "noOfBathRooms",
          "nearbyFecilities",
          "area",
          "totalFloors",
          "propertyOnFloor",
          "brochureUrl",
        ],
        include: [
          {
            model: Address,
            attributes: [
              "id",
              "street",
              "city",
              "postalCode",
              "state",
              "latitude",
              "longitude",
            ],
            // where: addressQuery,
          },
          {
            model: PropertyFeatures,
            attributes: ["id", "key", "value"],
          },
          {
            model: PropertyImages,
            attributes: ["propertyId", "id", "path"],
          },
          {
            model: User,
            attributes: [
              "firstName",
              "lastName",
              "email",
              "mobileNo",
              "userType",
              "image",
              "coverImage",
            ],
          },
        ],
      });
      trendingProperties = await Property.findAll({
        where: query,
        order: [
          [literal("viewCount"), "DESC"],
          ["id", "desc"],
        ],
        attributes: [
          "id",
          "name",
          "type",
          "status",
          "addressId",
          "price",
          "image",
          "description",
          "furnishing",
          "propertyStatus",
          "payOnAccess",
          "featured",
          "listedBy",
          "propertyKind",
          "videoLink",
          "propertyExtraFlags",
          "reraNumber",
          "noOfRooms",
          "noOfBathRooms",
          "nearbyFecilities",
          "area",
          "totalFloors",
          "propertyOnFloor",
          "brochureUrl",
          [fn("COUNT", col("propertyViews.id")), "viewCount"],
        ],
        include: [
          {
            model: Address,
            attributes: [
              "id",
              "street",
              "city",
              "postalCode",
              "state",
              "latitude",
              "longitude",
            ],
            // where: addressQuery,
          },
          {
            model: PropertyFeatures,
            attributes: ["id", "key", "value"],
          },
          {
            model: PropertyImages,
            attributes: ["propertyId", "id", "path"],
          },
          {
            model: User,
            attributes: [
              "firstName",
              "lastName",
              "email",
              "mobileNo",
              "userType",
              "image",
              "coverImage",
            ],
          },
          {
            model: PropertyView,
            attributes: [], // Don't include actual view records, just count
            required: false, // left join, include properties even if no views
          },
        ],
      });
    }

    let settings = await getSettings();

    let result = await Promise.all(
      properties.map(async (property) => {
        property.dataValues["isBookmarked"] = false;
        if (!property?.user) {
          property.dataValues["user"] = {
            firstName: "Admin",
            lastName: "",
            mobileNo: settings?.contactInfoMobileNo ?? "",
            email: settings?.contactInfoEmail ?? "",
            image: null,
            coverImage: null,
          };
        }
        property.dataValues["payonaccess"] = null;
        if (req?.user) {
          if (req?.user?.planActivationDate) {
            property.dataValues.payonaccess = { userId: req?.user?.id };
          } else {
            let payOnAccess = await PayOnAccess.findOne({
              where: {
                propertyId: property?.id,
                userId: req?.user?.id,
              },
              raw: true,
            });
            property.dataValues.payonaccess = payOnAccess || null;
          }
          const isBookmarked = await Bookmark.findOne({
            where: {
              userId: req?.user?.id,
              propertyId: property?.id,
            },
          });
          property.dataValues["isBookmarked"] = isBookmarked ? true : false;
        }
        return property;
      })
    );
    recentlyAddedProperties = await Promise.all(
      recentlyAddedProperties.map(async (property) => {
        property.dataValues["isBookmarked"] = false;
        if (!property?.user) {
          property.dataValues["user"] = {
            firstName: "Admin",
            lastName: "",
            mobileNo: settings?.contactInfoMobileNo ?? "",
            email: settings?.contactInfoEmail ?? "",
          };
        }
        property.dataValues["payonaccess"] = null;
        if (req?.user) {
          if (req?.user?.planActivationDate) {
            property.dataValues.payonaccess = { userId: req?.user?.id };
          } else {
            let payOnAccess = await PayOnAccess.findOne({
              where: {
                propertyId: property?.id,
                userId: req?.user?.id,
              },
              raw: true,
            });
            property.dataValues.payonaccess = payOnAccess || null;
          }
          const isBookmarked = await Bookmark.findOne({
            where: {
              userId: req?.user?.id,
              propertyId: property?.id,
            },
          });
          property.dataValues["isBookmarked"] = isBookmarked ? true : false;
        }
        return property;
      })
    );
    trendingProperties = await Promise.all(
      trendingProperties.map(async (property) => {
        property.dataValues["isBookmarked"] = false;
        if (!property?.user) {
          property.dataValues["user"] = {
            firstName: "Admin",
            lastName: "",
            mobileNo: settings?.contactInfoMobileNo ?? "",
            email: settings?.contactInfoEmail ?? "",
          };
        }
        property.dataValues["payonaccess"] = null;
        if (req?.user) {
          if (req?.user?.planActivationDate) {
            property.dataValues.payonaccess = { userId: req?.user?.id };
          } else {
            let payOnAccess = await PayOnAccess.findOne({
              where: {
                propertyId: property?.id,
                userId: req?.user?.id,
              },
              raw: true,
            });
            property.dataValues.payonaccess = payOnAccess || null;
          }
          const isBookmarked = await Bookmark.findOne({
            where: {
              userId: req?.user?.id,
              propertyId: property?.id,
            },
          });
          property.dataValues["isBookmarked"] = isBookmarked ? true : false;
        }
        return property;
      })
    );
    return success(res, {
      msg: "Properties listed successfully!!",
      data: result,
      otherData: {
        recentlyAddedProperties,
        trendingProperties,
      },
    });
  } catch (err) {
    console.log(err);
    return error(res, {
      msg: "Something went wrong",
    });
  }
};

const addProperty = async (req, res) => {
  try {
    let { baseUrl } = getReqInformation(req);
    let payload = req.body,
      id = req.body?.id;
    payload["userId"] = req?.user?.id;

    let address = {
      street: payload?.street,
      city: payload?.city,
      state: payload?.state,
      postalCode: payload?.postalCode,
    };
    let addressData = `${address.street},${address.city},${address.state},${address.postalCode},IN`;
    let detail = await getLatLongByAddress(addressData);
    address["latitude"] = detail.latitude;
    address["longitude"] = detail.longitude;
    if ("image" in payload) {
      delete payload.image;
    }
    if (req.files?.image?.length) {
      payload["image"] = baseUrl + "/uploads/" + req.files.image[0]?.filename;
    }
    if (req.files?.video?.length) {
      payload["videoLink"] =
        baseUrl + "/uploads/" + req.files.video[0]?.filename;
    }
    console.log(req.body);
    payload["totalPrice"] = payload?.price;
    let msg = "Property added successfully";
    if (payload?.id) {
      // if (req.file?.path) {
      //   payload["image"] = baseUrl + "/uploads/" + req.file?.filename;
      // }
      delete payload.id;
      await updateAddress(payload?.addressId, address);
      console.log("=-=-=-", id, "=-=-=-");
      msg = "Property updated successfully";
      await Property.update(payload, {
        where: {
          id: id,
        },
      });
    } else {
      // if (!req.file?.path) {
      //   return error(res, {
      //     msg: "Please select file",
      //   });
      // }
      // payload["image"] = baseUrl + "/uploads/" + req.file?.filename;
      let addedAddress = await addAddress(address);
      payload["addressId"] = addedAddress?.id;
      let property = await Property.create(payload);
      id = property.id;
    }

    console.log(id, "-=-=-=-");
    if (req.files?.image?.length) {
      await Promise.all(
        req.files.image?.map(async (file) => {
          let image = baseUrl + "/uploads/" + file?.filename;
          await addImage({ propertyId: id, path: image });
        })
      );
    }

    let propertyFeatures = JSON.parse(
      payload?.propertyFeatures ?? JSON.stringify([])
    );

    if (propertyFeatures?.length > 0) {
      await deletePropertyFeature(id);
      let obj = {};
      propertyFeatures?.map(async (feature) => {
        if(feature.key?.toLowerCase() == "plotarea"){
          obj["area"] = feature?.value;
        }else if(feature.key?.toLowerCase() == "bedroom"){
          obj["noOfRooms"] = feature?.value;
        }else if(feature.key?.toLowerCase() == "bathroom"){
          obj["noOfBathRooms"] = feature?.value;
        }else if(feature.key?.toLowerCase() == "floorarea"){
          obj["area"] = feature?.value;
        }
        feature["propertyId"] = id;
        await addPropertyFeature(feature);
      });
      if(Object.keys(obj).length > 0){
        await Property.update(obj, { where: { id : id } });
      }
    }
    return success(res, {
      msg: msg,
    });
  } catch (err) {
    console.log(err);
    return error(res, {
      msg: "Something went wrong!!",
      error: [err?.message],
    });
  }
};

const getUserProperties = async (req, res) => {
  try {
    let userId = req.user?.id;

    let properties = await Property.findAll({
      where: {
        userId: userId,
      },
      order: [["id", "desc"]],
      attributes: [
        "id",
        "name",
        "type",
        "status",
        "addressId",
        "price",
        "image",
        "description",
        "furnishing",
        "propertyStatus",
        "payOnAccess",
        "featured",
        "listedBy",
        "brochureUrl",
        "videoLink",
      ],
      include: [
        {
          model: Address,
          attributes: ["street", "city", "state", "postalCode"],
        },
        {
          model: PropertyFeatures,
          attributes: ["id", "key", "value"],
        },
        {
          model: PropertyImages,
          attributes: ["propertyId", "id", "path"],
        },
      ],
    });

    properties = await Promise.all(
      properties.map(async (property) => {
        property.dataValues["viewCount"] = await PropertyView.count({
          where: {
            propertyId: property?.id,
          },
        });
        property.dataValues["bookMarkedCount"] = await Bookmark.count({
          where: {
            propertyId: property?.id,
          },
        });
        const isBookmarked = await Bookmark.findOne({
          where: {
            userId: req?.user?.id,
            propertyId: property?.id,
          },
        });
        property.dataValues["isBookmarked"] = isBookmarked ? true : false;
        return property;
      })
    );

    return success(res, {
      msg: "Properties listed successfully!!",
      data: properties,
    });
  } catch (err) {
    return error(res, {
      msg: "Something went wrong!!",
      error: [err?.message],
    });
  }
};

const deleteImage = async (req, res) => {
  try {
    let { propertyId, id } = req.params;
    await PropertyImages.destroy({
      where: {
        propertyId: propertyId,
        id: id,
      },
    });

    return success(res, {
      status: true,
      msg: "Images deleted successfully!!",
    });
  } catch (err) {
    return error(res, {
      status: false,
      msg: "Something went wrong!!",
      error: [err?.message],
    });
  }
};

const initiatePayment = async (req, res) => {
  try {
    let payload = req.body;
    payload["userId"] = req?.user?.id;
    let checkAlreadyPaid = await PayOnAccess.findOne({
      where: {
        propertyId: payload?.propertyId,
        userId: payload?.userId,
      },
    });
    if (checkAlreadyPaid) {
      return error(res, {
        msg: "You have already paid amount to see property details. if you still getting issue please contact admin",
      });
    }
    let property = await Property.findByPk(payload?.propertyId);
    if (!property) {
      return error(res, {
        msg: "Provided property doesn't exists!!",
      });
    }
    payload["amount"] = property?.payOnAccess;
    await PayOnAccess.create(payload);
    return success(res, {
      msg: "You have paid amount to see property details.",
    });
  } catch (err) {
    return error(res, {
      msg: "Something went wrong!!",
    });
  }
};

const report = async (req, res) => {
  try {
    let payload = req.body;
    payload["userId"] = req?.user?.id;
    await Report.create(payload);

    return success(res, {
      msg: "Property reported sent successfully!!",
    });
  } catch (err) {
    return error(res, {
      msg: "Something went wrong!!",
    });
  }
};

const deleteProperty = async (req, res) => {
  try {
    let id = req.params.propertyId;
    let property = await Property.findOne({
      where: {
        id: id,
        userId: req.user?.id,
      },
    });
    if (!property) {
      return error(res, {
        msg: "No property found with this id!!",
      });
    }
    await Bookmark.destroy({
      where: {
        propertyId: id,
      },
    });
    await Address.destroy({
      where: {
        id: property.addressId,
      },
    });
    await PropertyFeatures.destroy({
      where: {
        propertyId: id,
      },
    });
    await PropertyImages.destroy({
      where: {
        propertyId: id,
      },
    });
    property.destroy();
    return success(res, {
      msg: "Property deleted successfully!!",
      data: [],
    });
  } catch (err) {
    console.log(err);
    return error(res, {
      msg: "Something went wrong!!",
    });
  }
};

const getPropertyAnalysis = async (req, res) => {
  try {
    let data = {
      name: "",
      totalViews: 0,
      totalFavorites: 0,
      propertyViewsByCities: [],
      leads: [],
      PropertyImages: [],
      videoLink: "",
      daysLeft: 0
    };
    const property = await Property.findOne({
      id: req.params.id
    })
    data.name = property?.name;
    const featuredProperty = await FeaturedProperty.findOne({
      propertyId: req.params.id,
      order: [["id", "desc"]]
    });
    if(featuredProperty){
      const date2 = new Date(featuredProperty.expiresIn);
      const date1 = new Date();

      const diffTime = Math.abs(date2 - date1);
      diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
      data.daysLeft = diffDays;
    }
    data.propertyViewsByCities = await PropertyView.findAll({
      where: {
        propertyId: req.params.id,
      },
      attributes: [
        "city",
        [sequelize.fn("count", sequelize.col("city")), "totalCount"],
      ],
      group: ["city"],
    });

    data.PropertyImages = await PropertyImages.findAll({
      where: {
        propertyId: req.params.id,
      },
      attributes: ["propertyId", "id", "path"],
    });

    data.videoLink = await Property.findOne({
      where: {
        id: req.params.id,
      },
      attributes: ["videoLink"],
    });

    let count = data.propertyViewsByCities.reduce(
      (a, b) => a + parseInt(b.totalCount),
      0
    );
    data.totalViews = count;
    data.totalFavorites = await Bookmark.count({
      where: {
        propertyId: req.params.id,
      },
    });
    if (req.user.userType == "agent") {
      data.leads = await PropertyLead.findAll({
        where: {
          propertyId: req.params.id,
        },
        include: [
          {
            model: User,
            attributes: [
              "firstName",
              "lastName",
              "mobileNo",
              "image",
              "coverImage",
            ],
          },
        ],
      });
    }
    return success(res, {
      msg: "Property analysis listed successfully!!",
      data: [data],
    });
  } catch (err) {
    console.log(err);
    return error(res, {
      msg: "Something went wrong!!",
    });
  }
};

const leaderBoard = async (req, res) => {
  try {
    let sql = `SELECT 
    users.id,
    users.firstName,
    users.lastName,
    users.image,
    users.mobileNo,
    users.coverImage,
    COUNT(properties.id) AS propertyCount
  FROM users
  LEFT JOIN properties ON properties.userId = users.id
  GROUP BY users.id
  ORDER BY propertyCount DESC
  LIMIT 10;`;
    const [results, metadata] = await sequelize.query(sql);
    return success(res, {
      msg: "Leaderboard data listed successfully!!",
      data: results,
    });
  } catch (err) {
    console.log(err);
    return error(res, {
      msg: "Something went wrong!!",
    });
  }
};

const addPropertyLead = async (req, res) => {
  try {
    const propertyId = req.params.propertyId;
    const propertyLead = await PropertyLead.findOne({
      where: {
        propertyId: propertyId,
        userId: req.user.id,
      },
    });
    if (!propertyLead) {
      await PropertyLead.create({
        propertyId: propertyId,
        userId: req.user.id,
      });
    }
    return success(res, {
      msg: "Property lead added successfully!!",
    });
  } catch (err) {
    console.log(err);
    return error(res, {
      msg: "Something went wrong!!",
    });
  }
};

const getBoughtProperties = async(req, res) => {
  try{
    let properties = await PayOnAccess.findAll({
      where: {
        userId: req.user?.id
      },
      include: [
        {
          model: Property,
          attributes: [
            "id",
            "name",
            "type",
            "status",
            "addressId",
            "price",
            "image",
            "description",
            "furnishing",
            "propertyStatus",
            "payOnAccess",
            "featured",
            "listedBy",
            "propertyKind",
            "videoLink",
            "propertyExtraFlags",
            "reraNumber",
            "noOfRooms",
            "noOfBathRooms",
            "nearbyFecilities",
            "area",
            "totalFloors",
            "propertyOnFloor",
            "brochureUrl",
          ],
          include: [
            {
              model: Address,
              attributes: [
                "id",
                "street",
                "city",
                "postalCode",
                "state",
                "latitude",
                "longitude",
              ],
            },
            {
              model: PropertyFeatures,
              attributes: ["id", "key", "value"],
            },
            {
              model: PropertyImages,
              attributes: ["propertyId", "id", "path"],
            },
            {
              model: User,
              attributes: [
                "firstName",
                "lastName",
                "email",
                "mobileNo",
                "userType",
                "image",
                "coverImage",
              ],
            },
          ],
        }
      ]
    });

    properties = await Promise.all(properties?.map(async(boughtProperty) => {
      const isBookmarked = await Bookmark.findOne({
        where: {
          userId: req?.user?.id,
          propertyId: boughtProperty?.property?.id,
        },
      });
      boughtProperty = boughtProperty?.toJSON();
      boughtProperty.property["isBookmarked"] = isBookmarked ? true : false;
      return boughtProperty;
    }));

    return success(res, {
      msg: "Bought properties listed successfully!!",
      data: properties
    });
  } catch (err) {
    return error(res, {
      msg: "Something went wrong!!",
    });
  }
}

module.exports = {
  index,
  addProperty,
  getUserProperties,
  deleteImage,
  initiatePayment,
  report,
  deleteProperty,
  getPropertyAnalysis,
  addPropertyLead,
  leaderBoard,
  getBoughtProperties
};
