import { TRPCError } from "@trpc/server";
import type { TRPCContext } from "../trpc.js";

export type OwnedResourceReadContext = Pick<TRPCContext, "db" | "dbUser">;

export function canManageOwnedResourceReads(ctx: { dbUser: { systemRole: string } | null }): boolean {
  const role = ctx.dbUser?.systemRole;
  return role === "ADMIN" || role === "MANAGER";
}

export async function findOwnedReadResourceId(
  ctx: OwnedResourceReadContext,
): Promise<string | null> {
  if (!ctx.dbUser?.id) {
    return null;
  }

  if (!ctx.db.resource || typeof ctx.db.resource.findFirst !== "function") {
    return null;
  }

  const resource = await ctx.db.resource.findFirst({
    where: { userId: ctx.dbUser.id },
    select: { id: true },
  });

  return resource?.id ?? null;
}

export async function assertCanReadOwnedResource(
  ctx: OwnedResourceReadContext,
  resourceId: string,
  forbiddenMessage: string,
): Promise<void> {
  if (canManageOwnedResourceReads(ctx)) {
    return;
  }

  const ownedResourceId = await findOwnedReadResourceId(ctx);
  if (!ownedResourceId || ownedResourceId !== resourceId) {
    throw new TRPCError({
      code: "FORBIDDEN",
      message: forbiddenMessage,
    });
  }
}

export async function resolveOwnedResourceReadFilter(
  ctx: OwnedResourceReadContext,
  requestedResourceId: string | undefined,
  forbiddenMessage: string,
): Promise<string | null | undefined> {
  if (canManageOwnedResourceReads(ctx)) {
    return requestedResourceId;
  }

  const ownedResourceId = await findOwnedReadResourceId(ctx);
  if (requestedResourceId && requestedResourceId !== ownedResourceId) {
    throw new TRPCError({
      code: "FORBIDDEN",
      message: forbiddenMessage,
    });
  }

  return ownedResourceId;
}
