/**
 * Appointment Types API — collection endpoints
 *
 * GET  /api/dashboard/appointment-types
 *   Returns all active appointment types for the authenticated user's organisation,
 *   ordered by sortOrder ascending.
 *
 * POST /api/dashboard/appointment-types
 *   Creates a new appointment type belonging to the user's organisation.
 */

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { prisma } from "@/lib/db";
import { appointmentTypesAdapter } from "@/lib/adapters/appointment-types";
import { getAuthenticatedUser } from "@/lib/utils/auth-helpers.util";
import { logger } from "@/lib/logger";
import { withCSRF } from "@/lib/csrf";
import { withRateLimit, rateLimiters } from "@/lib/rate-limiter";
import { createId } from "@paralleldrive/cuid2";

const scopedLogger = logger.scope("AppointmentTypesAPI");

export const dynamic = "force-dynamic";

// ---------------------------------------------------------------------------
// GET
// ---------------------------------------------------------------------------

export async function GET(request: NextRequest) {
  try {
    const user = await getAuthenticatedUser(request, auth);
    if (!user) {
      return NextResponse.json(
        { success: false, error: "Unauthorized" },
        { status: 401 },
      );
    }

    const org = await prisma.organizations.findFirst({
      where: { ownerId: user.userId },
      select: { id: true },
    });

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

    const types = await appointmentTypesAdapter.findMany({
      where: { organizationId: org.id, isActive: true },
      orderBy: { sortOrder: "asc" },
    });

    scopedLogger.info("Appointment types retrieved", {
      userId: user.userId,
      organizationId: org.id,
      count: types.length,
    });

    return NextResponse.json({ success: true, types });
  } catch (error) {
    scopedLogger.error("Failed to retrieve appointment types", error);
    return NextResponse.json(
      { success: false, error: "Internal server error" },
      { status: 500 },
    );
  }
}

// ---------------------------------------------------------------------------
// POST
// ---------------------------------------------------------------------------

async function postHandler(request: NextRequest): Promise<NextResponse> {
  try {
    const user = await getAuthenticatedUser(request, auth);
    if (!user) {
      return NextResponse.json(
        { success: false, error: "Unauthorized" },
        { status: 401 },
      );
    }

    let body: unknown;
    try {
      body = await request.json();
    } catch {
      return NextResponse.json(
        { success: false, error: "Invalid JSON body" },
        { status: 400 },
      );
    }

    const {
      nameEn,
      nameAr = "",
      duration = 30,
      price,
      category,
      categoryAr,
    } = body as Record<string, unknown>;

    // Validate
    if (!nameEn || String(nameEn).trim().length < 1) {
      return NextResponse.json(
        { success: false, error: "nameEn is required" },
        { status: 400 },
      );
    }

    if (price !== undefined && price !== null) {
      const priceNum = Number(price);
      if (isNaN(priceNum) || priceNum < 0) {
        return NextResponse.json(
          { success: false, error: "price must be a non-negative number" },
          { status: 400 },
        );
      }
    }

    const org = await prisma.organizations.findFirst({
      where: { ownerId: user.userId },
      select: { id: true },
    });

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

    // Determine next sortOrder
    const maxSortOrder = await appointmentTypesAdapter.aggregate({
      where: { organizationId: org.id },
      _max: { sortOrder: true },
    });
    const nextSortOrder = (maxSortOrder._max.sortOrder ?? -1) + 1;

    const type = await appointmentTypesAdapter.create({
      data: {
        id: createId(),
        organizationId: org.id,
        nameEn: String(nameEn).trim(),
        nameAr: String(nameAr).trim(),
        duration: Number(duration) || 30,
        price: price !== undefined && price !== null ? Number(price) : null,
        category: category ? String(category) : null,
        categoryAr: categoryAr ? String(categoryAr) : null,
        sortOrder: nextSortOrder,
        createdBy: user.userId,
      },
    });

    scopedLogger.info("Appointment type created", {
      userId: user.userId,
      typeId: type.id,
    });

    return NextResponse.json({ success: true, type }, { status: 201 });
  } catch (error) {
    scopedLogger.error("Failed to create appointment type", error);
    return NextResponse.json(
      { success: false, error: "Internal server error" },
      { status: 500 },
    );
  }
}

export const POST = withRateLimit(
  withCSRF(postHandler),
  rateLimiters.authGeneral,
);
