import { NextRequest, NextResponse } from "next/server";
import { Prisma } from "@/generated/prisma/client";
import { prisma } from "@/lib/db";
import {
  requireApiAuthWithOrg,
  requireApiAuthWithPermission,
  handleApiError,
} from "@/lib/api-auth";

type RouteContext = { params: Promise<{ id: string }> };

async function verifyTemplateOwnership(templateId: string, orgId: string) {
  const template = await prisma.formTemplate.findUnique({
    where: { id: templateId },
    select: { id: true, organizationId: true },
  });
  if (!template || template.organizationId !== orgId) return null;
  return template;
}

export async function GET(_request: NextRequest, ctx: RouteContext) {
  try {
    const session = await requireApiAuthWithOrg();
    const { id } = await ctx.params;

    if (!(await verifyTemplateOwnership(id, session.user.orgId!))) {
      return NextResponse.json(
        { error: "Template not found" },
        { status: 404 }
      );
    }

    const fields = await prisma.formField.findMany({
      where: { formTemplateId: id },
      orderBy: { sortOrder: "asc" },
    });

    return NextResponse.json({ fields });
  } catch (error) {
    return handleApiError(error);
  }
}

export async function POST(request: NextRequest, ctx: RouteContext) {
  try {
    const session = await requireApiAuthWithPermission("settings.edit");
    const { id } = await ctx.params;

    if (!(await verifyTemplateOwnership(id, session.user.orgId!))) {
      return NextResponse.json(
        { error: "Template not found" },
        { status: 404 }
      );
    }

    const body = await request.json();
    const { key, label, type, section, options, required, placeholder, helpText, validation, visibleOnCard, visibleOnSurvey } = body as {
      key?: string;
      label?: string;
      type?: string;
      section?: string;
      options?: unknown;
      required?: boolean;
      placeholder?: string;
      helpText?: string;
      validation?: unknown;
      visibleOnCard?: boolean;
      visibleOnSurvey?: boolean;
    };

    if (!key?.trim() || !label?.trim() || !type?.trim()) {
      return NextResponse.json(
        { error: "key, label, and type are required" },
        { status: 400 }
      );
    }

    const maxSort = await prisma.formField.aggregate({
      where: { formTemplateId: id },
      _max: { sortOrder: true },
    });
    const nextSort = (maxSort._max.sortOrder ?? -1) + 1;

    const field = await prisma.formField.create({
      data: {
        formTemplateId: id,
        key: key.trim(),
        label: label.trim(),
        type: type.trim(),
        section: section?.trim() || "personal",
        required: required ?? false,
        sortOrder: nextSort,
        options: options ?? Prisma.JsonNull,
        placeholder: placeholder?.trim() || null,
        helpText: helpText?.trim() || null,
        validation: validation ?? Prisma.JsonNull,
        visibleOnCard: visibleOnCard ?? true,
        visibleOnSurvey: visibleOnSurvey ?? true,
      },
    });

    return NextResponse.json(field, { status: 201 });
  } catch (error) {
    return handleApiError(error);
  }
}

export async function PUT(request: NextRequest, ctx: RouteContext) {
  try {
    const session = await requireApiAuthWithPermission("settings.edit");
    const { id } = await ctx.params;

    if (!(await verifyTemplateOwnership(id, session.user.orgId!))) {
      return NextResponse.json(
        { error: "Template not found" },
        { status: 404 }
      );
    }

    const body = await request.json();
    const reorders = body as Array<{ id: string; sortOrder: number }>;

    if (!Array.isArray(reorders) || reorders.length === 0) {
      return NextResponse.json(
        { error: "Expected array of { id, sortOrder }" },
        { status: 400 }
      );
    }

    await prisma.$transaction(
      reorders.map((item) =>
        prisma.formField.update({
          where: { id: item.id },
          data: { sortOrder: item.sortOrder },
        })
      )
    );

    const fields = await prisma.formField.findMany({
      where: { formTemplateId: id },
      orderBy: { sortOrder: "asc" },
    });

    return NextResponse.json({ fields });
  } catch (error) {
    return handleApiError(error);
  }
}
