/**
 * Appointment Types Bulk Import API
 *
 * POST /api/dashboard/appointment-types/import
 *   Accepts a pre-parsed array of appointment type objects (the frontend
 *   parses the CSV and sends the resulting rows here).
 *
 * Request body:
 *   {
 *     types: Array<{
 *       nameEn: string;
 *       nameAr?: string;
 *       duration?: number;
 *       price?: number | null;
 *       category?: string;
 *       categoryAr?: string;
 *       itemType?: string;
 *     }>
 *   }
 *
 * Response (success):
 *   { success: true, imported: number, errors: string[] }
 *
 * Response (error):
 *   { success: false, error: string }
 */

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("AppointmentTypesImportAPI");

export const dynamic = "force-dynamic";

const MAX_IMPORT = 200;

interface ImportRow {
  nameEn: string;
  nameAr?: string;
  duration?: number;
  price?: number | null;
  category?: string;
  categoryAr?: string;
}

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 { types } = body as { types?: unknown[] };

    if (!Array.isArray(types) || types.length === 0) {
      return NextResponse.json(
        { success: false, error: "types must be a non-empty array" },
        { status: 400 },
      );
    }

    if (types.length > MAX_IMPORT) {
      return NextResponse.json(
        {
          success: false,
          error: `Cannot import more than ${MAX_IMPORT} items at once`,
        },
        { 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 starting sortOrder
    const maxSortOrder = await appointmentTypesAdapter.aggregate({
      where: { organizationId: org.id },
      _max: { sortOrder: true },
    });
    let nextSortOrder = (maxSortOrder._max.sortOrder ?? -1) + 1;

    const errors: string[] = [];
    const validRows: Array<{
      id: string;
      organizationId: string;
      nameEn: string;
      nameAr: string;
      duration: number;
      price: number | null;
      category: string | null;
      categoryAr: string | null;
      sortOrder: number;
      createdBy: string;
    }> = [];

    for (let i = 0; i < types.length; i++) {
      const row = types[i] as ImportRow;
      const rowLabel = `Row ${i + 1}`;

      if (!row.nameEn || String(row.nameEn).trim().length < 1) {
        errors.push(`${rowLabel}: nameEn is required`);
        continue;
      }

      const price =
        row.price !== undefined && row.price !== null
          ? Number(row.price)
          : null;

      if (price !== null && (isNaN(price) || price < 0)) {
        errors.push(`${rowLabel}: price must be a non-negative number`);
        continue;
      }

      validRows.push({
        id: createId(),
        organizationId: org.id,
        nameEn: String(row.nameEn).trim(),
        nameAr: row.nameAr ? String(row.nameAr).trim() : "",
        duration: row.duration ? Number(row.duration) || 30 : 30,
        price,
        category: row.category ? String(row.category) : null,
        categoryAr: row.categoryAr ? String(row.categoryAr) : null,
        sortOrder: nextSortOrder++,
        createdBy: user.userId,
      });
    }

    let imported = 0;
    if (validRows.length > 0) {
      const result = await appointmentTypesAdapter.createMany({
        data: validRows,
        skipDuplicates: true,
      });
      imported = result.count;
    }

    scopedLogger.info("Appointment types imported", {
      userId: user.userId,
      organizationId: org.id,
      requested: types.length,
      imported,
      errorCount: errors.length,
    });

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

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