/**
 * GET /api/staff/dashboard/demos
 *
 * Fetch demo bookings with optional filtering.
 *
 * This endpoint allows staff users to:
 * - View all demo appointment requests
 * - Filter by status (pending, confirmed, cancelled)
 * - Search by customer name, email, or phone
 * - Filter by date range (today, this week, this month)
 *
 * @route GET /api/staff/dashboard/demos
 * @access Staff only (requires authentication)
 */

import { NextRequest, NextResponse } from "next/server";
import { requireStaffAuth } from "@/lib/staff-auth";
import { prisma } from "@/lib/db";
import { getDataSource } from "@/lib/data-source";
import { logger } from "@/lib/logger";
import type {
  DemoBookingFilters,
  DemoBooking,
} from "@/lib/staff-dashboard/demo-bookings";
import {
  validateFilters,
  createUnauthorizedResponse,
  createBadRequestResponse,
  createSuccessResponse,
  logOperation,
  logSuccess,
} from "@/lib/staff-dashboard/demo-bookings";

/**
 * GET handler - Fetch and filter demo bookings
 */
export async function GET(request: NextRequest) {
  // Step 1: Authenticate staff user
  const user = await requireStaffAuth();
  if (!user) {
    return createUnauthorizedResponse();
  }

  // Step 2: Parse and validate query parameters
  const { searchParams } = new URL(request.url);
  const filters: DemoBookingFilters = {
    status: (searchParams.get("status") as DemoBookingFilters["status"]) || "all",
    search: searchParams.get("search") || undefined,
    dateRange: (searchParams.get("dateRange") as DemoBookingFilters["dateRange"]) || "all",
  };

  const validation = validateFilters(filters);
  if (!validation.valid) {
    return createBadRequestResponse(validation.errors);
  }

  logOperation("Fetching demo bookings", { filters, userId: user.id });

  // -- Convex data-source branch --
  if (getDataSource("bookings") === "convex") {
    try {
      const { convexQuery } = await import("@/lib/convex-client");

      // Build Convex query args from filters
      const convexArgs: Record<string, unknown> = {};
      if (filters.status && filters.status !== "all") {
        convexArgs.status = filters.status;
      }
      if (filters.dateRange && filters.dateRange !== "all") {
        const now = new Date();
        let startDate: Date;
        switch (filters.dateRange) {
          case "today":
            startDate = new Date(
              now.getFullYear(),
              now.getMonth(),
              now.getDate(),
            );
            break;
          case "week":
            startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
            break;
          case "month":
            startDate = new Date(
              now.getFullYear(),
              now.getMonth() - 1,
              now.getDate(),
            );
            break;
          default:
            startDate = new Date(0);
        }
        convexArgs.startDate = startDate.getTime();
      }

      const convexBookings = await convexQuery(
        "bookings/queries:getDemoBookings",
        convexArgs,
      );

      if (convexBookings) {
        // Map Convex results to the DemoBooking frontend format
        let bookings: DemoBooking[] = (
          convexBookings as Record<string, unknown>[]
        ).map((doc) => ({
          id: (doc._id as string) || (doc.prismaId as string) || "",
          fullName: (doc.fullName as string) || "",
          email: (doc.email as string) || "",
          telephone: (doc.telephone as string) || "",
          appointmentDate:
            typeof doc.appointmentDate === "number"
              ? new Date(doc.appointmentDate as number).toISOString()
              : String(doc.appointmentDate || ""),
          appointmentTime: (doc.appointmentTime as string) || "",
          duration: (doc.duration as string) || "",
          specialRequirements: (doc.specialRequirements as string) ?? null,
          language: (doc.language as "ar" | "en") || "en",
          status:
            (doc.status as "pending" | "confirmed" | "cancelled") || "pending",
          webhookStatus:
            (doc.webhookStatus as "pending" | "sent" | "failed") || "pending",
          webhookRetryCount: (doc.webhookRetryCount as number) ?? 0,
          webhookLastAttempt:
            typeof doc.webhookLastAttempt === "number"
              ? new Date(doc.webhookLastAttempt as number).toISOString()
              : null,
          webhookResponse: (doc.webhookResponse as string) ?? null,
          meetingLink: (doc.meetingLink as string) ?? null,
          internalNotes: (doc.internalNotes as string) ?? null,
          contactedAt:
            typeof doc.contactedAt === "number"
              ? new Date(doc.contactedAt as number).toISOString()
              : null,
          contactedBy: (doc.contactedBy as string) ?? null,
          createdAt:
            typeof doc.createdAt === "number"
              ? new Date(doc.createdAt as number).toISOString()
              : String(doc.createdAt || ""),
          updatedAt:
            typeof doc.updatedAt === "number"
              ? new Date(doc.updatedAt as number).toISOString()
              : String(doc.updatedAt || ""),
        }));

        // Apply search filter client-side (Convex doesn't support ILIKE)
        if (filters.search) {
          const searchLower = filters.search.toLowerCase();
          bookings = bookings.filter(
            (b) =>
              b.fullName.toLowerCase().includes(searchLower) ||
              b.email.toLowerCase().includes(searchLower) ||
              b.telephone.includes(filters.search!),
          );
        }

        logSuccess(`Fetched ${bookings.length} demo bookings via Convex`);
        return createSuccessResponse({ bookings, total: bookings.length });
      }
    } catch (convexError) {
      logger.warn(
        "Convex demo bookings fetch failed, falling through to Prisma",
        {
          error:
            convexError instanceof Error
              ? convexError.message
              : String(convexError),
        },
      );
      // Fall through to Prisma path
    }
  }

  // -- Prisma path --
  try {
    const where: Record<string, unknown> = {};

    if (filters.status && filters.status !== "all") {
      where.status = filters.status;
    }

    if (filters.dateRange && filters.dateRange !== "all") {
      const now = new Date();
      let startDate: Date;
      switch (filters.dateRange) {
        case "today":
          startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
          break;
        case "week":
          startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
          break;
        case "month":
          startDate = new Date(now.getFullYear(), now.getMonth() - 1, now.getDate());
          break;
        default:
          startDate = new Date(0);
      }
      where.createdAt = { gte: startDate };
    }

    const bookings = await prisma.demo_bookings.findMany({
      where,
      orderBy: { createdAt: "desc" },
    });

    let mapped = bookings.map((b) => ({
      id: b.id,
      fullName: b.fullName || "",
      email: b.email || "",
      telephone: b.telephone || "",
      appointmentDate: b.appointmentDate ? new Date(b.appointmentDate).toISOString() : "",
      appointmentTime: b.appointmentTime || "",
      duration: b.duration || "",
      specialRequirements: b.specialRequirements ?? null,
      language: (b.language as "ar" | "en") || "en",
      status: (b.status as "pending" | "confirmed" | "cancelled") || "pending",
      webhookStatus: (b.webhookStatus as "pending" | "sent" | "failed") || "pending",
      webhookRetryCount: b.webhookRetryCount ?? 0,
      webhookLastAttempt: b.webhookLastAttempt ? new Date(b.webhookLastAttempt).toISOString() : null,
      webhookResponse: b.webhookResponse ?? null,
      meetingLink: b.meetingLink ?? null,
      internalNotes: b.internalNotes ?? null,
      contactedAt: b.contactedAt ? new Date(b.contactedAt).toISOString() : null,
      contactedBy: b.contactedBy ?? null,
      createdAt: b.createdAt ? new Date(b.createdAt).toISOString() : "",
      updatedAt: b.updatedAt ? new Date(b.updatedAt).toISOString() : "",
    }));

    // Apply search filter
    if (filters.search) {
      const searchLower = filters.search.toLowerCase();
      mapped = mapped.filter(
        (b) =>
          b.fullName.toLowerCase().includes(searchLower) ||
          b.email.toLowerCase().includes(searchLower) ||
          b.telephone.includes(filters.search!),
      );
    }

    logSuccess(`Fetched ${mapped.length} demo bookings`);
    return createSuccessResponse({ bookings: mapped, total: mapped.length });
  } catch (error) {
    logger.error("Failed to fetch demo bookings", { error });
    return NextResponse.json(
      { error: "Failed to fetch demo bookings" },
      { status: 500 },
    );
  }
}
