import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/server/db";
import { UnauthorizedError } from "@/server/errors";
import { fail, ok } from "@/server/http";
import { hashOpaqueToken } from "@/server/security/auth";
import { setAuthCookies } from "@/server/security/cookies";
import { signAccessToken, signRefreshToken, verifyRefreshToken } from "@/server/security/jwt";

export async function POST(request: NextRequest) {
  try {
    const token = request.cookies.get("refresh_token")?.value;
    if (!token) throw new UnauthorizedError();
    const claims = await verifyRefreshToken(token);
    const session = await prisma.session.findFirst({
      where: {
        id: claims.sessionId,
        userId: claims.sub,
        revokedAt: null,
        expiresAt: { gt: new Date() },
        refreshTokenHash: hashOpaqueToken(token)
      },
      include: { user: true }
    });

    if (!session) throw new UnauthorizedError("Session expired");

    const accessToken = await signAccessToken({ userId: session.userId, sessionId: session.id, roles: session.user.roles });
    const refreshToken = await signRefreshToken({ userId: session.userId, sessionId: session.id });
    await prisma.session.update({
      where: { id: session.id },
      data: {
        refreshTokenHash: hashOpaqueToken(refreshToken),
        rotatedAt: new Date()
      }
    });

    const response = ok({ refreshed: true }) as NextResponse;
    setAuthCookies(response, { accessToken, refreshToken });
    return response;
  } catch (error) {
    return fail(error);
  }
}
