import { resolver, SecurePassword, hash256 } from "blitz";

import db from "../../../db";
import { ResetPassword } from "../validations";
import login from "./login";

export class ResetPasswordError extends Error {
	name = "ResetPasswordError";
	message = "Reset password link is invalid or it has expired.";
}

export default resolver.pipe(resolver.zod(ResetPassword), async ({ password, token }, ctx) => {
	// 1. Try to find this token in the database
	const hashedToken = hash256(token);
	const possibleToken = await db.token.findFirst({
		where: { hashedToken, type: "RESET_PASSWORD" },
		include: { user: true },
	});

	// 2. If token not found, error
	if (!possibleToken) {
		throw new ResetPasswordError();
	}
	const savedToken = possibleToken;

	// 3. Delete token so it can't be used again
	await db.token.delete({ where: { id: savedToken.id } });

	// 4. If token has expired, error
	if (savedToken.expiresAt < new Date()) {
		throw new ResetPasswordError();
	}

	// 5. Since token is valid, now we can update the user's password
	const hashedPassword = await SecurePassword.hash(password.trim());
	const user = await db.user.update({
		where: { id: savedToken.userId },
		data: { hashedPassword },
	});

	// 6. Revoke all existing login sessions for this user
	await db.session.deleteMany({ where: { userId: user.id } });

	// 7. Now log the user in with the new credentials
	await login({ email: user.email, password }, ctx);

	return true;
});