import { EngineMismatchError } from "./index.js";
import { eq } from "drizzle-orm";
import { boolean, pgTable, text, timestamp, uniqueIndex, varchar } from "drizzle-orm/pg-core";
import { betterAuth } from "better-auth";
import { parseSetCookieHeader } from "better-auth/cookies";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { jwt } from "better-auth/plugins";
//#region src/engine-better-auth.ts
const platformAccounts = pgTable("platform_accounts", {
	id: text("id").primaryKey(),
	email: varchar("email", { length: 255 }).notNull().unique(),
	name: varchar("name", { length: 255 }),
	emailVerified: boolean("emailVerified").default(false),
	avatarUrl: text("avatar_url"),
	createdAt: timestamp("created_at", { withTimezone: true }),
	updatedAt: timestamp("updated_at", { withTimezone: true })
});
const baSession = pgTable("session", {
	id: text("id").primaryKey(),
	token: text("token").notNull().unique(),
	userId: text("userId").notNull(),
	expiresAt: timestamp("expiresAt", { withTimezone: true }).notNull(),
	createdAt: timestamp("createdAt", { withTimezone: true }).notNull(),
	updatedAt: timestamp("updatedAt", { withTimezone: true }).notNull(),
	ipAddress: text("ipAddress"),
	userAgent: text("userAgent")
});
const baAccount = pgTable("account", {
	id: text("id").primaryKey(),
	userId: text("userId").notNull(),
	issuer: text("issuer").notNull(),
	accountId: text("accountId").notNull(),
	providerId: text("providerId").notNull(),
	accessToken: text("accessToken"),
	refreshToken: text("refreshToken"),
	idToken: text("idToken"),
	expiresAt: timestamp("expiresAt", { withTimezone: true }),
	password: text("password"),
	createdAt: timestamp("createdAt", { withTimezone: true }).notNull(),
	updatedAt: timestamp("updatedAt", { withTimezone: true }).notNull(),
	accessTokenExpiresAt: timestamp("accessTokenExpiresAt", { withTimezone: true }),
	refreshTokenExpiresAt: timestamp("refreshTokenExpiresAt", { withTimezone: true }),
	scope: text("scope")
}, (table) => [uniqueIndex("account_issuer_accountId_uidx").on(table.issuer, table.accountId)]);
const baVerification = pgTable("verification", {
	id: text("id").primaryKey(),
	identifier: text("identifier").notNull(),
	value: text("value").notNull(),
	expiresAt: timestamp("expiresAt", { withTimezone: true }).notNull(),
	createdAt: timestamp("createdAt", { withTimezone: true }),
	updatedAt: timestamp("updatedAt", { withTimezone: true })
});
const baJwks = pgTable("jwks", {
	id: text("id").primaryKey(),
	publicKey: text("publicKey").notNull(),
	privateKey: text("privateKey").notNull(),
	createdAt: timestamp("createdAt", { withTimezone: true }).notNull(),
	expiresAt: timestamp("expiresAt", { withTimezone: true }),
	alg: text("alg"),
	crv: text("crv")
});
const betterAuthSchema = {
	platformAccounts,
	baSession,
	baAccount,
	baVerification,
	baJwks
};
function readSessionCookieValue(setCookieHeader, cookiePrefix) {
	if (!setCookieHeader) return null;
	const name = `${cookiePrefix}.session_token`;
	return parseSetCookieHeader(setCookieHeader).get(name)?.value ?? null;
}
/**
* Better-auth adapter (session-cookie + JWT, bcrypt KDF).
* NOT wire-compatible with engine-custom — different KDF + session tables.
*/
function createBetterAuthEngine(config) {
	const cookiePrefix = config.cookiePrefix ?? "platform";
	const sessionCookieName = `${cookiePrefix}.session_token`;
	const auth = betterAuth({
		database: drizzleAdapter(config.db, {
			provider: "pg",
			schema: {
				user: platformAccounts,
				session: baSession,
				account: baAccount,
				verification: baVerification,
				jwks: baJwks
			}
		}),
		secret: config.secret,
		baseURL: config.baseURL ?? "http://localhost",
		emailAndPassword: {
			enabled: true,
			requireEmailVerification: false
		},
		session: {
			strategy: "jwt",
			maxAge: 2592e3
		},
		plugins: [jwt({ jwt: { expirationTime: "30d" } })],
		advanced: {
			generateId: () => crypto.randomUUID(),
			cookiePrefix: config.cookiePrefix ?? "platform"
		}
	});
	function toPrincipal(userId, sessionId, roles = ["user"]) {
		return {
			userId,
			sessionId,
			roles
		};
	}
	return {
		async signIn({ email, password }) {
			const cookieValue = readSessionCookieValue((await auth.api.signInEmail({
				body: {
					email,
					password
				},
				returnHeaders: true
			})).headers.get("set-cookie"), cookiePrefix);
			if (!cookieValue) throw new Error("invalid credentials");
			const session = await auth.api.getSession({ headers: new Headers({ cookie: `${sessionCookieName}=${cookieValue}` }) });
			if (!session?.user) throw new Error("invalid credentials");
			return {
				principal: toPrincipal(session.user.id, session.session.id),
				accessToken: cookieValue,
				refreshToken: session.session.token
			};
		},
		async signOut(sessionId) {
			await config.db.delete(baSession).where(eq(baSession.id, sessionId));
		},
		async verifySession(token) {
			const session = await auth.api.getSession({ headers: new Headers({ cookie: `${sessionCookieName}=${token}` }) });
			if (!session?.user) return null;
			return toPrincipal(session.user.id, session.session.id);
		},
		async refresh(refreshToken) {
			const session = await auth.api.getSession({ headers: new Headers({ cookie: `${sessionCookieName}=${refreshToken}` }) });
			if (!session?.user) return null;
			return {
				principal: toPrincipal(session.user.id, session.session.id),
				accessToken: refreshToken
			};
		},
		async createUser({ email, password, roles }) {
			if (roles !== void 0) throw new EngineMismatchError("createUser roles not supported by engine-better-auth — assign roles via a better-auth admin plugin");
			const res = await auth.api.signUpEmail({ body: {
				email,
				password,
				name: email.split("@")[0] ?? "user"
			} });
			if (!res?.user?.id) throw new Error("create failed");
			return { userId: res.user.id };
		},
		async setPassword(_userId, _password) {
			throw new EngineMismatchError("setPassword not supported by engine-better-auth — use the better-auth change-password handler");
		},
		async verifyPassword(_password, _storedHash) {
			throw new EngineMismatchError("verifyPassword not supported by engine-better-auth — route credentials through the better-auth sign-in handler");
		}
	};
}
//#endregion
export { baAccount, baJwks, baSession, baVerification, betterAuth, betterAuthSchema, createBetterAuthEngine, platformAccounts };
