import { z } from "zod";
import prisma from "~/server/utils/prisma";

// Query parameter validation schema
const querySchema = z.object({
  period: z.enum(["hour", "day", "week", "month"]).default("day"),
  metric: z.enum(["throughput", "error_rate", "response_time"]).default("throughput"),
});

export default defineEventHandler(async (event) => {
  try {
    // Parse and validate query parameters
    const query = getQuery(event);
    const { period, metric } = querySchema.parse(query);

    // Set time range based on period
    const now = new Date();
    let startDate;
    let intervalMinutes;
    let numPoints;

    switch (period) {
      case "hour":
        startDate = new Date(now.getTime() - 60 * 60 * 1000); // 1 hour ago
        intervalMinutes = 1; // 1-minute intervals
        numPoints = 60;
        break;
      case "day":
        startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000); // 24 hours ago
        intervalMinutes = 60; // 1-hour intervals
        numPoints = 24;
        break;
      case "week":
        startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); // 7 days ago
        intervalMinutes = 24 * 60; // 1-day intervals
        numPoints = 7;
        break;
      case "month":
        startDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); // 30 days ago
        intervalMinutes = 24 * 60; // 1-day intervals
        numPoints = 30;
        break;
      default:
        startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000);
        intervalMinutes = 60;
        numPoints = 24;
    }

    const dataPoints = [];

    // Generate time buckets
    for (let i = 0; i < numPoints; i++) {
      const bucketStart = new Date(startDate.getTime() + i * intervalMinutes * 60 * 1000);
      const bucketEnd = new Date(bucketStart.getTime() + intervalMinutes * 60 * 1000);

      let value = 0;

      switch (metric) {
        case "throughput": {
          // Count completed jobs in this time bucket
          const count = await prisma.notification_queue.count({
            where: {
              status: "completed",
              updated_at: {
                gte: bucketStart,
                lt: bucketEnd,
              },
            },
          });
          value = count;
          break;
        }

        case "error_rate": {
          // Calculate error rate in this time bucket
          const [totalJobs, failedJobs] = await Promise.all([
            prisma.notification_queue.count({
              where: {
                OR: [{ status: "completed" }, { status: "failed" }],
                updated_at: {
                  gte: bucketStart,
                  lt: bucketEnd,
                },
              },
            }),
            prisma.notification_queue.count({
              where: {
                status: "failed",
                updated_at: {
                  gte: bucketStart,
                  lt: bucketEnd,
                },
              },
            }),
          ]);
          value = totalJobs > 0 ? Math.round((failedJobs / totalJobs) * 100) : 0;
          break;
        }

        case "response_time": {
          // Calculate average response time in this time bucket
          const jobs = await prisma.notification_queue.findMany({
            where: {
              status: "completed",
              updated_at: {
                gte: bucketStart,
                lt: bucketEnd,
              },
              last_attempt_at: { not: null },
            },
            select: {
              created_at: true,
              last_attempt_at: true,
            },
            take: 50, // Sample size
          });

          if (jobs.length > 0) {
            const responseTimes = jobs.map(job => {
              const diff = new Date(job.last_attempt_at).getTime() - new Date(job.created_at).getTime();
              return Math.abs(diff);
            });
            value = Math.round(responseTimes.reduce((sum, time) => sum + time, 0) / responseTimes.length);
          } else {
            value = 0;
          }
          break;
        }
      }

      dataPoints.push({
        timestamp: bucketStart.toISOString(),
        value,
      });
    }

    // Calculate summary statistics
    const values = dataPoints.map(p => p.value);
    const min = Math.min(...values);
    const max = Math.max(...values);
    const avg = Math.round(values.reduce((sum, val) => sum + val, 0) / values.length);

    // Calculate trend (compare first half vs second half)
    const midpoint = Math.floor(values.length / 2);
    const firstHalfAvg = values.slice(0, midpoint).reduce((sum, val) => sum + val, 0) / midpoint;
    const secondHalfAvg = values.slice(midpoint).reduce((sum, val) => sum + val, 0) / (values.length - midpoint);
    const trend = secondHalfAvg > firstHalfAvg * 1.1 ? "increasing" 
                : secondHalfAvg < firstHalfAvg * 0.9 ? "decreasing" 
                : "stable";

    return {
      success: true,
      data: {
        metric,
        period,
        dataPoints,
        summary: {
          min,
          max,
          avg,
          trend,
        },
      },
    };
  } catch (error) {
    console.error("Error fetching queue history:", error);

    if (error.name === "ZodError") {
      throw createError({
        statusCode: 400,
        statusMessage: "Invalid query parameters",
        data: {
          errors: error.errors,
        },
      });
    }

    throw createError({
      statusCode: 500,
      statusMessage: "Failed to fetch queue history",
      data: {
        error: error.message,
      },
    });
  } finally {
  }
});
