import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import {
  ACCESS_TOKEN_EXPIRES_IN,
  REFRESH_TOKEN_EXPIRES_IN,
  createMobileTokenPair,
  hashToken,
  revokeRefreshTokenFamily,
} from "@/lib/mobileTokens";

export async function POST(req: NextRequest) {
  const { refreshToken } = await req.json().catch(() => ({}));

  if (typeof refreshToken !== "string" || !refreshToken.trim()) {
    return NextResponse.json({ error: "refreshToken is required" }, { status: 400 });
  }

  const existingRefreshToken = await db.refreshToken.findUnique({
    where: { tokenHash: hashToken(refreshToken.trim()) },
    include: {
      user: {
        select: {
          id: true,
          name: true,
          phone: true,
          role: true,
        },
      },
    },
  });

  if (!existingRefreshToken) {
    return NextResponse.json({ error: "Invalid refresh token" }, { status: 401 });
  }

  if (existingRefreshToken.revokedAt) {
    await revokeRefreshTokenFamily(existingRefreshToken.userId, existingRefreshToken.familyId);
    return NextResponse.json({ error: "Refresh token has been revoked" }, { status: 401 });
  }

  if (existingRefreshToken.expiresAt <= new Date()) {
    await db.refreshToken.update({
      where: { id: existingRefreshToken.id },
      data: { revokedAt: new Date() },
    });

    return NextResponse.json({ error: "Refresh token has expired" }, { status: 401 });
  }

  const tokens = await createMobileTokenPair(existingRefreshToken.userId, existingRefreshToken.familyId);

  await db.refreshToken.update({
    where: { id: existingRefreshToken.id },
    data: {
      revokedAt: new Date(),
      replacedByTokenId: tokens.refreshTokenId,
    },
  });

  return NextResponse.json({
    accessToken: tokens.accessToken,
    token: tokens.accessToken,
    tokenType: "Bearer",
    expiresIn: ACCESS_TOKEN_EXPIRES_IN,
    expiresAt: tokens.accessTokenExpiresAt.toISOString(),
    refreshToken: tokens.refreshToken,
    refreshExpiresIn: REFRESH_TOKEN_EXPIRES_IN,
    refreshExpiresAt: tokens.refreshTokenExpiresAt.toISOString(),
    user: existingRefreshToken.user,
  });
}
