import models from "$models/index.js";

// Get all permissions
export const ALL = async (req, res) => {
  try {
    const permissions = await models.permission.find({ isActive: true }).sort({
      resource: 1,
      action: 1,
    });

    res.status(200).send({
      message: "permissions retrieved successfully",
      data: permissions,
    });
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

// Get permissions grouped by resource using aggregation
export const GROUPED = async (req, res) => {
  try {
    const groupedArray = await models.permission.aggregate([
      { $match: { isActive: true } },
      { $sort: { resource: 1, action: 1 } },
      {
        $group: {
          _id: "$resource",
          resource: { $first: "$resource" },
          resourceLabel: { $first: "$resourceLabel" },
          permissions: {
            $push: {
              _id: "$_id",
              key: "$key",
              action: "$action",
              label: "$label",
              description: "$description",
              isDangerous: "$isDangerous",
            },
          },
        },
      },
      { $sort: { resource: 1 } },
    ]);

    res.status(200).send({
      message: "Grouped permissions retrieved successfully",
      data: groupedArray,
    });
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

// Get single permission
export const SINGLE = async (req, res) => {
  try {
    const permission = await models.permission.findById(req.params.id);

    if (!permission) {
      return res.status(404).send({ message: "permission not found" });
    }

    res.status(200).send({
      message: "permission retrieved successfully",
      data: permission,
    });
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

export const CREATE = async (req, res) => {
  try {
    const { resource, label, description } = req.body;

    // Check if resource already exists
    const existing = await models.permission.findOne({ resource });
    if (existing) {
      return res.status(400).send({
        message: `Resource "${resource}" already exists`,
      });
    }

    // Define actions and labels
    const actions = ["view", "create", "update", "delete"];
    const actionLabels = {
      view: "مشاهده",
      create: "ایجاد",
      update: "ویرایش",
      delete: "حذف",
    };

    // Create 4 permissions for this resource
    const permissions = actions.map((action) => ({
      resource,
      resourceLabel: label,
      action,
      key: `${resource}:${action}`,
      label: `${actionLabels[action]} ${label}`,
      description: `${actionLabels[action]} ${description}`,
      isDangerous: action === "delete",
    }));

    const created = await models.permission.insertMany(permissions);

    res.status(201).send({
      message: `Created ${created.length} permissions for resource "${resource}"`,
      data: created,
    });
  } catch (error) {
    if (error.code === 11000) {
      return res
        .status(400)
        .send({ message: "permission with this key already exists" });
    }
    res.status(500).send({ message: error.message });
  }
};

export const UPDATE = async (req, res) => {
  try {
    const permission = await models.permission.findById(req.params.id);

    if (!permission) {
      return res.status(404).send({ message: "permission not found" });
    }

    const nextResourceLabel = String(
      req.body.label ?? req.body.resourceLabel ?? permission.resourceLabel,
    ).trim();
    const nextDescriptionBase = String(req.body.description ?? "").trim();

    const actionLabels = {
      view: "مشاهده",
      create: "ایجاد",
      update: "ویرایش",
      delete: "حذف",
    };

    const relatedPermissions = await models.permission.find({
      resource: permission.resource,
    });

    await Promise.all(
      relatedPermissions.map((item) => {
        const actionLabel = actionLabels[item.action] || "";
        const updatePayload = {
          resourceLabel: nextResourceLabel || item.resourceLabel,
          label: `${actionLabel} ${nextResourceLabel || item.resourceLabel}`.trim(),
          description: nextDescriptionBase
            ? `${actionLabel} ${nextDescriptionBase}`.trim()
            : "",
        };

        return models.permission.findByIdAndUpdate(item._id, updatePayload, {
          new: true,
          runValidators: true,
        });
      }),
    );

    const updatedPermissions = await models.permission.find({
      resource: permission.resource,
      isActive: true,
    });

    res.status(200).send({
      message: "permission updated successfully",
      data: updatedPermissions,
    });
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

export const DELETE = async (req, res) => {
  try {
    const permission = await models.permission.findById(req.params.id);

    if (!permission) {
      return res.status(404).send({ message: "permission not found" });
    }

    // Delete all permissions for this resource
    const result = await models.permission.deleteMany({
      resource: permission.resource,
    });

    res.status(200).send({
      message: `Deleted ${result.deletedCount} permissions for resource "${permission.resource}"`,
      data: {
        deletedCount: result.deletedCount,
        resource: permission.resource,
      },
    });
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};
