import { auth } from "@clerk/nextjs/server";
import { NextResponse } from "next/server";
import { USER_ROLES, type UserRole } from "@fitai/shared";
import { setUserRole } from "@/lib/clerk-helpers";
import { getDatabase } from "@/lib/database";
import { ensureUserSynced } from "@/lib/sync-user";

export async function POST(req: Request) {
  try {
    // Authenticate the request
    const { userId } = await auth();

    if (!userId) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const db = await getDatabase();
    const currentUser = await ensureUserSynced(userId, db);

    if (!currentUser) {
      return NextResponse.json(
        { error: "Forbidden: user not found" },
        { status: 403 },
      );
    }

    // Check if the requesting user is an admin
    const requestingUserIsAdmin =
      currentUser.role === "admin" || currentUser.role === "superAdmin";

    if (!requestingUserIsAdmin) {
      return NextResponse.json(
        { error: "Forbidden: Admin access required" },
        { status: 403 },
      );
    }

    // Parse request body
    const body = await req.json();
    const { targetUserId, role } = body;

    // Validate inputs
    if (!targetUserId || typeof targetUserId !== "string") {
      return NextResponse.json(
        { error: "Invalid or missing targetUserId" },
        { status: 400 },
      );
    }

    if (!role || !USER_ROLES.includes(role as UserRole)) {
      return NextResponse.json(
        {
          error: `Invalid role. Must be one of: ${USER_ROLES.join(", ")}`,
        },
        { status: 400 },
      );
    }

    const allowedRolesByRequester: Record<UserRole, UserRole[]> = {
      superAdmin: ["superAdmin", "admin", "trainer", "client"],
      admin: ["admin", "trainer", "client"],
      trainer: [],
      client: [],
    };

    const allowedTargetRoles = allowedRolesByRequester[currentUser.role];
    if (!allowedTargetRoles.includes(role as UserRole)) {
      return NextResponse.json(
        { error: `Forbidden: cannot assign role '${role}'` },
        { status: 403 },
      );
    }

    // Prevent admin from changing their own role
    if (userId === targetUserId) {
      return NextResponse.json(
        { error: "Cannot change your own role" },
        { status: 400 },
      );
    }

    const targetUser = await db.getUserById(targetUserId);
    if (!targetUser) {
      return NextResponse.json({ error: "User not found" }, { status: 404 });
    }

    if (
      currentUser.role !== "superAdmin" &&
      (!currentUser.gymId || targetUser.gymId !== currentUser.gymId)
    ) {
      return NextResponse.json(
        { error: "Cannot change roles for users from other gyms" },
        { status: 403 },
      );
    }

    // Set the user's role
    const updatedUser = await setUserRole(targetUserId, role as UserRole);

    return NextResponse.json({
      success: true,
      message: `User role updated to ${role}`,
      user: {
        id: updatedUser.id,
        email: updatedUser.emailAddresses[0]?.emailAddress,
        firstName: updatedUser.firstName,
        lastName: updatedUser.lastName,
        role: updatedUser.publicMetadata.role,
      },
    });
  } catch (error) {
    console.error("Error setting user role:", error);

    if (error instanceof Error && error.message.includes("not found")) {
      return NextResponse.json({ error: "User not found" }, { status: 404 });
    }

    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 },
    );
  }
}
