import { hashPassword } from "@pmap/auth";
import { prisma } from "@pmap/database";
import { fail, ok } from "../../_lib";

async function sha256(value: string): Promise<string> {
  const bytes = new TextEncoder().encode(value);
  const hash = await crypto.subtle.digest("SHA-256", bytes);
  return [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
}

export async function POST(request: Request) {
  try {
    const payload = await request.json().catch(() => null) as { token?: unknown; password?: unknown } | null;
    const token = typeof payload?.token === "string" ? payload.token : "";
    const password = typeof payload?.password === "string" ? payload.password : "";
    if (!token) return fail(request, "TOKEN_REQUIRED", "Password reset token is required.", 422);
    if (password.length < 8) return fail(request, "PASSWORD_TOO_SHORT", "Password must be at least 8 characters.", 422);

    const resetToken = await prisma.passwordResetToken.findUnique({
      where: { tokenHash: await sha256(token) }
    });
    if (!resetToken || resetToken.usedAt) return fail(request, "INVALID_TOKEN", "Password reset link is invalid.", 404);
    if (resetToken.expiresAt < new Date()) return fail(request, "EXPIRED_TOKEN", "Password reset link has expired.", 409);

    await prisma.$transaction([
      prisma.user.update({
        where: { id: resetToken.userId },
        data: { passwordHash: await hashPassword(password), failedLoginCount: 0, lockedUntil: null }
      }),
      prisma.passwordResetToken.update({
        where: { id: resetToken.id },
        data: { usedAt: new Date() }
      })
    ]);

    return ok(request, { updated: true });
  } catch (error) {
    return fail(request, "PASSWORD_RESET_UPDATE_FAILED", "Password could not be reset.", 500, error instanceof Error ? error.message : error);
  }
}
