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

const CAPABILITY_OPTIONS = ["approver", "contractor"] as const;

async function getRequestingUserRole(portfolioId: bigint, email: string) {
  const rows = await db
    .select({ role: portfolioUsers.role })
    .from(portfolioUsers)
    .innerJoin(user, eq(user.id, portfolioUsers.userId))
    .where(
      and(
        eq(portfolioUsers.portfolioId, portfolioId),
        eq(user.email, email),
      ),
    )
    .limit(1);
  return rows[0]?.role ?? null;
}

// GET — list all capability assignments for this portfolio
export async function GET(
  _req: NextRequest,
  props: { params: Promise<{ portfolioId: string }> },
) {
  const { portfolioId } = await props.params;

  try {
    const rows = await db
      .select({
        id: portfolioCapabilities.id,
        userId: portfolioCapabilities.userId,
        capability: portfolioCapabilities.capability,
        name: user.firstName,
        email: user.email,
      })
      .from(portfolioCapabilities)
      .leftJoin(user, eq(user.id, portfolioCapabilities.userId))
      .where(eq(portfolioCapabilities.portfolioId, BigInt(portfolioId)));

    return NextResponse.json(
      rows.map((r) => ({
        id: r.id?.toString(),
        userId: r.userId?.toString(),
        capability: r.capability,
        name: r.name ?? null,
        email: r.email ?? "",
      })),
    );
  } catch (err) {
    console.error("GET /capabilities error:", err);
    return NextResponse.json(
      { error: "Failed to fetch capabilities" },
      { status: 500 },
    );
  }
}

// POST — assign a capability to a user
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 pId = BigInt(portfolioId);

  const requestingRole = await getRequestingUserRole(pId, session.user.email);
  if (requestingRole !== "admin" && requestingRole !== "creator") {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  const bodySchema = z.object({
    userId: z.string(),
    capability: z.enum(CAPABILITY_OPTIONS),
  });

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

  try {
    await db
      .insert(portfolioCapabilities)
      .values({
        portfolioId: pId,
        userId: BigInt(body.userId),
        capability: body.capability as PortfolioCapabilityType,
      })
      .onConflictDoNothing();

    return NextResponse.json({ success: true }, { status: 200 });
  } catch (err) {
    console.error("POST /capabilities error:", err);
    return NextResponse.json(
      { error: "Failed to assign capability" },
      { status: 500 },
    );
  }
}

// DELETE — remove a capability from a user
export async function DELETE(
  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 pId = BigInt(portfolioId);

  const requestingRole = await getRequestingUserRole(pId, session.user.email);
  if (requestingRole !== "admin" && requestingRole !== "creator") {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  const bodySchema = z.object({
    userId: z.string(),
    capability: z.enum(CAPABILITY_OPTIONS),
  });

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

  try {
    await db
      .delete(portfolioCapabilities)
      .where(
        and(
          eq(portfolioCapabilities.portfolioId, pId),
          eq(portfolioCapabilities.userId, BigInt(body.userId)),
          eq(
            portfolioCapabilities.capability,
            body.capability as PortfolioCapabilityType,
          ),
        ),
      );

    return NextResponse.json({ success: true }, { status: 200 });
  } catch (err) {
    console.error("DELETE /capabilities error:", err);
    return NextResponse.json(
      { error: "Failed to remove capability" },
      { status: 500 },
    );
  }
}
