const Sequelize = require("sequelize");
const Vouchers = require("../../models/Vouchers");
const { filterUpdateValues } = require("../../helpers/common");
const { createAuditTrail } = require("../../helpers/sellerAuditTrail.service");
const SellersCompany = require("../../models/SellersCompany");

exports.getSellerVouchers = async (req, res, next) => {
  const { seller_id, seller_account_id, parent_company } = req;

  const { page = 1, limit = 20 } = req.pagination;
  const { keyword = "", amount_sort = "DESC" } = req.query;

  try {
    const sellerIds = [seller_id];
    if (parent_company) {
      const childCompanies = await SellersCompany.findAll({
        where: {
          parent_company: seller_id,
        },
        attributes: ["id"],
      });
      childCompanies.forEach((company) => sellerIds.push(company.id));
    }

    const whereClause = {
      seller_voucher: {
        [Sequelize.Op.in]: sellerIds,
      },
      status: 1,
    };

    const orderClause = [];

    if (amount_sort) orderClause.push(["amount", amount_sort]);

    if (keyword !== "" || keyword !== null) {
      const voucherWhere = {
        [Sequelize.Op.like]: `%${keyword}%`,
      };
      whereClause.voucher_code = voucherWhere;
    }

    const offset = (page - 1) * limit;

    const sellerVouchersPromise = Vouchers.findAll({
      where: whereClause,
      limit,
      offset,
      order: orderClause,
    });

    const sellerVoucherCountPromise = Vouchers.count({
      where: whereClause,
    });

    const [sellerVouchers, sellerVoucherCount] = await Promise.all([
      sellerVouchersPromise,
      sellerVoucherCountPromise,
    ]);

    let mappedSellerVoucher = [];
    if (sellerVouchers.length > 0) {
      mappedSellerVoucher = sellerVouchers.map((voucher) => ({
        id: voucher.id,
        voucher_code: voucher.voucher_code,
        amount: voucher.amount,
        amount_in_percent: voucher.amount_in_percent,
        voucher_amount_in_percent: voucher.in_percent === "Yes" ? true : false,
        valid_until: voucher.valid_until,
        status: voucher.status === 1 ? true : false,
        min_amount_requirement: voucher.min_amount_requirement,
      }));
    }

    const totalPages = Math.ceil(sellerVoucherCount / limit);
    const hasNextPage = (page - 1) * limit + sellerVouchers.length < totalPages;
    const hasPreviousPage = page > 1;

    await createAuditTrail({
      seller_id: seller_account_id,
      seller_company_id: seller_id,
      module: "Vouchers",
      action: "view",
      action_description: ``,
    });

    res.status(200).json({
      success: true,
      vouchers: mappedSellerVoucher,
      pagination: {
        totalPages,
        currentPage: page,
        hasNextPage,
        hasPreviousPage,
      },
    });
  } catch (err) {
    next(err);
  }
};

exports.createSellerVoucher = async (req, res, next) => {
  const { seller_id, seller_account_id, parent_company } = req;
  try {
    const {
      voucher_code,
      amount,
      amount_in_percent,
      in_percent = false,
      valid_until,
      min_amount_requirement,
    } = req.body;

    if (!voucher_code || voucher_code === "" || voucher_code === null)
      return res
        .status(400)
        .json({ success: false, message: "Invalid voucher code." });
    if (in_percent && !amount_in_percent)
      return res
        .status(400)
        .json({ success: false, message: "Invalid amount in percent value." });
    if (!in_percent && !amount_in_percent && !amount)
      return res
        .status(400)
        .json({ success: false, message: "Invalid voucher amount." });
    if (!valid_until)
      return res
        .status(400)
        .json({ success: false, message: "Invalid voucher validity date." });

    if (parent_company) {
      return res
        .status(400)
        .json({
          success: false,
          message: "Parent company cannot create vouchers.",
        });
    }

    const _voucherCheck = await Vouchers.findAll({
      where: {
        voucher_code,
        status: true,
      },
    });

    if (_voucherCheck.length > 0)
      return res
        .status(400)
        .json({ success: false, message: "Voucher code exists!" });

    let voucherAmount = parseFloat(amount) || 0;
    if (in_percent) {
      const decimalValuePercent = parseFloat(amount_in_percent) / 100;
      voucherAmount = parseFloat(decimalValuePercent);
    }

    const createdVoucher = await Vouchers.create({
      voucher_code,
      amount: in_percent ? null : voucherAmount,
      amount_in_percent: in_percent ? voucherAmount : null,
      in_percent: in_percent ? "Yes" : null,
      valid_until,
      seller_voucher: seller_id,
      status: true,
      agent: "",
      min_amount_requirement: min_amount_requirement,
    });

    await createAuditTrail({
      seller_id: seller_account_id,
      seller_company_id: seller_id,
      module: "Vouchers",
      action: "create",
      action_description: `Created Voucher: ${createdVoucher.voucher_code}`,
    });

    res.status(201).json({ success: true, createdVoucher });
  } catch (err) {
    next(err);
  }
};

exports.softDeleteVoucher = async (req, res, next) => {
  try {
    const { seller_id, seller_account_id, parent_company } = req;
    const { voucher_id } = req.params;

    const sellerIds = [seller_id];
    if (parent_company) {
      const childCompanies = await SellersCompany.findAll({
        where: {
          parent_company: seller_id,
        },
        attributes: ["id"],
      });
      childCompanies.forEach((company) => sellerIds.push(company.id));
    }

    const _voucher = await Vouchers.findOne({
      where: {
        id: voucher_id,
        seller_voucher: {
          [Sequelize.Op.in]: sellerIds,
        },
      },
    });

    if (!_voucher)
      return res
        .status(400)
        .json({ success: false, message: "Voucher does not exists!" });

    _voucher.status = false;
    await _voucher.save();

    await createAuditTrail({
      seller_id: seller_account_id,
      seller_company_id: seller_id,
      module: "Vouchers",
      action: "delete",
      action_description: `Deleted voucher: ${_voucher.voucher_code}`,
    });
    res.status(200).json({ success: true });
  } catch (err) {
    next(err);
  }
};

exports.editSellerVoucher = async (req, res, next) => {
  try {
    const { seller_id, seller_account_id, parent_company } = req;
    const { voucher_id } = req.params;
    const {
      voucher_code,
      amount,
      amount_in_percent,
      in_percent,
      valid_until,
      min_amount_requirement,
    } = req.body;

    const sellerIds = [seller_id];
    if (parent_company) {
      const childCompanies = await SellersCompany.findAll({
        where: {
          parent_company: seller_id,
        },
        attributes: ["id"],
      });
      childCompanies.forEach((company) => sellerIds.push(company.id));
    }
    const _voucher = await Vouchers.findOne({
      where: {
        id: voucher_id,
        seller_voucher: {
          [Sequelize.Op.in]: sellerIds,
        },
      },
    });

    if (!_voucher)
      return res
        .status(400)
        .json({ success: false, message: "Voucher does not exist!" });

    let updateValues = {
      voucher_code,
      amount,
      amount_in_percent,
      in_percent,
      valid_until,
      min_amount_requirement,
    };

    updateValues = filterUpdateValues(updateValues);

    if ("voucher_code" in updateValues) {
      if (!updateValues.voucher_code || updateValues.voucher_code === "")
        return res
          .status(400)
          .json({ success: false, message: "Invalid voucher code." });

      const _voucherCheck = await Vouchers.findAll({
        where: {
          voucher_code: updateValues.voucher_code,
          status: 1,
          id: { [Sequelize.Op.ne]: voucher_id },
        },
      });

      if (_voucherCheck.length > 0)
        return res
          .status(400)
          .json({ success: false, message: "Voucher code exists!" });
    }

    const isInPercent =
      updateValues.in_percent === true || updateValues.in_percent === "Yes";

    if ("in_percent" in updateValues || "amount_in_percent" in updateValues) {
      if (isInPercent && !updateValues.amount_in_percent)
        return res.status(400).json({
          success: false,
          message: "Invalid amount in percent value.",
        });
    }

    if (!isInPercent && "amount" in updateValues && !updateValues.amount)
      return res
        .status(400)
        .json({ success: false, message: "Invalid voucher amount." });

    if ("valid_until" in updateValues && !updateValues.valid_until)
      return res
        .status(400)
        .json({ success: false, message: "Invalid voucher validity date." });

    let finalAmount = parseFloat(updateValues.amount) || 0;
    let finalPercent = null;

    if (isInPercent) {
      finalPercent = parseFloat(updateValues.amount_in_percent) / 100;
      finalAmount = null;
    }

    await _voucher.update({
      voucher_code: updateValues.voucher_code || _voucher.voucher_code,
      amount: isInPercent ? null : finalAmount,
      amount_in_percent: isInPercent ? finalPercent : null,
      in_percent: isInPercent ? "Yes" : null,
      valid_until: updateValues.valid_until || _voucher.valid_until,
      min_amount_requirement:
        updateValues.min_amount_requirement || _voucher.min_amount_requirement,
    });

    await createAuditTrail({
      seller_id: seller_account_id,
      seller_company_id: seller_id,
      module: "Vouchers",
      action: "edit",
      action_description: `Updated voucher: ${_voucher.voucher_code}`,
    });

    res.status(200).json({ success: true, updatedVoucher: _voucher });
  } catch (err) {
    next(err);
  }
};
