import { NextRequest, NextResponse } from "next/server";
import { getServerSession } from "next-auth";
import { z } from "zod";
import { AuthOptions } from "@/app/api/auth/[...nextauth]/authOptions";
import { db } from "@/app/db/db";
import { portfolioCapabilities, portfolioUsers } from "@/app/db/schema/portfolio";
import { user } from "@/app/db/schema/users";
import { and, eq } from "drizzle-orm";
import { bulkInstructDeals } from "@/app/lib/bulkInstructDeals";
import { MEASURE_NAMES } from "@/app/lib/measureDocumentRequirements";

const bodySchema = z.object({
  deals: z
    .array(
      z.object({
        dealId: z.string().min(1),
        measureNames: z.array(z.string().min(1)).min(1),
      }),
    )
    .min(1, "deals must not be empty"),
  notes: z.string().optional(),
});

/**
 * POST /api/portfolio/[portfolioId]/bulk-instructed-measures
 *
 * Approver-only. Instructs the given measures on each listed deal in a single
 * atomic DB transaction. If any deal/measure fails the entire batch rolls back.
 *
 * Body: { deals: [{ dealId, measureNames }], notes? }
 * Response: 200 { ok: true, hubspotSync } | 400/401/403
 */
export async function POST(
  req: NextRequest,
  props: { params: Promise<{ portfolioId: string }> },
) {
  const session = await getServerSession(AuthOptions);
  if (!session?.user?.email) {
    return NextResponse.json({ error: "Unauthorised" }, { status: 401 });
  }

  const { portfolioId } = await props.params;

  const userRow = await db
    .select({ id: user.id })
    .from(user)
    .where(eq(user.email, session.user.email))
    .limit(1);

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

  const portfolioUserRow = await db
    .select({ role: portfolioUsers.role })
    .from(portfolioUsers)
    .where(
      and(
        eq(portfolioUsers.portfolioId, BigInt(portfolioId)),
        eq(portfolioUsers.userId, userRow[0].id),
      ),
    )
    .limit(1);

  if (!portfolioUserRow[0]?.role) {
    return NextResponse.json({ error: "No portfolio access" }, { status: 403 });
  }

  const capabilityRows = await db
    .select({ capability: portfolioCapabilities.capability })
    .from(portfolioCapabilities)
    .where(
      and(
        eq(portfolioCapabilities.portfolioId, BigInt(portfolioId)),
        eq(portfolioCapabilities.userId, userRow[0].id),
      ),
    );

  if (!capabilityRows.some((r) => r.capability === "approver")) {
    return NextResponse.json({ error: "Approver capability required" }, { status: 403 });
  }

  let body: z.infer<typeof bodySchema>;
  try {
    body = bodySchema.parse(await req.json());
  } catch {
    return NextResponse.json({ error: "Invalid body" }, { status: 400 });
  }

  for (const deal of body.deals) {
    for (const name of deal.measureNames) {
      if (!(MEASURE_NAMES as ReadonlyArray<string>).includes(name)) {
        return NextResponse.json({ error: `Unknown measure: ${name}` }, { status: 400 });
      }
    }
  }

  const result = await bulkInstructDeals({
    deals: body.deals,
    userId: userRow[0].id,
    notes: body.notes,
  });

  if (!result.ok) {
    return NextResponse.json({ ok: false, error: result.error }, { status: 400 });
  }

  return NextResponse.json({ ok: true, hubspotSync: result.hubspotSync, hubspotError: result.hubspotError });
}
