import { db, setupTokens, users } from "@server/db";
import { eq } from "drizzle-orm";
import { generateRandomString, RandomReader } from "@oslojs/crypto/random";
import moment from "moment";
import logger from "@server/logger";

const random: RandomReader = {
    read(bytes: Uint8Array): void {
        crypto.getRandomValues(bytes);
    }
};

function generateToken(): string {
    // Generate a 32-character alphanumeric token
    const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
    return generateRandomString(random, alphabet, 32);
}

function generateId(length: number): string {
    const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
    return generateRandomString(random, alphabet, length);
}

export async function ensureSetupToken() {
    try {
        // Check if a server admin already exists
        const [existingAdmin] = await db
            .select()
            .from(users)
            .where(eq(users.serverAdmin, true));

        // If admin exists, no need for setup token
        if (existingAdmin) {
            logger.debug(
                "Server admin exists. Setup token generation skipped."
            );
            return;
        }

        // Check if a setup token already exists
        const existingTokens = await db
            .select()
            .from(setupTokens)
            .where(eq(setupTokens.used, false));

        // If unused token exists, display it instead of creating a new one
        if (existingTokens.length > 0) {
            console.log("=== SETUP TOKEN EXISTS ===");
            console.log("Token:", existingTokens[0].token);
            console.log("Use this token on the initial setup page");
            console.log("================================");
            return;
        }

        // Generate a new setup token
        const token = generateToken();
        const tokenId = generateId(15);

        await db.insert(setupTokens).values({
            tokenId: tokenId,
            token: token,
            used: false,
            dateCreated: moment().toISOString(),
            dateUsed: null
        });

        console.log("=== SETUP TOKEN GENERATED ===");
        console.log("Token:", token);
        console.log("Use this token on the initial setup page");
        console.log("================================");
    } catch (error) {
        console.error("Failed to ensure setup token:", error);
        throw error;
    }
}
