import models from "$models/index.js";
import { accessGrantHelpers, identityHelpers } from "$helpers/index.js";
import { buildTransactionTableQuery } from "./transaction.query.js";

const isOwner = (itemUser, requestUser) => {
  const itemUserId = itemUser?._id || itemUser;
  return itemUserId?.toString() === requestUser?._id?.toString();
};

const populateTransactionRequest = (query) =>
  query.populate({
    path: "request",
    populate: [
      {
        path: "investor",
        select: identityHelpers.USER_IDENTITY_PROJECTION,
      },
      {
        path: "paymentCard",
      },
      {
        path: "paymentSlip",
      },
    ],
  });

const resolveTransactionOwner = (transaction) =>
  transaction?.request?.investor || null;

export const ALL = async (req, res) => {
  try {
    const {
      pageSize,
      currentPage,
      skip,
      filterQuery,
      sort,
      sortField,
      sortDirection,
    } = buildTransactionTableQuery(req.query);
    const query = { ...filterQuery };
    const canAccessAllTransactions = accessGrantHelpers.hasAllResourceAccess(
      req.user,
      "transactions",
    );

    if (!canAccessAllTransactions) {
      const ownRequestIds = await models.request
        .find({ investor: req.user._id })
        .select("_id")
        .lean();
      query.request = { $in: ownRequestIds.map((item) => item._id) };
    }

    const transactions = await populateTransactionRequest(
      models.transaction.find(query).limit(pageSize).skip(skip).sort(sort),
    );

    const totalData = await models.transaction.countDocuments(query);
    const totalPage = pageSize ? Math.ceil(totalData / pageSize) : 0;

    res.status(200).send({
      transactions,
      totalData,
      currentPage,
      totalPage,
      sortField,
      sortDirection,
    });
  } catch (error) {
    const status = error.status || 500;
    const message = error.message || "خطا در دریافت transaction";
    return res.status(status).send({ message });
  }
};

export const SINGLE = async (req, res) => {
  try {
    const { id } = req.params;
    const data = await populateTransactionRequest(
      models.transaction.findById(id),
    );

    if (!data) {
      return res.status(404).send({ message: "یافت نشد" });
    }

    if (
      !accessGrantHelpers.hasAllResourceAccess(req.user, "transactions") &&
      !isOwner(resolveTransactionOwner(data), req.user)
    ) {
      return res.status(403).send({ message: "دسترسی محدود" });
    }

    res.status(200).send(data);
  } catch (error) {
    const status = error.status || 500;
    const message = error.message || "خطا در دریافت transaction";
    return res.status(status).send({ message });
  }
};

export const CREATE = async (req, res) => {
  try {
    const data = req.body;

    const newItem = await models.transaction.create(data);
    const populated = await populateTransactionRequest(
      models.transaction.findById(newItem._id),
    );

    res.status(201).send({
      message: "با موفقیت ایجاد شد",
      data: populated,
    });
  } catch (error) {
    const status = error.status || 500;
    const message = error.message || "خطا در ایجاد transaction";
    return res.status(status).send({ message });
  }
};

export const UPDATE = async (req, res) => {
  try {
    const { id } = req.params;
    const updateData = req.body;

    delete updateData._id;
    delete updateData.createdAt;
    delete updateData.updatedAt;

    const existingItem = await populateTransactionRequest(
      models.transaction.findById(id),
    );
    if (!existingItem) {
      return res.status(404).send({ message: "یافت نشد" });
    }

    if (
      !accessGrantHelpers.hasAllResourceAccess(req.user, "transactions") &&
      !isOwner(resolveTransactionOwner(existingItem), req.user)
    ) {
      return res.status(403).send({ message: "دسترسی محدود" });
    }

    const updated = await populateTransactionRequest(
      models.transaction.findByIdAndUpdate(
        id,
        { $set: updateData },
        { new: true },
      ),
    );

    res.status(200).send({
      message: "با موفقیت ویرایش شد",
      data: updated,
    });
  } catch (error) {
    const status = error.status || 500;
    const message = error.message || "خطا در ویرایش transaction";
    return res.status(status).send({ message });
  }
};

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

    if (!existingItem) {
      return res.status(404).send({ message: "یافت نشد" });
    }

    if (
      !accessGrantHelpers.hasAllResourceAccess(req.user, "transactions") &&
      !isOwner(resolveTransactionOwner(existingItem), req.user)
    ) {
      return res.status(403).send({ message: "دسترسی محدود" });
    }

    await models.transaction.findByIdAndDelete(id);

    res.status(200).send({
      message: "با موفقیت حذف شد",
    });
  } catch (error) {
    const status = error.status || 500;
    const message = error.message || "خطا در حذف transaction";
    return res.status(status).send({ message });
  }
};
