import { s as listTablesLike } from "./dialect-helpers-B9uSp2GJ.mjs";
import { t as validateIdentifier } from "./validate-CqRJb_xU.mjs";
import { n as decodeCursor, r as encodeCursor } from "./types-CMMN0pNg.mjs";
import { sql } from "kysely";
import { ulid } from "ulidx";

//#region src/database/repositories/byline.ts
function rowToByline(row) {
	return {
		id: row.id,
		slug: row.slug,
		displayName: row.display_name,
		bio: row.bio,
		avatarMediaId: row.avatar_media_id,
		websiteUrl: row.website_url,
		userId: row.user_id,
		isGuest: row.is_guest === 1,
		createdAt: row.created_at,
		updatedAt: row.updated_at
	};
}
var BylineRepository = class {
	constructor(db) {
		this.db = db;
	}
	async findById(id) {
		const row = await this.db.selectFrom("_emdash_bylines").selectAll().where("id", "=", id).executeTakeFirst();
		return row ? rowToByline(row) : null;
	}
	async findBySlug(slug) {
		const row = await this.db.selectFrom("_emdash_bylines").selectAll().where("slug", "=", slug).executeTakeFirst();
		return row ? rowToByline(row) : null;
	}
	async findByUserId(userId) {
		const row = await this.db.selectFrom("_emdash_bylines").selectAll().where("user_id", "=", userId).executeTakeFirst();
		return row ? rowToByline(row) : null;
	}
	async findMany(options) {
		const limit = Math.min(Math.max(options?.limit ?? 50, 1), 100);
		let query = this.db.selectFrom("_emdash_bylines").selectAll().orderBy("created_at", "desc").orderBy("id", "desc").limit(limit + 1);
		if (options?.search) {
			const term = `%${options.search.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_")}%`;
			query = query.where((eb) => eb.or([eb("display_name", "like", term), eb("slug", "like", term)]));
		}
		if (options?.isGuest !== void 0) query = query.where("is_guest", "=", options.isGuest ? 1 : 0);
		if (options?.userId !== void 0) query = query.where("user_id", "=", options.userId);
		if (options?.cursor) {
			const decoded = decodeCursor(options.cursor);
			if (decoded) query = query.where((eb) => eb.or([eb("created_at", "<", decoded.orderValue), eb.and([eb("created_at", "=", decoded.orderValue), eb("id", "<", decoded.id)])]));
		}
		const rows = await query.execute();
		const items = rows.slice(0, limit).map(rowToByline);
		const result = { items };
		if (rows.length > limit) {
			const last = items.at(-1);
			if (last) result.nextCursor = encodeCursor(last.createdAt, last.id);
		}
		return result;
	}
	async create(input) {
		const id = ulid();
		const now = (/* @__PURE__ */ new Date()).toISOString();
		await this.db.insertInto("_emdash_bylines").values({
			id,
			slug: input.slug,
			display_name: input.displayName,
			bio: input.bio ?? null,
			avatar_media_id: input.avatarMediaId ?? null,
			website_url: input.websiteUrl ?? null,
			user_id: input.userId ?? null,
			is_guest: input.isGuest ? 1 : 0,
			created_at: now,
			updated_at: now
		}).execute();
		const byline = await this.findById(id);
		if (!byline) throw new Error("Failed to create byline");
		return byline;
	}
	async update(id, input) {
		if (!await this.findById(id)) return null;
		const updates = { updated_at: (/* @__PURE__ */ new Date()).toISOString() };
		if (input.slug !== void 0) updates.slug = input.slug;
		if (input.displayName !== void 0) updates.display_name = input.displayName;
		if (input.bio !== void 0) updates.bio = input.bio;
		if (input.avatarMediaId !== void 0) updates.avatar_media_id = input.avatarMediaId;
		if (input.websiteUrl !== void 0) updates.website_url = input.websiteUrl;
		if (input.userId !== void 0) updates.user_id = input.userId;
		if (input.isGuest !== void 0) updates.is_guest = input.isGuest ? 1 : 0;
		await this.db.updateTable("_emdash_bylines").set(updates).where("id", "=", id).execute();
		return await this.findById(id);
	}
	async delete(id) {
		if (!await this.findById(id)) return false;
		await this.db.transaction().execute(async (trx) => {
			await trx.deleteFrom("_emdash_content_bylines").where("byline_id", "=", id).execute();
			await trx.deleteFrom("_emdash_bylines").where("id", "=", id).execute();
			const tableNames = await listTablesLike(trx, "ec_%");
			for (const tableName of tableNames) {
				validateIdentifier(tableName, "content table");
				await sql`
					UPDATE ${sql.ref(tableName)}
					SET primary_byline_id = NULL
					WHERE primary_byline_id = ${id}
				`.execute(trx);
			}
		});
		return true;
	}
	async getContentBylines(collectionSlug, contentId) {
		return (await this.db.selectFrom("_emdash_content_bylines as cb").innerJoin("_emdash_bylines as b", "b.id", "cb.byline_id").select([
			"cb.sort_order as sort_order",
			"cb.role_label as role_label",
			"b.id as id",
			"b.slug as slug",
			"b.display_name as display_name",
			"b.bio as bio",
			"b.avatar_media_id as avatar_media_id",
			"b.website_url as website_url",
			"b.user_id as user_id",
			"b.is_guest as is_guest",
			"b.created_at as created_at",
			"b.updated_at as updated_at"
		]).where("cb.collection_slug", "=", collectionSlug).where("cb.content_id", "=", contentId).orderBy("cb.sort_order", "asc").execute()).map((row) => ({
			byline: rowToByline(row),
			sortOrder: row.sort_order,
			roleLabel: row.role_label
		}));
	}
	/**
	* Batch-fetch byline credits for multiple content items in a single query.
	* Returns a Map keyed by contentId.
	*/
	async getContentBylinesMany(collectionSlug, contentIds) {
		const result = /* @__PURE__ */ new Map();
		if (contentIds.length === 0) return result;
		const rows = await this.db.selectFrom("_emdash_content_bylines as cb").innerJoin("_emdash_bylines as b", "b.id", "cb.byline_id").select([
			"cb.content_id as content_id",
			"cb.sort_order as sort_order",
			"cb.role_label as role_label",
			"b.id as id",
			"b.slug as slug",
			"b.display_name as display_name",
			"b.bio as bio",
			"b.avatar_media_id as avatar_media_id",
			"b.website_url as website_url",
			"b.user_id as user_id",
			"b.is_guest as is_guest",
			"b.created_at as created_at",
			"b.updated_at as updated_at"
		]).where("cb.collection_slug", "=", collectionSlug).where("cb.content_id", "in", contentIds).orderBy("cb.sort_order", "asc").execute();
		for (const row of rows) {
			const contentId = row.content_id;
			const credit = {
				byline: rowToByline(row),
				sortOrder: row.sort_order,
				roleLabel: row.role_label
			};
			const existing = result.get(contentId);
			if (existing) existing.push(credit);
			else result.set(contentId, [credit]);
		}
		return result;
	}
	/**
	* Batch-fetch byline profiles linked to user IDs in a single query.
	* Returns a Map keyed by userId.
	*/
	async findByUserIds(userIds) {
		const result = /* @__PURE__ */ new Map();
		if (userIds.length === 0) return result;
		const rows = await this.db.selectFrom("_emdash_bylines").selectAll().where("user_id", "in", userIds).execute();
		for (const row of rows) if (row.user_id) result.set(row.user_id, rowToByline(row));
		return result;
	}
	async setContentBylines(collectionSlug, contentId, inputBylines) {
		validateIdentifier(collectionSlug, "collection slug");
		const tableName = `ec_${collectionSlug}`;
		validateIdentifier(tableName, "content table");
		const seen = /* @__PURE__ */ new Set();
		const bylines = inputBylines.filter((item) => {
			if (seen.has(item.bylineId)) return false;
			seen.add(item.bylineId);
			return true;
		});
		if (bylines.length > 0) {
			const ids = bylines.map((item) => item.bylineId);
			if ((await this.db.selectFrom("_emdash_bylines").select("id").where("id", "in", ids).execute()).length !== ids.length) throw new Error("One or more byline IDs do not exist");
		}
		await this.db.deleteFrom("_emdash_content_bylines").where("collection_slug", "=", collectionSlug).where("content_id", "=", contentId).execute();
		for (let i = 0; i < bylines.length; i++) {
			const item = bylines[i];
			await this.db.insertInto("_emdash_content_bylines").values({
				id: ulid(),
				collection_slug: collectionSlug,
				content_id: contentId,
				byline_id: item.bylineId,
				sort_order: i,
				role_label: item.roleLabel ?? null,
				created_at: (/* @__PURE__ */ new Date()).toISOString()
			}).execute();
		}
		await sql`
			UPDATE ${sql.ref(tableName)}
			SET primary_byline_id = ${bylines[0]?.bylineId ?? null}
			WHERE id = ${contentId}
		`.execute(this.db);
		return await this.getContentBylines(collectionSlug, contentId);
	}
};

//#endregion
export { BylineRepository as t };
//# sourceMappingURL=byline-CL847F26.mjs.map