const Sequelize = require("sequelize");

const SellerModules = require("../../models/SellerModules");
const SellerGroups = require("../../models/SellerGroups");
const SellerGroupMembers = require("../../models/SellerGroupMembers");
const SellerGroupPermissions = require("../../models/SellerGroupPermissions");

const SellerFeatureFlags = require("../../models/SellerFeatureFlags");
const SellerControlFeatureFlags = require("../../models/SellerControlFeatureFlags");
const {
  SELLER_USER_PERMISSIONS_FLAG,
  SELLER_SETTINGS_MODULE,
  isUserHasPermissionToDoAction,
  isSellerHasFeatureFlag,
} = require("../../helpers/common");
const Seller = require("../../models/Seller");
const { createAuditTrail } = require("../../helpers/sellerAuditTrail.service");

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

  try {
    const hasFeatureFlag = await isSellerHasFeatureFlag(req);

    let mappedPermissions = [];

    if (!hasFeatureFlag) {
      const modules = await SellerModules.findAll();

      mappedPermissions = modules.map((module) => ({
        id: module.id,
        module: module.name,
        view_permission: true,
        add_permission: true,
        edit_permission: true,
        delete_permission: true,
      }));

      return res
        .status(200)
        .json({ success: true, permissions: mappedPermissions });
    }

    const sellerGroups = await SellerGroupMembers.findAll({
      where: {
        seller_id: seller_account_id,
        status: true,
      },
    });

    const groupIds = sellerGroups.map((g) => g.seller_group_id);

    const sellerGroupPermissions = await SellerGroupPermissions.findAll({
      where: {
        seller_group_id: groupIds,
        status: true,
      },
      include: [
        {
          model: SellerModules,
          as: "module",
        },
      ],
    });

    if (
      Array.isArray(sellerGroupPermissions) &&
      sellerGroupPermissions.length > 0
    ) {
      mappedPermissions = sellerGroupPermissions.map(
        ({
          id,
          view_permission,
          add_permission,
          edit_permission,
          delete_permission,
          module,
        }) => ({
          id,
          module: module.name,
          view_permission,
          add_permission,
          edit_permission,
          delete_permission,
        })
      );
    }

    res.status(200).json({ success: true, permissions: mappedPermissions });
  } catch (error) {
    next(error);
  }
};

exports.getUserPagePermission = async (req, res, next) => {
  const { seller_account_id, seller_id } = req;
  const { p: page } = req.query;

  if (!page)
    return res.status(400).json({ success: false, message: "Invalid query" });

  try {
    const hasFeatureFlag = await isSellerHasFeatureFlag(req);

    const sellerModule = await SellerModules.findOne({
      where: Sequelize.where(
        Sequelize.fn("LOWER", Sequelize.col("name")),
        page.toLowerCase()
      ),
    });

    if (!sellerModule)
      return res.status(400).json({ success: false, message: "Invalid page" });

    if (!hasFeatureFlag) {
      return res.status(200).json({
        success: true,
        permission: {
          id: sellerModule.id,
          module: sellerModule.name,
          view_permission: true,
          add_permission: true,
          edit_permission: true,
          delete_permission: true,
        },
      });
    }

    const sellerGroupMembers = await SellerGroupMembers.findAll({
      where: {
        seller_id: seller_account_id,
        status: true,
      },
    });

    const groupIds = sellerGroupMembers.map((g) => g.seller_group_id);

    const sellerGroupPermission = await SellerGroupPermissions.findAll({
      where: {
        seller_group_id: groupIds,
        seller_module_id: sellerModule.id,
      },
      include: [
        {
          model: SellerModules,
          as: "module",
        },
      ],
    });

    let mappedPermission = null;

    if (
      Array.isArray(sellerGroupPermission) &&
      sellerGroupPermission.length > 0
    ) {
      mappedPermission = {
        id: sellerGroupPermission[0].id,
        module: sellerGroupPermission[0].module.name,
        view_permission: sellerGroupPermission[0].view_permission,
        add_permission: sellerGroupPermission[0].add_permission,
        edit_permission: sellerGroupPermission[0].edit_permission,
        delete_permission: sellerGroupPermission[0].delete_permission,
      };
    }

    res.status(200).json({
      success: true,
      permission: mappedPermission,
    });
  } catch (error) {
    next(error);
  }
};
exports.addNewSellerGroup = async (req, res, next) => {
  const { seller_account_id, seller_id } = req;
  try {
    const { group_name } = req.body;
    if (!group_name)
      return res
        .status(200)
        .json({ success: false, message: "Group Name cannot be empty." });

    const hasFeatureFlag = await isSellerHasFeatureFlag(req);

    const isPermitted = await isUserHasPermissionToDoAction(
      "add",
      SELLER_SETTINGS_MODULE,
      seller_account_id
    );

    if (!isPermitted)
      return res
        .status(200)
        .json({ success: false, message: "Not Authorized" });

    const existingGroupName = await SellerGroups.findAll({
      where: {
        name: group_name,
        seller_company_id: seller_id,
        status: true,
      },
    });
    if (
      existingGroupName &&
      Array.isArray(existingGroupName) &&
      existingGroupName.length > 0
    )
      return res
        .status(200)
        .json({ success: false, message: "Group name already exists." });

    const createdSellerGroup = await SellerGroups.create({
      name: group_name,
      seller_company_id: seller_id,
      status: true,
    });

    const trail = await createAuditTrail({
      seller_id: seller_account_id,
      seller_company_id: seller_id,
      module: "Permissions",
      action: "add",
      action_description: `Added new seller group: ${group_name}`,
    });

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

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

  try {
    const isPermitted = await isUserHasPermissionToDoAction(
      "edit",
      SELLER_SETTINGS_MODULE,
      seller_account_id
    );

    if (!isPermitted)
      return res
        .status(200)
        .json({ success: false, message: "Not Authorized" });

    const { group_id } = req.params;
    const { group_name } = req.body;

    const existingGroupNamePromise = SellerGroups.findAll({
      where: {
        name: group_name,
        seller_company_id: seller_id,
        status: true,
      },
    });

    const sellerGroupPromise = SellerGroups.findOne({
      where: {
        id: group_id,
        seller_company_id: seller_id,
        status: true,
      },
    });

    const [existingGroupName, sellerGroup] = await Promise.all([
      existingGroupNamePromise,
      sellerGroupPromise,
    ]);

    if (
      existingGroupName &&
      Array.isArray(existingGroupName) &&
      existingGroupName.length > 0
    )
      return res
        .status(200)
        .json({ success: false, message: "Group name already exists." });
    if (!sellerGroup)
      return res
        .status(200)
        .json({ success: false, message: "Invalid group id." });

    sellerGroup.name = group_name;

    await sellerGroup.save();

    const trail = await createAuditTrail({
      seller_id: seller_account_id,
      seller_company_id: seller_id,
      module: "Permissions",
      action: "update",
      action_description: `Updated seller group: ${sellerGroup.name} > ${group_name}`,
    });

    res.status(200).json({ success: true });
  } catch (err) {
    next(err);
  }
};
exports.deleteSellerGroup = async (req, res, next) => {
  const { seller_account_id, seller_id } = req;

  try {
    const isPermitted = await isUserHasPermissionToDoAction(
      "delete",
      SELLER_SETTINGS_MODULE,
      seller_account_id
    );

    if (!isPermitted)
      return res
        .status(200)
        .json({ success: false, message: "Not Authorized" });

    const { group_id } = req.params;

    const sellerGroupPromise = SellerGroups.findOne({
      where: {
        id: group_id,
        seller_company_id: seller_id,
        status: true,
      },
    });

    const [sellerGroup] = await Promise.all([sellerGroupPromise]);

    if (!sellerGroup)
      return res
        .status(200)
        .json({ success: false, message: "Invalid group id." });

    sellerGroup.status = false;

    await sellerGroup.save();

    const trail = await createAuditTrail({
      seller_id: seller_account_id,
      seller_company_id: seller_id,
      module: "Permissions",
      action: "delete",
      action_description: `Deleted seller group: ${sellerGroup.name}`,
    });

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

exports.getSellerGroups = async (req, res, next) => {
  const { seller_account_id, seller_id } = req;
  try {
    const isPermitted = await isUserHasPermissionToDoAction(
      "view",
      SELLER_SETTINGS_MODULE,
      seller_account_id
    );

    if (!isPermitted)
      return res
        .status(200)
        .json({ success: false, message: "Not Authorized" });

    const sellerGroups = await SellerGroups.findAll({
      where: {
        seller_company_id: seller_id,
        status: true,
      },
    });
    res.status(200).json({ success: true, seller_groups: sellerGroups });
  } catch (err) {
    next(err);
  }
};

exports.getSellerGroupPermissionsAndUsersById = async (req, res, next) => {
  const { seller_account_id, seller_id } = req;
  try {
    const { group_id } = req.params;
    const isPermitted = await isUserHasPermissionToDoAction(
      "view",
      SELLER_SETTINGS_MODULE,
      seller_account_id
    );

    if (!isPermitted)
      return res
        .status(200)
        .json({ success: false, message: "Not Authorized" });

    if (!group_id)
      return res
        .status(200)
        .json({ success: false, message: "Group Id is undefined" });

    const sellerGroupDetail = await SellerGroups.findOne({
      where: {
        id: group_id,
        seller_company_id: seller_id,
        status: true,
      },
      include: [
        {
          model: SellerGroupPermissions,
          as: "group_permissions",
          include: [
            {
              model: SellerModules,
              as: "module",
            },
          ],
        },
        {
          model: SellerGroupMembers,
          as: "group_members",
          include: [
            {
              model: Seller,
              as: "seller",
            },
          ],
        },
      ],
    });
    if (!sellerGroupDetail)
      return res
        .status(200)
        .json({ success: false, message: "Seller group is undefined" });

    const { id, name, status, group_permissions, group_members } =
      sellerGroupDetail;

    const mappedPermissions = group_permissions.map(
      ({
        id,
        view_permission,
        add_permission,
        edit_permission,
        delete_permission,
        module,
      }) => ({
        id,
        module_id: module.id,
        module: module.name,
        view_permission,
        add_permission,
        edit_permission,
        delete_permission,
      })
    );

    const mappedGroupMembers = group_members
      .filter(({ seller }) => seller)
      .map(({ id, status, seller }) => ({
        id,
        status,
        seller: {
          id: seller.id,
          name: seller.name,
        },
      }));

    const responseJson = {
      id,
      name,
      status,
      group_permissions: mappedPermissions,
      group_members: mappedGroupMembers,
    };

    const trail = await createAuditTrail({
      seller_id: seller_account_id,
      seller_company_id: seller_id,
      module: "Permissions",
      action: "view",
      action_description: ``,
    });

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

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

  try {
    const isPermitted = await isUserHasPermissionToDoAction(
      "edit",
      SELLER_SETTINGS_MODULE,
      seller_account_id
    );

    if (!isPermitted)
      return res
        .status(200)
        .json({ success: false, message: "Not Authorized" });

    const { group_id } = req.params;
    const { module_id, permission_type = null, value = false } = req.body;

    if (!group_id)
      return res
        .status(200)
        .json({ success: false, message: "Group Id is undefined" });

    if (!permission_type)
      return res
        .status(200)
        .json({ success: false, message: "Permission type is undefined" });

    const sellerGroupPromise = SellerGroups.findOne({
      where: {
        id: group_id,
        status: true,
        seller_company_id: seller_id,
      },
    });
    const sellerModulePromise = SellerModules.findByPk(module_id);

    const [sellerGroup, sellerModule] = await Promise.all([
      sellerGroupPromise,
      sellerModulePromise,
    ]);

    if (!sellerGroup || !sellerModule)
      return res.status(200).json({ success: false, message: "Bad request" });

    const existingGroupPermission = await SellerGroupPermissions.findOne({
      where: {
        seller_module_id: sellerModule.id,
        seller_group_id: sellerGroup.id,
        status: true,
      },
    });

    if (existingGroupPermission) {
      existingGroupPermission[`${permission_type}_permission`] = value;
      await existingGroupPermission.save();
    }

    if (!existingGroupPermission) {
      const createdGroupPermission = await SellerGroupPermissions.create({
        seller_module_id: sellerModule.id,
        seller_group_id: sellerGroup.id,
        view_permission: false,
        add_permission: false,
        edit_permission: false,
        delete_permission: false,
        status: true,
      });

      createdGroupPermission[`${permission_type}_permission`] = value;
      await createdGroupPermission.save();
    }

    const trail = await createAuditTrail({
      seller_id: seller_account_id,
      seller_company_id: seller_id,
      module: "Permissions",
      action: "update",
      action_description: `Updated seller group permission: ${sellerGroup.name}`,
    });

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

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

  try {
    const isPermitted = await isUserHasPermissionToDoAction(
      "view",
      SELLER_SETTINGS_MODULE,
      seller_account_id
    );

    if (!isPermitted)
      return res
        .status(200)
        .json({ success: false, message: "Not Authorized" });

    // const { group_id } = req.params;

    // const groupMembers = await SellerGroupMembers.findAll({
    //   where: {
    //     seller_group_id: group_id,
    //     status: true,
    //   },
    //   attributes: ["seller_id"],
    // });

    // const memberIds = groupMembers.map((member) => member.seller_id);

    const sellerAccounts = await Seller.findAll({
      where: {
        seller_id: seller_id,
      },
      attributes: ["id", "username", "name"],
    });

    // const filteredSellerAccounts = sellerAccounts.filter(
    //   (account) => !memberIds.includes(account.id)
    // );
    res.status(200).json({ success: true, seller_accounts: sellerAccounts });
  } catch (err) {
    next(err);
  }
};

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

  try {
    const { action, new_user_seller_account_id, group_id } = req.body;

    switch (action) {
      case "add":
        const addPermission = await isUserHasPermissionToDoAction(
          "add",
          SELLER_SETTINGS_MODULE,
          seller_account_id
        );

        if (!addPermission)
          return res
            .status(200)
            .json({ success: false, message: "Not Authorized" });

        await SellerGroupMembers.create({
          seller_group_id: group_id,
          seller_id: new_user_seller_account_id,
          status: true,
        });

        await createAuditTrail({
          seller_id: seller_account_id,
          seller_company_id: seller_id,
          module: "Permissions Group",
          action: "add",
          action_description: `Added seller to group permission: ${group_id}`,
        });

        res.status(200).json({ success: true });
        break;

      case "delete":
        const deletePermission = await isUserHasPermissionToDoAction(
          "delete",
          SELLER_SETTINGS_MODULE,
          seller_account_id
        );

        if (!deletePermission)
          return res
            .status(200)
            .json({ success: false, message: "Not Authorized" });

        await createAuditTrail({
          seller_id: seller_account_id,
          seller_company_id: seller_id,
          module: "Permissions Group",
          action: "delete",
          action_description: `Removed seller to group permission: ${group_id}`,
        });
        await SellerGroupMembers.destroy({
          where: {
            seller_id: new_user_seller_account_id,
            seller_group_id: group_id,
          },
        });
        res.status(200).json({ success: true });
        break;

      default:
        return res
          .status(200)
          .json({ success: false, message: "Invalid action" });
        break;
    }
  } catch (err) {
    next(err);
  }
};

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

  try {
    const sellerModules = await SellerModules.findAll({
      where: {
        status: true,
      },
    });

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