/**
 * Booking Notes API
 * GET - Returns all notes for a specific booking
 * POST - Creates a new note for a booking
 *
 * Only accessible by admin and staff users
 */

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { prisma } from "@/lib/db";
import { validateCSRFToken } from "@/lib/csrf";
import { getAuthenticatedEmail } from "@/lib/utils/auth-helpers.util";
import { getEffectiveOwnerId } from "@/lib/utils/organization-data";
import { logger } from "@/lib/logger";
import { convexMutation } from "@/lib/convex-client";
import { getDataSource } from "@/lib/data-source";
import { bookingNotesAdapter } from "@/lib/adapters/bookings";
import { createId } from "@paralleldrive/cuid2";
import { bookingNoteCreateSchema } from "@/lib/validators/api-schemas";

export const dynamic = "force-dynamic";

/**
 * GET /api/bookings/[id]/notes
 * Returns all notes for a specific booking (admin/staff only)
 */
export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  try {
    const { id: bookingId } = await params;

    // Authenticate user
    const userEmail = await getAuthenticatedEmail(request, auth);

    if (!userEmail) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    // Get user and check role
    const user = await prisma.users.findUnique({
      where: { email: userEmail },
      select: { id: true, role: true, name: true },
    });

    if (!user) {
      return NextResponse.json({ error: "User not found" }, { status: 404 });
    }

    // Get effective owner ID (for org members, this returns the org owner's ID)
    const effectiveUserId = await getEffectiveOwnerId(user.id);

    // Verify the booking exists and user has access
    const booking = await prisma.bookings.findFirst({
      where: {
        id: bookingId,
        userId: effectiveUserId,
      },
      select: { id: true },
    });

    if (!booking) {
      return NextResponse.json(
        { error: "Booking not found or access denied" },
        { status: 404 },
      );
    }

    // Fetch all notes for this booking
    const notes = await prisma.booking_notes.findMany({
      where: { bookingId },
      orderBy: { createdAt: "desc" },
    });

    return NextResponse.json({
      success: true,
      notes,
      total: notes.length,
    });
  } catch (error) {
    logger.error("Failed to fetch booking notes", {
      error: error instanceof Error ? error.message : "Unknown error",
    });

    return NextResponse.json(
      { error: "Failed to fetch booking notes" },
      { status: 500 },
    );
  }
}

/**
 * POST /api/bookings/[id]/notes
 * Creates a new note for a booking (admin/staff only)
 */
export async function POST(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  try {
    const { id: bookingId } = await params;

    // Authenticate user
    const userEmail = await getAuthenticatedEmail(request, auth);

    if (!userEmail) {
      return NextResponse.json(
        { success: false, error: "Unauthorized" },
        { status: 401 },
      );
    }

    // CSRF protection (bypass in development for easier testing)
    if (process.env.NODE_ENV !== "development") {
      const isValidCSRF = validateCSRFToken(request);
      if (!isValidCSRF) {
        return NextResponse.json(
          { success: false, error: "Invalid CSRF token" },
          { status: 403 },
        );
      }
    }

    // Get user and check role
    const user = await prisma.users.findUnique({
      where: { email: userEmail },
      select: { id: true, role: true, name: true },
    });

    if (!user) {
      return NextResponse.json(
        { success: false, error: "User not found" },
        { status: 404 },
      );
    }

    // Get effective owner ID (for org members, this returns the org owner's ID)
    const effectiveUserId = await getEffectiveOwnerId(user.id);

    // Parse and validate request body
    const body = await request.json();
    const parsed = bookingNoteCreateSchema.safeParse(body);

    if (!parsed.success) {
      return NextResponse.json(
        { success: false, error: parsed.error.errors.map(e => e.message).join(", ") },
        { status: 400 },
      );
    }

    const { content } = parsed.data;

    // --- Convex data-source routing (strangler fig) ---
    if (getDataSource("bookings") === "convex") {
      const { convexMutation } = await import("@/lib/convex-client");
      const note = await convexMutation("bookings/mutations:addNote", {
        bookingId,
        authorId: user.id,
        authorName: user.name ?? "Staff",
        content,
      });
      return NextResponse.json({ note }, { status: 201 });
    }
    // --- End Convex routing ---

    // Create the note
    const now = new Date();
    const note = await bookingNotesAdapter.create({
      data: {
        id: createId(),
        bookingId,
        authorId: user.id,
        authorName: user.name || user.email,
        content,
        createdAt: now,
        updatedAt: now,
      },
    });
    return NextResponse.json({ note }, { status: 201 });
  } catch (error) {
    logger.error("Failed to create booking note", {
      error: error instanceof Error ? error.message : "Unknown error",
    });

    return NextResponse.json(
      { success: false, error: "Failed to create booking note" },
      { status: 500 },
    );
  }
}
