import { Request, Response } from 'express';
import { PrismaClient } from '@prisma/client';
import { startOfMonth, endOfMonth, subMonths, startOfHour } from 'date-fns'; 

const prisma = new PrismaClient();

// Helper to calculate percentage change
const calculateGrowth = (current: number, previous: number) => {
  if (previous === 0) return current === 0 ? 0 : 100;
  return ((current - previous) / previous) * 100;
};

export const getDashboardStats = async (req: Request, res: Response) => {
  try {
    const now = new Date();
    const currentMonthStart = startOfMonth(now);
    const lastMonthStart = startOfMonth(subMonths(now, 1));
    const lastMonthEnd = endOfMonth(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: 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
    ] = await Promise.all([
      revenuePromise,
      usersPromise,
      salesPromise,
      activeNowPromise,
      recentSalesPromise,
      graphDataPromise
    ]);

    // --- Process Data for UI ---

    // Revenue
    const currentRev = thisMonthRevenue._sum.total?.toNumber() || 0;
    const lastRev = lastMonthRevenue._sum.total?.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 => ({
        id: order.id,
        name: order.user?.fullName || "Guest",
        email: order.user?.email || "Unknown",
        amount: order.total.toNumber(), // Convert Decimal to Number
        img: order.user?.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" });
  }
};