import { a as __exportAll } from "./runner-K8XK101B.mjs";
import { n as getI18nConfig } from "./config-CVssduLe.mjs";
import { t as EmDashValidationError } from "./types-CuW0zWDA.mjs";
import { t as BylineRepository } from "./byline-Bm8ZgUP9.mjs";

//#region src/api/handlers/bylines.ts
var bylines_exports = /* @__PURE__ */ __exportAll({
	handleBylineCreate: () => handleBylineCreate,
	handleBylineTranslations: () => handleBylineTranslations,
	handleBylineUpdate: () => handleBylineUpdate
});
const norm = (v) => v ?? null;
/**
* Whether the existing byline row's fixed columns match a fresh-create
* payload after null/undefined normalisation. Used by the D1 create-retry
* recovery branch.
*/
function bylineFixedFieldsMatch(existing, input, effectiveLocale) {
	return existing.displayName === input.displayName && norm(existing.bio) === norm(input.bio) && norm(existing.avatarMediaId) === norm(input.avatarMediaId) && norm(existing.websiteUrl) === norm(input.websiteUrl) && norm(existing.userId) === norm(input.userId) && existing.isGuest === (input.isGuest ?? false) && existing.locale === effectiveLocale;
}
/**
* Whether every key in `existing` appears in `input` with the same value.
* Allows `input` to contain additional keys (the partial-write recovery
* case); rejects on a divergent value or a key the input omits.
*/
function existingCustomFieldsAreSubsetOf(existing, input) {
	if (!input) return Object.keys(existing).length === 0;
	for (const [slug, value] of Object.entries(existing)) {
		if (!Object.hasOwn(input, slug)) return false;
		if (input[slug] !== value) return false;
	}
	return true;
}
/**
* Reject locales the site doesn't configure. Returns `null` when the locale
* is fine (omitted, or matches `locales` in the i18n config, or i18n isn't
* configured at all).
*/
function rejectUnknownLocale(locale) {
	if (!locale) return null;
	const config = getI18nConfig();
	if (!config) return null;
	if (config.locales.includes(locale)) return null;
	return {
		success: false,
		error: {
			code: "VALIDATION_ERROR",
			message: `Locale "${locale}" is not configured for this site`
		}
	};
}
/**
* List every translation of a byline (by row id). Returns NOT_FOUND when no
* row with the given id exists.
*/
async function handleBylineTranslations(db, id) {
	try {
		const repo = new BylineRepository(db);
		if (!await repo.findById(id)) return {
			success: false,
			error: {
				code: "NOT_FOUND",
				message: "Byline not found"
			}
		};
		return {
			success: true,
			data: { items: await repo.listTranslations(id) }
		};
	} catch {
		return {
			success: false,
			error: {
				code: "BYLINE_TRANSLATIONS_ERROR",
				message: "Failed to list byline translations"
			}
		};
	}
}
/**
* Create a new byline. When `translationOf` is supplied, the new row joins the
* source byline's translation_group (a sibling in the same logical identity).
*
* Translating from a source row only makes sense when the caller names the
* target locale, otherwise we'd silently clone into the configured default,
* which is almost never what's intended (and will collide if the source is
* already the default-locale row). Mirrors `handleMenuCreate`.
*/
async function handleBylineCreate(db, input) {
	try {
		if (input.translationOf && !input.locale) return {
			success: false,
			error: {
				code: "VALIDATION_ERROR",
				message: "`locale` is required when `translationOf` is provided"
			}
		};
		const localeErr = rejectUnknownLocale(input.locale);
		if (localeErr) return localeErr;
		const repo = new BylineRepository(db);
		let sourceGroup;
		if (input.translationOf) {
			const source = await repo.findById(input.translationOf);
			if (!source) return {
				success: false,
				error: {
					code: "NOT_FOUND",
					message: "Source byline for translation not found"
				}
			};
			sourceGroup = source.translationGroup ?? source.id;
		}
		const effectiveLocale = input.locale ?? getI18nConfig()?.defaultLocale ?? "en";
		if (sourceGroup) {
			if ((await repo.findByTranslationGroup(sourceGroup)).some((b) => b.locale === effectiveLocale)) return {
				success: false,
				error: {
					code: "CONFLICT",
					message: `Translation already exists in locale "${effectiveLocale}" for this byline`
				}
			};
		}
		const existing = await repo.findBySlug(input.slug, { locale: effectiveLocale });
		if (existing) {
			const expectedTranslationGroup = sourceGroup ?? existing.id;
			if (!!input.customFields && Object.keys(input.customFields).length > 0 && bylineFixedFieldsMatch(existing, input, effectiveLocale) && existing.translationGroup === expectedTranslationGroup && existingCustomFieldsAreSubsetOf(existing.customFields ?? {}, input.customFields)) {
				const recovered = await repo.update(existing.id, { customFields: input.customFields });
				if (recovered) return {
					success: true,
					data: recovered
				};
			}
			return {
				success: false,
				error: {
					code: "CONFLICT",
					message: `Byline "${input.slug}" already exists${input.locale ? ` in locale "${input.locale}"` : ""}`
				}
			};
		}
		return {
			success: true,
			data: await repo.create(input)
		};
	} catch (error) {
		if (error instanceof EmDashValidationError) return {
			success: false,
			error: {
				code: "VALIDATION_ERROR",
				message: error.message
			}
		};
		console.error("[BYLINE_CREATE_ERROR]", error);
		return {
			success: false,
			error: {
				code: "BYLINE_CREATE_ERROR",
				message: "Failed to create byline"
			}
		};
	}
}
/**
* Update an existing byline. Forwards every field on `UpdateBylineInput`
* to `BylineRepository.update`, including the Phase 3 `customFields`
* map; per-field type validation lives in the repo, which throws
* `EmDashValidationError` on unknown slugs, type mismatches, or
* `select`-choice misses. This handler translates that into a clean
* `VALIDATION_ERROR` (400 via `mapErrorStatus`).
*
* Returns `NOT_FOUND` when the byline id doesn't resolve. Generic
* failures surface as `BYLINE_UPDATE_ERROR` (500) without leaking the
* underlying message.
*/
async function handleBylineUpdate(db, id, input) {
	try {
		const byline = await new BylineRepository(db).update(id, input);
		if (!byline) return {
			success: false,
			error: {
				code: "NOT_FOUND",
				message: "Byline not found"
			}
		};
		return {
			success: true,
			data: byline
		};
	} catch (error) {
		if (error instanceof EmDashValidationError) return {
			success: false,
			error: {
				code: "VALIDATION_ERROR",
				message: error.message
			}
		};
		console.error("[BYLINE_UPDATE_ERROR]", error);
		return {
			success: false,
			error: {
				code: "BYLINE_UPDATE_ERROR",
				message: "Failed to update byline"
			}
		};
	}
}

//#endregion
export { handleBylineUpdate as i, handleBylineCreate as n, handleBylineTranslations as r, bylines_exports as t };
//# sourceMappingURL=bylines-6tm9mgQb.mjs.map