import { randomBytes } from "node:crypto";
import { and, eq } from "drizzle-orm";
import type { db as prodDb } from "../../db/index.ts";
import { apiKeys, users } from "../../db/schema.ts";

type Db = typeof prodDb;

// ── User Management ──────────────────────────────────────────────────

export async function getOrCreateUser(
	db: Db,
	logtoSub: string,
): Promise<{ id: number }> {
	const [user] = await db
		.insert(users)
		.values({ logtoSub })
		.onConflictDoUpdate({
			target: users.logtoSub,
			set: { logtoSub },
		})
		.returning({ id: users.id });
	return user;
}

// ── API Key Management ───────────────────────────────────────────────

export async function createApiKey(db: Db, userId: number, name: string) {
	const rawKey = randomBytes(32).toString("hex");
	const keyHash = await Bun.password.hash(rawKey);
	const keyPrefix = rawKey.slice(0, 8);

	const [record] = await db
		.insert(apiKeys)
		.values({ name, keyHash, keyPrefix, userId })
		.returning();

	return { ...record, rawKey };
}

export async function verifyApiKey(
	db: Db,
	rawKey: string,
): Promise<{ userId: number } | null> {
	const prefix = rawKey.slice(0, 8);
	const candidates = await db
		.select()
		.from(apiKeys)
		.where(eq(apiKeys.keyPrefix, prefix));

	for (const candidate of candidates) {
		const valid = await Bun.password.verify(rawKey, candidate.keyHash);
		if (valid) return { userId: candidate.userId };
	}

	return null;
}

export async function listApiKeys(db: Db, userId: number) {
	return db
		.select({
			id: apiKeys.id,
			name: apiKeys.name,
			keyPrefix: apiKeys.keyPrefix,
			createdAt: apiKeys.createdAt,
		})
		.from(apiKeys)
		.where(eq(apiKeys.userId, userId));
}

export async function deleteApiKey(db: Db, userId: number, id: number) {
	await db
		.delete(apiKeys)
		.where(and(eq(apiKeys.id, id), eq(apiKeys.userId, userId)));
}
