import { NextRequest, NextResponse } from "next/server";
import { getPublicUser, prisma } from "@repo/db";
import { getServerSession } from "../auth/[...nextauth]/auth";

// GET /api/booking - Get all bookings for the timeline
export const GET = async (req: NextRequest) => {
	try {
		const session = await getServerSession();
		if (!session?.user) {
			return NextResponse.json({ error: "Not authenticated" }, { status: 401 });
		}

		const { searchParams } = req.nextUrl;
		const filter = JSON.parse(searchParams.get("filter") || "{}");

		const bookings = await prisma.booking.findMany({
			where: filter,
			include: {
				User: true,
				Station: {
					select: {
						id: true,
						bosCallsign: true,
						bosCallsignShort: true,
					},
				},
			},
			orderBy: {
				startTime: "asc",
			},
		});

		return NextResponse.json(
			bookings.map((b) => ({
				...b,
				User: b.User ? getPublicUser(b.User) : null,
			})),
		);
	} catch (error) {
		console.error("Error fetching bookings:", error);
		return NextResponse.json({ error: "Internal server error" }, { status: 500 });
	}
};

// POST /api/booking - Create a new booking
export const POST = async (req: NextRequest) => {
	try {
		const session = await getServerSession();
		if (!session?.user) {
			return NextResponse.json({ error: "Not authenticated" }, { status: 401 });
		}

		const body = await req.json();
		const { type, stationId, startTime, endTime } = body;

		// Convert stationId to integer if provided
		const parsedStationId = stationId ? parseInt(stationId, 10) : null;

		// Validate required fields
		if (!type || !startTime || !endTime) {
			return NextResponse.json({ error: "Missing required fields" }, { status: 400 });
		}

		// Validate permissions for LST bookings
		const lstTypes = ["LST_01", "LST_02", "LST_03", "LST_04"];
		if (lstTypes.includes(type)) {
			if (!session.user.permissions.includes("DISPO")) {
				return NextResponse.json(
					{ error: "Insufficient permissions for LST booking" },
					{ status: 403 },
				);
			}
		}

		// Validate station requirement for STATION type
		if (type === "STATION" && !parsedStationId) {
			return NextResponse.json(
				{ error: "Station ID required for station booking" },
				{ status: 400 },
			);
		}

		// Validate that stationId is a valid integer when provided
		if (stationId && (isNaN(parsedStationId!) || parsedStationId! <= 0)) {
			return NextResponse.json({ error: "Invalid station ID" }, { status: 400 });
		}

		// Check for conflicts
		const conflictWhere: Record<string, unknown> = {
			type,
			OR: [
				{
					startTime: {
						lt: new Date(endTime),
					},
					endTime: {
						gt: new Date(startTime),
					},
				},
			],
		};

		if (type === "STATION" && parsedStationId) {
			conflictWhere.stationId = parsedStationId;
		}

		const existingBooking = await prisma.booking.findFirst({
			where: conflictWhere,
		});

		if (existingBooking) {
			const resourceName = type === "STATION" ? `Station` : type;
			return NextResponse.json(
				{ error: `Konflikt erkannt: ${resourceName} ist bereits für diesen Zeitraum gebucht.` },
				{ status: 409 },
			);
		}

		// Create the booking
		const booking = await prisma.booking.create({
			data: {
				userId: session.user.id,
				type,
				stationId: type === "STATION" ? parsedStationId : null,
				startTime: new Date(startTime),
				endTime: new Date(endTime),
			},
			include: {
				User: {
					select: {
						id: true,
						firstname: true,
						lastname: true,
					},
				},
				Station: {
					select: {
						id: true,
						bosCallsign: true,
						bosCallsignShort: true,
					},
				},
			},
		});

		return NextResponse.json(booking, { status: 201 });
	} catch (error) {
		console.error("Error creating booking:", error);
		return NextResponse.json({ error: "Internal server error" }, { status: 500 });
	}
};
