import { Request, Response } from "express";
import User from "../../models/user";
import { toImageUrl } from "../../utils/imageUrl";

const getVendors = async (req: Request, res: Response) => {
  const { page = 1, perPage = 10, search, status } = req.query;

  try {
    const filter: Record<string, any> = { role: "Vendor" };
    if (status && status !== "all") filter.status = status;
    if (search) {
      const escaped = String(search).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
      const re = new RegExp(escaped, "i");
      filter.$or = [{ name: re }, { email: re }];
    }
    const skip = (Number(page) - 1) * Number(perPage);
    const limit = Number(perPage);
    // Unfiltered by search/status - these back the summary stat cards,
    // which represent the whole vendor base regardless of what's currently
    // being searched/filtered in the list below.
    const baseFilter = { role: "Vendor" };

    const [vendors, totalItemCount, statusCounts, totalProductsAgg] = await Promise.all([
      // Aggregation pipeline so totalProducts/totalRevenue come straight
      // from the listing query (one DB round trip) instead of the admin
      // UI firing a separate products+orders request per vendor.
      User.aggregate([
        { $match: filter },
        { $sort: { createdAt: -1 } },
        { $skip: skip },
        { $limit: limit },
        {
          $lookup: {
            from: "products",
            localField: "_id",
            foreignField: "vendor",
            as: "_products",
          },
        },
        {
          $lookup: {
            from: "orders",
            localField: "_id",
            foreignField: "vendor",
            as: "_orders",
          },
        },
        {
          $addFields: {
            totalProducts: { $size: "$_products" },
            totalRevenue: { $sum: "$_orders.totalAmount" },
          },
        },
        // aggregate() bypasses the User model's toJSON transform (which
        // normally strips password and expands profileImage), so both are
        // handled explicitly here instead.
        { $project: { password: 0, _products: 0, _orders: 0 } },
      ]),
      User.countDocuments(filter),
      // Stat cards: status breakdown across every vendor.
      User.aggregate([
        { $match: baseFilter },
        { $group: { _id: "$status", count: { $sum: 1 } } },
      ]),
      // Stat cards: products listed across every vendor, summed.
      User.aggregate([
        { $match: baseFilter },
        {
          $lookup: {
            from: "products",
            localField: "_id",
            foreignField: "vendor",
            as: "_products",
          },
        },
        { $project: { count: { $size: "$_products" } } },
        { $group: { _id: null, total: { $sum: "$count" } } },
      ]),
    ]);

    vendors.forEach((vendor: any) => {
      if (vendor.profileImage) vendor.profileImage = toImageUrl(vendor.profileImage);
    });

    const stats = { totalVendors: 0, pendingVendors: 0, blockedVendors: 0 };
    statusCounts.forEach((s: any) => {
      stats.totalVendors += s.count;
      if (s._id === "Pending") stats.pendingVendors = s.count;
      if (s._id === "Blocked") stats.blockedVendors = s.count;
    });
    const totalProducts = totalProductsAgg[0]?.total || 0;

    res.status(200).json({ vendors, totalItemCount, stats: { ...stats, totalProducts } });
  } catch (e) {
    console.log(e);
    res.status(500).json({ message: e });
  }
};

export default getVendors;
