import { boolean, pgTable, primaryKey, text, uuid } from "drizzle-orm/pg-core";
import { and, eq } from "drizzle-orm";
//#region src/rbac-triad.ts
const rolesTable = pgTable("tenancy_roles", {
	id: uuid("id").primaryKey().defaultRandom(),
	tenantId: uuid("tenant_id").notNull(),
	name: text("name").notNull(),
	isSystemRole: boolean("is_system_role").notNull().default(false)
});
const permissionsTable = pgTable("tenancy_permissions", {
	id: uuid("id").primaryKey().defaultRandom(),
	key: text("key").notNull().unique()
});
const rolePermissionsTable = pgTable("tenancy_role_permissions", {
	roleId: uuid("role_id").notNull().references(() => rolesTable.id, { onDelete: "cascade" }),
	permissionId: uuid("permission_id").notNull().references(() => permissionsTable.id, { onDelete: "cascade" })
}, (t) => ({ pk: primaryKey({ columns: [t.roleId, t.permissionId] }) }));
const triadSchema = {
	roles: rolesTable,
	permissions: permissionsTable,
	rolePermissions: rolePermissionsTable
};
/** Production-sourced system role set (spec excludes ACCOUNTANT). */
const SYSTEM_ROLE_NAMES = [
	"OWNER",
	"ADMIN",
	"MEMBER",
	"VIEWER",
	"CONTRACTOR"
];
const PERMISSION_KEYS = [
	"tasks:read",
	"tasks:write",
	"billing:manage",
	"users:manage",
	"reports:read",
	"time:read",
	"time:write",
	"time:track"
];
const ALL = [...PERMISSION_KEYS];
const READ_ONLY = ALL.filter((k) => k.endsWith(":read"));
const SYSTEM_ROLE_PERMISSIONS = {
	OWNER: ALL,
	ADMIN: ALL.filter((k) => k !== "billing:manage" && k !== "users:manage"),
	MEMBER: [
		"tasks:read",
		"tasks:write",
		"time:read",
		"time:track"
	],
	VIEWER: READ_ONLY,
	CONTRACTOR: [
		"time:read",
		"time:write",
		"time:track",
		"tasks:read"
	]
};
function createTriadRbac(db) {
	async function seedPermissionCatalog() {
		for (const key of PERMISSION_KEYS) await db.insert(permissionsTable).values({ key }).onConflictDoNothing({ target: permissionsTable.key });
	}
	async function seedSystemRoles(tenantId) {
		for (const roleName of SYSTEM_ROLE_NAMES) {
			const [role] = await db.insert(rolesTable).values({
				tenantId,
				name: roleName,
				isSystemRole: true
			}).returning({ id: rolesTable.id });
			if (!role) continue;
			const keys = SYSTEM_ROLE_PERMISSIONS[roleName];
			for (const key of keys) {
				const permissionId = (await db.select({ id: permissionsTable.id }).from(permissionsTable).where(eq(permissionsTable.key, key)).limit(1))[0]?.id;
				if (!permissionId) continue;
				await db.insert(rolePermissionsTable).values({
					roleId: role.id,
					permissionId
				}).onConflictDoNothing();
			}
		}
	}
	async function resolveCapabilities(input) {
		const roleId = (await db.select({ id: rolesTable.id }).from(rolesTable).where(and(eq(rolesTable.tenantId, input.tenantId), eq(rolesTable.name, input.roleKey))).limit(1))[0]?.id;
		if (!roleId) return [];
		return (await db.select({ key: permissionsTable.key }).from(rolePermissionsTable).innerJoin(permissionsTable, eq(rolePermissionsTable.permissionId, permissionsTable.id)).where(eq(rolePermissionsTable.roleId, roleId))).map((row) => row.key);
	}
	return {
		seedPermissionCatalog,
		seedSystemRoles,
		resolveCapabilities
	};
}
//#endregion
export { SYSTEM_ROLE_NAMES, SYSTEM_ROLE_PERMISSIONS, createTriadRbac, permissionsTable, rolePermissionsTable, rolesTable, triadSchema };
