const { Op } = require("sequelize");
const {
  Property,
  Address,
  PropertyFeatures,
  User,
  Feedback,
  Bookmark,
  Plan,
} = require("../../models");
const { getReqInformation, getSettings } = require("../../utils/Common");
const {
  PropertyFeature,
  PropertyStatus,
  PropertyTypes,
  PropertyFurnishing,
  PropertyKind,
} = require("../../utils/Constants");
const sequelize = require("../../utils/Connection");
const { getLatLongByAddress } = require("../../utils/GoogleMap");

const index = async (req, res) => {
  let { baseUrl, endPoint } = getReqInformation(req);
  let user = req.session?.user ?? {};
  let query = { propertyStatus: 1 };
  let payload = req.query;
  if (payload?.status) {
    query["status"] = payload?.status;
  }
  if (payload?.type) {
    query["type"] = payload?.type;
  }

  if (payload?.price) {
    query["price"] = {
      [Op.lte]: payload?.price,
    };
  }
  let addressQuery = {};
  let lat = 0,
    long = 0,
    radius = 25;
  if (payload?.lat && payload?.long) {
    lat = payload?.lat;
    long = payload?.long;
  } else if (req.session.location?.lat && req.session.location?.long) {
    lat = req.session.location?.lat ?? 0;
    long = req.session.location?.long ?? 0;
  }
  if (payload?.location) {
    addressQuery = {
      [Op.or]: [
        {
          city: {
            [Op.like]: `%${payload?.location}%`,
          },
        },
        {
          street: {
            [Op.like]: `%${payload?.location}%`,
          },
        },
        {
          state: {
            [Op.like]: `%${payload?.location}%`,
          },
        },
      ],
    };
  }
  let properties = [];
  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: [["featured", "desc"]],
      include: [
        {
          model: Address,
          attributes: [
            "id",
            "street",
            "city",
            "postalCode",
            "state",
            "latitude",
            "longitude",
            [sequelize.literal(xyz), "distance"],
          ],
          where: addressQuery,
        },
        {
          model: PropertyFeatures,
          attributes: ["key", "value"],
        },
        {
          model: User,
          attributes: ["firstName", "lastName", "image"],
        },
      ],
      having: sequelize.where(sequelize.literal(xyz), "<", radius),
      limit: 6,
    });
  } else {
    properties = await Property.findAll({
      where: query,
      order: [["featured", "desc"]],
      include: [
        {
          model: Address,
          attributes: [
            "id",
            "street",
            "city",
            "postalCode",
            "state",
            "latitude",
            "longitude",
          ],
          where: addressQuery,
        },
        {
          model: PropertyFeatures,
          attributes: ["key", "value"],
        },
        {
          model: User,
          attributes: ["firstName", "lastName", "image"],
        },
      ],
      limit: 6,
    });
  }

  let propertyIds = properties.map((e) => e?.id);
  let bookmarks = [];
  if (req.session?.user) {
    bookmarks = await Bookmark.findAll({
      where: {
        userId: req.session?.user?.id,
        propertyId: {
          [Op.in]: propertyIds,
        },
      },
      raw: true,
    });
  }

  let cityWiseProperties = await Property.findAll({
    where: {
      propertyStatus: 1,
    },
    include: [
      {
        model: Address,
        required: true,
      },
    ],
    attributes: [
      [sequelize.fn("count", sequelize.col("properties.id")), "totalCount"],
      "image",
    ],
    group: ["address.city"],
    raw: true,
    nest: true,
  });

  let settings = await getSettings();

  let feedbacks = await Feedback.findAll({
    where: {
      status: true,
    },
    order: [["id", "desc"]],
    include: [
      {
        model: User,
        attributes: ["firstName", "lastName", "image"],
      },
    ],
    limit: 5,
  });

  console.log(user, "=-=-=-=-");

  // let agents = await User.findAll({
  //   where: {
  //     userType: "agent",
  //   },
  //   attributes: ["firstName", "lastName", "image", "id"],
  //   include: [
  //     {
  //       model: Property,
  //       attributes: [
  //         [sequelize.fn("count", sequelize.col("userId")), "totalCount"],
  //       ],
  //     },
  //   ],
  //   group: ["id"],
  //   raw: true,
  //   nest: true,
  //   limit: 4,
  // });

  let plans = await Plan.findAll({
    where: {
      type: "userplan",
    },
  });

  return res.render("index.ejs", {
    baseUrl,
    endPoint,
    properties,
    PropertyFeature,
    PropertyStatus,
    PropertyFurnishing,
    PropertyTypes,
    PropertyKind,
    oldFilterData: payload ?? {},
    user,
    cityWiseProperties,
    settings,
    feedbacks,
    bookmarks,
    plans,
    // agents,
  });
};

const updateLatLongOfAddress = async (req, res) => {
  try {
    let address = await Address.findAll({});
    await Promise.all(
      address.map(async (item) => {
        let addressData = `${item?.street},${item?.city},${item?.state},${item?.postalCode},IN`;
        console.log(addressData);
        let detail = await getLatLongByAddress(addressData);
        if (detail.latitude && detail.longitude) {
          item.latitude = detail.latitude;
          item.longitude = detail.longitude;
          await item.save();
        }
      })
    );
    return res.send({
      status: true,
      msg: "data updated successfully!!",
    });
  } catch (err) {
    return res.send({
      status: true,
      msg: "Something went wrong!!!!",
    });
  }
};

const refundReturnPolicy = async (req, res) => {
  let user = req.session?.user ?? {};
  let { baseUrl, endPoint } = getReqInformation(req);
  let settings = await getSettings();

  return res.render("refund-return-policy/index.ejs", {
    baseUrl,
    endPoint,
    user,
    settings,
  });
};

module.exports = {
  index,
  updateLatLongOfAddress,
  refundReturnPolicy,
};
