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

const t = initTRPC.context<TRPCContext>().create();

export const createTRPCRouter = t.router;
export const publicProcedure = t.procedure;

const isAuthed = t.middleware(({ ctx, next }) => {
  if (!ctx.user) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  return next({
    ctx: { user: ctx.user },
  });
});

export const protectedProcedure = t.procedure.use(isAuthed);

const isAdmin = t.middleware(({ ctx, next }) => {
  if (!ctx.user) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  if ((ctx.user.role as string) !== "admin") {
    throw new TRPCError({ code: "FORBIDDEN" });
  }
  return next({
    ctx: { user: ctx.user },
  });
});

export const adminProcedure = t.procedure.use(isAdmin);

const rateLimitMap = new Map<string, { count: number; resetAt: number }>();

const isRateLimited = t.middleware(({ ctx, next }) => {
  const identifier = ctx.user?.id ?? ctx.apiKey ?? "anonymous";
  const now = Date.now();
  const entry = rateLimitMap.get(identifier);
  const limit = 100;
  const windowMs = 60_000;

  if (!entry || now > entry.resetAt) {
    rateLimitMap.set(identifier, { count: 1, resetAt: now + windowMs });
    return next();
  }

  if (entry.count >= limit) {
    throw new TRPCError({
      code: "TOO_MANY_REQUESTS",
      message: "Rate limit exceeded",
    });
  }

  entry.count++;
  return next();
});

export const rateLimitedProcedure = t.procedure.use(isRateLimited);
