/**
 * POST /api/staff/dashboard/demos/update
 *
 * Update a demo booking record.
 *
 * This endpoint allows staff users to:
 * - Change booking status (pending -> confirmed/cancelled)
 * - Add video meeting links (Zoom, Google Meet, Teams, etc.)
 * - Add internal notes (private, customer never sees these)
 * - Track when customer was contacted and by whom
 *
 * @route POST /api/staff/dashboard/demos/update
 * @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 demo bookings utilities
import {
  mapUpdateRequestToDatabase,
  validateUpdateRequest,
  createUnauthorizedResponse,
  createBadRequestResponse,
  createSuccessResponse,
  logOperation,
  logSuccess,
  AUDIT_CONFIG,
  type DemoBookingUpdateRequest,
} from "@/lib/staff-dashboard/demo-bookings";

/**
 * POST handler - Update demo booking
 */
export async function POST(request: NextRequest) {
  // Step 1: Authenticate staff user
  const user = await requireStaffAuth();
  if (!user) {
    return createUnauthorizedResponse();
  }

  // Step 2: Parse and validate request body
  const body = await request.json();
  const validation = validateUpdateRequest(body);

  if (!validation.valid) {
    return createBadRequestResponse(validation.errors);
  }

  const updateRequest = body as DemoBookingUpdateRequest;
  const { bookingId, ...updates } = updateRequest;

  logOperation("Updating demo booking", {
    bookingId,
    updates,
    staffId: user.id,
  });

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

      // Look up the demo booking - try Convex ID first, fall back to legacy Prisma ID
      let convexBooking: Record<string, unknown> | null = null;
      let convexDocId: string | null = null;

      try {
        convexBooking = await convexQuery(
          "bookings/queries:getDemoBookingById",
          { id: bookingId },
        );
        if (convexBooking) convexDocId = bookingId;
      } catch {
        // Not a valid Convex ID - try as a legacy Prisma ID
      }

      if (!convexBooking) {
        convexBooking = await convexQuery(
          "bookings/queries:getDemoBookingByLegacyId",
          { legacyId: bookingId },
        );
        if (convexBooking)
          convexDocId = (convexBooking as Record<string, unknown>)
            ._id as string;
      }

      if (convexBooking && convexDocId) {
        // Build Convex update args
        const convexUpdateArgs: Record<string, unknown> = {
          id: convexDocId as `${string}`,
          status: updates.status,
        };

        if (updates.meetingLink !== undefined) {
          convexUpdateArgs.meetingLink = updates.meetingLink;
        }
        if (updates.internalNotes !== undefined) {
          convexUpdateArgs.internalNotes = updates.internalNotes;
        }

        // Auto-set contacted fields when confirming or adding meeting link
        if (updates.status === "confirmed" || updates.meetingLink) {
          convexUpdateArgs.contactedAt = Date.now();
          convexUpdateArgs.contactedBy = user.id;
        }

        await convexMutation(
          "bookings/mutations:updateDemoBookingStatus",
          convexUpdateArgs,
        );

        // Log staff action for audit trail
        const auditChanges = {
          status: updates.status,
          meetingLink: updates.meetingLink,
          internalNotes: updates.internalNotes,
        };

        // Write audit log
        try {
          await prisma.audit_logs.create({
            data: {
              userId: user.id,
              type: AUDIT_CONFIG.TYPE,
              action: AUDIT_CONFIG.ACTION,
              success: true,
              ipAddress: request.headers.get("x-forwarded-for") || "0.0.0.0",
              metadata: JSON.stringify({
                bookingId,
                convexDocId,
                changes: auditChanges,
                staffRole: user.role,
                staffName: user.name,
              }),
            },
          });
        } catch (auditErr) {
          logger.warn("Audit log write failed (non-critical)", { error: auditErr });
        }

        logSuccess(`Updated booking ${bookingId} via Convex`, auditChanges);

        return createSuccessResponse({
          success: true,
          booking: { ...convexBooking, ...auditChanges },
        });
      } else {
        logger.info("Convex booking not found, falling through to Prisma", {
          bookingId,
        });
      }
    } catch (convexError) {
      logger.warn(
        "Convex demo booking update failed, falling through to Prisma",
        {
          bookingId,
          error:
            convexError instanceof Error
              ? convexError.message
              : String(convexError),
        },
      );
      // Fall through to Prisma path
    }
  }

  // -- Prisma path --
  try {
    // Transform update data (camelCase -> snake_case)
    const updateData = mapUpdateRequestToDatabase(updates, user.id);

    const updatedBooking = await prisma.demo_bookings.update({
      where: { id: bookingId },
      data: updateData,
    });

    logSuccess(`Updated booking ${bookingId}`, updateData);

    return createSuccessResponse({
      success: true,
      booking: updatedBooking,
    });
  } catch (error) {
    logger.error("Failed to update demo booking", { error, bookingId });
    return NextResponse.json(
      { error: "Failed to update booking" },
      { status: 500 },
    );
  }
}
