import { PGlite } from "@electric-sql/pglite";
import { sql } from "drizzle-orm";
import { drizzle } from "drizzle-orm/pglite";
import { migrate } from "drizzle-orm/pglite/migrator";
import * as schema from "../../src/db/schema.ts";

type Db = ReturnType<typeof drizzle<typeof schema>>;

// Cache: one PGlite instance per test file (per worker)
let cachedClient: PGlite | null = null;
let cachedDb: Db | null = null;

async function getOrCreateDb(): Promise<Db> {
	if (cachedDb) return cachedDb;
	cachedClient = new PGlite();
	cachedDb = drizzle(cachedClient, { schema });
	await migrate(cachedDb, { migrationsFolder: "./drizzle-pg" });
	return cachedDb;
}

// Truncation order respects foreign keys (children first)
const TRUNCATE_TABLES = [
	"shares",
	"setup_items",
	"setups",
	"thread_candidates",
	"threads",
	"items",
	"global_item_tags",
	"global_items",
	"tags",
	"oauth_tokens",
	"oauth_codes",
	"oauth_clients",
	"api_keys",
	"settings",
	"categories",
	"users",
];

export async function createTestDb() {
	const db = await getOrCreateDb();

	// Truncate all tables and reset sequences (fast reset, no PGlite restart)
	for (const t of TRUNCATE_TABLES) {
		await db.execute(sql.raw(`TRUNCATE TABLE "${t}" RESTART IDENTITY CASCADE`));
	}

	// Seed a test user
	const [user] = await db
		.insert(schema.users)
		.values({ logtoSub: "test-user-sub" })
		.returning();

	// Seed per-user Uncategorized category
	await db
		.insert(schema.categories)
		.values({ name: "Uncategorized", icon: "package", userId: user.id });

	return { db, userId: user.id };
}

export async function createSecondTestUser(db: Db) {
	const [user] = await db
		.insert(schema.users)
		.values({ logtoSub: "test-user-2-sub" })
		.returning();

	await db
		.insert(schema.categories)
		.values({ name: "Uncategorized", icon: "package", userId: user.id });

	return user.id;
}
