// auth/token.ts
import { generateRandomString, isWithinExpiration } from "lucia/utils";

const EXPIRES_IN = 1000 * 60 * 60; // 1 hour

export const generateEmailVerificationToken = async (userId: string) => {
    const storedUserTokens = await prisma?.email_verification_token.findMany({
        where: {
            userId
        }
    }) ?? [];

    if (storedUserTokens.length > 0) {
        const reusableStoredToken = storedUserTokens.find((token) => {
            // check if expiration is within 1 hour
            // and reuse the token if true
            return isWithinExpiration(Number(token.expires) - EXPIRES_IN / 2);
        });

        if (reusableStoredToken) return reusableStoredToken.id;
    }

    const token = generateRandomString(63);
    await prisma?.email_verification_token.create({
        data: {
            id: token,
            expires: new Date().getTime() + EXPIRES_IN,
            userId,
        }
    })
    return token;
};

export const validateEmailVerificationToken = async (token: string) => {
    return await prisma?.$transaction(async (trx) => {
        // Find the stored token
        const storedToken = await trx.email_verification_token.findUnique({
            where: { id: token }
        });

        if (!storedToken) {
            throw new Error("Invalid token");
        }

        // Delete all tokens for the same user
        await trx.email_verification_token.deleteMany({
            where: { userId: storedToken.userId }
        });

        // Convert bigint to number if needed
        const tokenExpires = Number(storedToken.expires);

        if (!isWithinExpiration(tokenExpires)) {
            throw new Error("Expired token");
        }

        return storedToken.userId;
    });
};
