import { NextRequest, NextResponse } from "next/server";
import { auth } from "@clerk/nextjs/server";
import { USER_ROLES } from "@fitai/shared";

export type UserRole = (typeof USER_ROLES)[number];

interface AuthResult {
  userId: string;
  role: UserRole;
}

/**
 * Middleware to require authentication and optionally check user role
 *
 * @param allowedRoles - Array of roles allowed to access the endpoint (optional)
 * @returns Authentication result with userId and role, or NextResponse error
 *
 * @example
 * export async function DELETE(request: NextRequest) {
 *   const authResult = await requireAuth(["admin", "superAdmin"]);
 *   if (authResult instanceof NextResponse) return authResult;
 *   const { userId, role } = authResult;
 *   // ... proceed with authorized logic
 * }
 */
export async function requireAuth(
  allowedRoles?: UserRole[],
): Promise<AuthResult | NextResponse> {
  const { userId } = await auth();

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

  // Get user role from Clerk metadata
  const { sessionClaims } = await auth();
  const role = (sessionClaims?.metadata as { role?: UserRole })?.role;

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

  // Check if user has required role
  if (allowedRoles && allowedRoles.length > 0) {
    if (!allowedRoles.includes(role)) {
      return NextResponse.json(
        {
          error: `Forbidden - Requires one of: ${allowedRoles.join(", ")}`,
          requiredRoles: allowedRoles,
          userRole: role,
        },
        { status: 403 },
      );
    }
  }

  return { userId, role };
}

/**
 * Check if the authenticated user is trying to modify their own account
 * Useful for preventing self-deletion or self-demotion
 *
 * @param userId - Authenticated user's ID
 * @param targetUserId - ID of user being modified
 * @returns true if user is modifying themselves
 */
export function isSelfModification(
  userId: string,
  targetUserId: string,
): boolean {
  return userId === targetUserId;
}

/**
 * Validate that an admin isn't demoting themselves or deleting their own account
 *
 * @param userId - Authenticated user's ID
 * @param targetUserId - ID of user being modified
 * @param action - Action being performed (e.g., "delete", "demote")
 * @returns NextResponse error if invalid, undefined if valid
 */
export function preventSelfModification(
  userId: string,
  targetUserId: string,
  action: string,
): NextResponse | undefined {
  if (isSelfModification(userId, targetUserId)) {
    return NextResponse.json(
      {
        error: `Cannot ${action} your own account`,
        hint: "Ask another administrator to perform this action",
      },
      { status: 403 },
    );
  }
  return undefined;
}
