const { Transaction, User } = require("../../models");
const { Op } = require("sequelize");
const { NotFoundError } = require("../../utils/errors");

class adminTransactionsService {
  async getTransactions(query) {
    const { type, status, userId, source, q, page = 1, limit = 20 } = query;
    const offset = (Number(page) - 1) * Number(limit);

    const where = {};
    if (type) where.kind = type;            // deposit/withdrawal/order/adjustment
    if (status) where.status = status;      // pending/completed/failed
    if (userId) where.userId = userId;
    if (source) where.source = source;      // funding/wallet

    if (q) {
      where[Op.or] = [
        { transactionId: { [Op.like]: `%${q}%` } },
        { kind: { [Op.like]: `%${q}%` } },
        { source: { [Op.like]: `%${q}%` } },
      ];
    }

    const { rows, count } = await Transaction.findAndCountAll({
      where,
      include: [{ model: User, as: "user" }],
      order: [["created_at", "DESC"]],
      limit: Number(limit),
      offset,
    });

    const stats = {
      total: count,
      completed: rows.filter(r => r.status === "completed").length,
      pending: rows.filter(r => r.status === "pending").length,
      failed: rows.filter(r => r.status === "failed").length,
    };

    return {
      stats,
      count,
      page: Number(page),
      limit: Number(limit),
      transactions: rows.map(t => ({
        id: t.id,
        tx: t.transactionId,
        userId: t.userId,
        user: t.user?.name ?? null,
        source: t.source,
        kind: t.kind,
        amount: Number(t.amount ?? 0),
        status: t.status,
        createdAt: t.created_at,
        meta: t.meta ?? {},
      })),
    };
  }

  async getTransactionById(txId) {
    const tx = await Transaction.findOne({
      where: { [Op.or]: [{ id: txId }, { transactionId: txId }] },
      include: [{ model: User, as: "user" }],
    });

    if (!tx) throw new NotFoundError("Transaction not found");

    return { transaction: tx };
  }
}

module.exports = new adminTransactionsService();
