const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");
const httpStatus = require("http-status");
require("dotenv").config();
const { Broker, AssignSite, Site, Plot } = require("../models");

const getpassword = async (req, res) => {
  const password = "12345678";
  const hashedPassword = await bcrypt.hash(password, 10);
  //  console.log (hashedPassword);
  res.status(httpStatus.CREATED).json({ msg: hashedPassword });
};

const getBroker = async (req, res) => {
  try {
    const spkg = await Broker.findAll({
      where: { is_delete: false },
    });
    await Promise.all(
      spkg.map(async (obj) => {
        // Fetch events for each event id
        const assignSite = await AssignSite.findAll({
          where: { broker_id: obj.dataValues.id },
        });
        if (assignSite.length > 0) {
          obj.dataValues.sites = JSON.parse(assignSite[0].dataValues.site_ids);
        } else {
          obj.dataValues.sites = [];
        }
      })
    );
    res
      .status(httpStatus.OK)
      .json({ msg: "Broker Fetch Successfully", broker: spkg });
  } catch (error) {
    console.error("Error saving broker data:", error);
    res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ msg: "Server error" });
  }
};

const addBroker = async (req, res) => {
  try {
    let exist = await Broker.findOne({
      where: { email: req.body.email },
    });
    if (exist) {
      return res
        .status(httpStatus.FORBIDDEN)
        .json({ msg: "Email Id Already Exist" });
    }

    req.body.is_active = 1;
    const hashedPassword = await bcrypt.hash(req.body.password, 10);
    req.body.password = hashedPassword;
    const broker = new Broker(req.body);
    await broker.save();
    res.status(httpStatus.CREATED).json({
      msg: `Broker Added Successfully`,
      data: broker,
    });
  } catch (error) {
    console.error("Error saving  data:", error);
    res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ msg: "Server error" });
  }
};

const updateBroker = async (req, res) => {
  try {
    let broker = await Broker.findOne({
      where: { id: req.params.id },
    });
    if (broker.is_delete == true) {
      return res
        .status(httpStatus.FORBIDDEN)
        .json({ msg: "Your account is deleted" });
    }

    if (broker.is_active == false) {
      return res
        .status(httpStatus.FORBIDDEN)
        .json({ msg: "Your account is deactive" });
    }

    if (!broker) {
      return res
        .status(httpStatus.BAD_REQUEST)
        .json({ msg: "Broker not found" });
    }

    await Broker.update(
      {
        ...req.body,
      },
      { where: { id: req.params.id } }
    );

    const updateBroker = await Broker.findOne({
      where: { id: req.params.id },
    });
    res.status(httpStatus.OK).json({
      msg: `Broker Update Successfully`,
      data: updateBroker,
    });
  } catch (error) {
    res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ msg: "Server error" });
  }
};

const changePassword = async (req, res) => {
  try {
    let broker = await Broker.findOne({
      where: { id: req.params.id },
    });
    if (broker.is_delete == true) {
      return res
        .status(httpStatus.FORBIDDEN)
        .json({ msg: "Your account is deleted" });
    }

    if (broker.is_active == false) {
      return res
        .status(httpStatus.FORBIDDEN)
        .json({ msg: "Your account is deactive" });
    }
    if (!broker) {
      return res
        .status(httpStatus.BAD_REQUEST)
        .json({ msg: "Broker not found" });
    }
    const hashedPassword = await bcrypt.hash(req.body.password, 10);
    req.body.password = hashedPassword;
    await Broker.update(
      {
        password: hashedPassword,
      },
      { where: { id: req.params.id } }
    );

    const updateBroker = await Broker.findOne({
      where: { id: req.params.id },
    });
    res.status(httpStatus.OK).json({
      msg: `Password Update Successfully`,
      data: updateBroker,
    });
  } catch (error) {
    res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ msg: "Server error" });
  }
};

const Newbrokerlogin = async (req, res) => {
  try {
    const { email, password } = req.body;

    const broker = await Broker.findOne({
      where: { email: email },
    });

    if (!broker) {
      return res
        .status(httpStatus.BAD_REQUEST)
        .json({ msg: "Invalid Email Id" });
    }

    if (broker.is_delete == true) {
      return res
        .status(httpStatus.FORBIDDEN)
        .json({ msg: "Your account is deleted" });
    }

    if (broker.is_active == false) {
      return res
        .status(httpStatus.FORBIDDEN)
        .json({ msg: "Your account is deactive" });
    }

    const isPasswordValid = await bcrypt.compare(password, broker.password);
    if (!isPasswordValid) {
      return res
        .status(httpStatus.BAD_REQUEST)
        .json({ msg: "Invalid password" });
    }
    const token = jwt.sign({ brokerId: broker.id }, "Bearar");
    if (broker) {
      return res.status(httpStatus.OK).json({
        msg: `Welcome ${broker.name}`,
        token: token,
        data: broker,
      });
    }
  } catch (error) {
    res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ msg: "server error" });
  }
};

const deleteBroker = async (req, res) => {
  try {
    const exist = await Broker.findOne({
      where: { is_delete: false, id: req.params.id },
    });
    if (!exist) {
      return res
        .status(httpStatus.BAD_REQUEST)
        .json({ msg: "Broker not found" });
    }
    const broker = await Broker.update(
      {
        is_delete: true,
      },
      { where: { is_delete: false, id: req.params.id } }
    );

    await Broker.update({ is_delete: true }, { where: { id: req.params.id } });

    res.status(httpStatus.OK).json({ msg: "Broker Delete Successfully" });
  } catch (error) {
    res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ msg: "Server error" });
  }
};

const activateBroker = async (req, res) => {
  try {
    const exist = await Broker.findOne({
      where: { is_delete: false, id: req.params.id },
    });
    if (!exist) {
      return res
        .status(httpStatus.BAD_REQUEST)
        .json({ msg: "Broker not found" });
    }
    const broker = await Broker.update(
      {
        is_active: !exist.dataValues.is_active,
      },
      { where: { is_delete: false, id: req.params.id } }
    );

    res.status(httpStatus.OK).json({ msg: "Broker Update Successfully" });
  } catch (error) {
    res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ msg: "Server error" });
  }
};

const assignSite = async (req, res) => {
  try {
    let exist = await Broker.findOne({
      where: { id: req.body.broker_id, is_delete: false },
    });
    if (!exist) {
      return res.status(httpStatus.FORBIDDEN).json({ msg: "Broker Not Exist" });
    }

    let brokerAssign = await AssignSite.findOne({
      where: { broker_id: req.body.broker_id },
    });

    if (brokerAssign) {
      await AssignSite.update(
        {
          ...req.body,
        },
        { where: { broker_id: req.body.broker_id } }
      );
    } else {
      const brokerA = new AssignSite(req.body);
      await brokerA.save();
    }
    let brokerAs = await AssignSite.findOne({
      where: { broker_id: req.body.broker_id },
    });

    res.status(httpStatus.CREATED).json({
      msg: `Assign project to broker successfully`,
      data: brokerAs,
    });
  } catch (error) {
    console.error("Error saving  data:", error);
    res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ msg: "Server error" });
  }
};

const getBrokerDashboard = async (req, res) => {
  try {
    // Check if broker exists
    let exist = await Broker.findOne({
      where: { id: req.params.broker_id, is_delete: false, is_active: true },
    });

    if (!exist) {
      return res.status(httpStatus.FORBIDDEN).json({ msg: "Broker Not Exist" });
    }

    // Fetch all assigned sites for the broker
    const allSite = await AssignSite.findAll({
      where: { broker_id: req.params.broker_id },
    });

    let totalSites = 0;
    let totalPlots = 0;
    let soldPlots = 0;
    let unsoldPlots = 0;

    // Process each site in parallel
    await Promise.all(
      allSite.map(async (obj) => {
        let siteIds = JSON.parse(obj.dataValues.site_ids);

        // Fetch all sites in one query instead of looping
        const sites = await Site.findAll({
          where: { id: siteIds, is_active: true, is_delete: false },
        });

        totalSites += sites.length; // Count total sites

        // Fetch all plots for the retrieved sites
        await Promise.all(
          sites.map(async (site) => {
            const plots = await Plot.findAll({
              where: { site_id: site.id, is_delete: false, is_active: true },
            });

            totalPlots += plots.length; // Count total plots
            soldPlots += plots.filter((plot) => plot.status === "Sold").length; // Count sold plots
            unsoldPlots += plots.filter(
              (plot) => plot.status === "Unsold"
            ).length; // Count unsold plots

            site.dataValues.plots = plots; // Attach plots to site
          })
        );

        obj.dataValues.sites = sites; // Attach sites to each assigned site
      })
    );

    res.status(httpStatus.OK).json({
      msg: "Broker Fetch Successfully",
      brokerSite: allSite,
      totalSites,
      totalPlots,
      soldPlots,
      unsoldPlots,
    });
  } catch (error) {
    console.error("Error fetching broker dashboard:", error);
    res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ msg: "Server error" });
  }
};

module.exports = {
  getpassword,
  Newbrokerlogin,
  addBroker,
  updateBroker,
  changePassword,
  deleteBroker,
  activateBroker,
  getBroker,
  assignSite,
  getBrokerDashboard,
};
