"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDashboardStats = void 0;
const client_1 = require("@prisma/client");
const date_fns_1 = require("date-fns");
const prisma = new client_1.PrismaClient();
// Helper to calculate percentage change
const calculateGrowth = (current, previous) => {
    if (previous === 0)
        return current === 0 ? 0 : 100;
    return ((current - previous) / previous) * 100;
};
const getDashboardStats = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    var _a, _b;
    try {
        const now = new Date();
        const currentMonthStart = (0, date_fns_1.startOfMonth)(now);
        const lastMonthStart = (0, date_fns_1.startOfMonth)((0, date_fns_1.subMonths)(now, 1));
        const lastMonthEnd = (0, date_fns_1.endOfMonth)((0, date_fns_1.subMonths)(now, 1));
        // --- 1. Total Revenue (Sum of Order.total) ---
        const revenuePromise = Promise.all([
            // Current Month Revenue
            prisma.order.aggregate({
                _sum: { total: true },
                where: {
                    createdAt: { gte: currentMonthStart },
                    isPaid: true, // Only count paid orders
                },
            }),
            // Last Month Revenue
            prisma.order.aggregate({
                _sum: { total: true },
                where: {
                    createdAt: { gte: lastMonthStart, lte: lastMonthEnd },
                    isPaid: true,
                },
            }),
        ]);
        // --- 2. Subscriptions (Mapped to Total Users for this schema) ---
        const usersPromise = Promise.all([
            prisma.user.count({ where: { createdAt: { gte: currentMonthStart } } }),
            prisma.user.count({ where: { createdAt: { gte: lastMonthStart, lte: lastMonthEnd } } }),
        ]);
        // --- 3. Sales (Count of Orders) ---
        const salesPromise = Promise.all([
            prisma.order.count({ where: { createdAt: { gte: currentMonthStart } } }),
            prisma.order.count({ where: { createdAt: { gte: lastMonthStart, lte: lastMonthEnd } } }),
        ]);
        // --- 4. Active Now (Users updated in last hour) ---
        // Note: For real "Active Now", you usually need Redis/Websockets. 
        // Here we use users who performed an action (updatedAt) in the last hour as a proxy.
        const activeNowPromise = prisma.user.count({
            where: { updatedAt: { gte: (0, date_fns_1.startOfHour)(now) } },
        });
        // --- 5. Recent Sales List ---
        const recentSalesPromise = prisma.order.findMany({
            take: 5,
            orderBy: { createdAt: 'desc' },
            include: {
                user: {
                    select: {
                        fullName: true,
                        email: true,
                        image: true,
                    },
                },
            },
        });
        // --- 6. Monthly Graph Data (Last 12 Months Revenue) ---
        // This is a raw query example for performance, or you can use groupBy if using simple logic
        const graphDataPromise = prisma.$queryRaw `
      SELECT TO_CHAR("createdAt", 'Mon') as name, SUM(total) as total
      FROM "Order"
      WHERE "isPaid" = true
      GROUP BY TO_CHAR("createdAt", 'Mon'), DATE_TRUNC('month', "createdAt")
      ORDER BY DATE_TRUNC('month', "createdAt") ASC
      LIMIT 12;
    `;
        // Execute all queries in parallel
        const [[thisMonthRevenue, lastMonthRevenue], [thisMonthUsers, lastMonthUsers], [thisMonthSales, lastMonthSales], activeNow, recentSales, graphData] = yield Promise.all([
            revenuePromise,
            usersPromise,
            salesPromise,
            activeNowPromise,
            recentSalesPromise,
            graphDataPromise
        ]);
        // --- Process Data for UI ---
        // Revenue
        const currentRev = ((_a = thisMonthRevenue._sum.total) === null || _a === void 0 ? void 0 : _a.toNumber()) || 0;
        const lastRev = ((_b = lastMonthRevenue._sum.total) === null || _b === void 0 ? void 0 : _b.toNumber()) || 0;
        // Response Object
        const stats = {
            revenue: {
                value: currentRev,
                change: calculateGrowth(currentRev, lastRev),
            },
            subscriptions: {
                value: thisMonthUsers,
                change: calculateGrowth(thisMonthUsers, lastMonthUsers),
            },
            sales: {
                value: thisMonthSales,
                change: calculateGrowth(thisMonthSales, lastMonthSales),
            },
            activeNow: {
                value: activeNow,
                since: "last hour"
            },
            recentSales: recentSales.map(order => {
                var _a, _b, _c;
                return ({
                    id: order.id,
                    name: ((_a = order.user) === null || _a === void 0 ? void 0 : _a.fullName) || "Guest",
                    email: ((_b = order.user) === null || _b === void 0 ? void 0 : _b.email) || "Unknown",
                    amount: order.total.toNumber(), // Convert Decimal to Number
                    img: ((_c = order.user) === null || _c === void 0 ? void 0 : _c.image) || "",
                });
            }),
            graphData: graphData // [{name: 'Jan', total: 5000}, ...]
        };
        res.json(stats);
    }
    catch (error) {
        console.error("Dashboard Stats Error:", error);
        res.status(500).json({ error: "Failed to fetch dashboard statistics" });
    }
});
exports.getDashboardStats = getDashboardStats;
