/**
 * @fileoverview Library entry service for workspace-backed files and durable
 * organization context references.
 *
 * @see doc/product/domains/library-and-context/resources-library-workspaces.md - Library files and workspace resource links
 * @see doc/product/domains/library-and-context/documents-and-work-products.md - durable work products and documents
 * @see doc/product/domains/agents/instruction-loading.md - runtime context eligibility
 */
import { libraryEntries } from "@rudderhq/db";
import { and, eq, like, or } from "drizzle-orm";
function titleFromPath(filePath) {
    const segments = filePath.split("/").filter(Boolean);
    return segments.at(-1) ?? filePath;
}
export function libraryEntryService(db) {
    async function getByCurrentPath(orgId, filePath) {
        return await db
            .select()
            .from(libraryEntries)
            .where(and(eq(libraryEntries.orgId, orgId), eq(libraryEntries.currentPath, filePath), eq(libraryEntries.kind, "file"), eq(libraryEntries.sourceType, "workspace_file")))
            .then((rows) => rows[0] ?? null);
    }
    return {
        async getById(orgId, entryId) {
            return await db
                .select()
                .from(libraryEntries)
                .where(and(eq(libraryEntries.orgId, orgId), eq(libraryEntries.id, entryId)))
                .then((rows) => rows[0] ?? null);
        },
        async getByCurrentPath(orgId, filePath) {
            return getByCurrentPath(orgId, filePath);
        },
        async getOrCreateWorkspaceFileEntry(orgId, filePath, title) {
            const existing = await getByCurrentPath(orgId, filePath);
            if (existing)
                return existing;
            const [entry] = await db
                .insert(libraryEntries)
                .values({
                orgId,
                kind: "file",
                sourceType: "workspace_file",
                currentPath: filePath,
                title: title?.trim() || titleFromPath(filePath),
                status: "active",
            })
                .onConflictDoNothing({
                target: [libraryEntries.orgId, libraryEntries.currentPath],
            })
                .returning();
            if (entry)
                return entry;
            const createdByConcurrentRequest = await getByCurrentPath(orgId, filePath);
            if (createdByConcurrentRequest)
                return createdByConcurrentRequest;
            throw new Error("Failed to create or load Library entry for workspace file");
        },
        async listByCurrentPaths(orgId, filePaths) {
            const entries = new Map();
            if (filePaths.length === 0)
                return entries;
            await Promise.all(filePaths.map(async (filePath) => {
                const entry = await getByCurrentPath(orgId, filePath);
                if (entry?.currentPath)
                    entries.set(entry.currentPath, entry);
            }));
            return entries;
        },
        async moveWorkspaceFileEntry(orgId, previousPath, nextPath) {
            const existing = await getByCurrentPath(orgId, previousPath);
            if (!existing)
                return null;
            const [updated] = await db
                .update(libraryEntries)
                .set({
                currentPath: nextPath,
                title: titleFromPath(nextPath),
                status: "active",
                updatedAt: new Date(),
            })
                .where(and(eq(libraryEntries.orgId, orgId), eq(libraryEntries.id, existing.id)))
                .returning();
            return updated ?? null;
        },
        async moveWorkspaceDirectoryEntries(orgId, previousPath, nextPath) {
            const rows = await db
                .select()
                .from(libraryEntries)
                .where(and(eq(libraryEntries.orgId, orgId), eq(libraryEntries.kind, "file"), eq(libraryEntries.sourceType, "workspace_file"), or(eq(libraryEntries.currentPath, previousPath), like(libraryEntries.currentPath, `${previousPath}/%`))));
            await Promise.all(rows.map(async (entry) => {
                if (!entry.currentPath)
                    return;
                const movedPath = entry.currentPath === previousPath
                    ? nextPath
                    : `${nextPath}${entry.currentPath.slice(previousPath.length)}`;
                await db
                    .update(libraryEntries)
                    .set({
                    currentPath: movedPath,
                    title: titleFromPath(movedPath),
                    status: "active",
                    updatedAt: new Date(),
                })
                    .where(and(eq(libraryEntries.orgId, orgId), eq(libraryEntries.id, entry.id)));
            }));
        },
        async markWorkspaceFileEntryDeleted(orgId, filePath) {
            const existing = await getByCurrentPath(orgId, filePath);
            if (!existing)
                return null;
            const [updated] = await db
                .update(libraryEntries)
                .set({
                currentPath: null,
                status: "deleted",
                updatedAt: new Date(),
            })
                .where(and(eq(libraryEntries.orgId, orgId), eq(libraryEntries.id, existing.id)))
                .returning();
            return updated ?? null;
        },
        async markWorkspaceDirectoryEntriesDeleted(orgId, directoryPath) {
            await db
                .update(libraryEntries)
                .set({
                currentPath: null,
                status: "deleted",
                updatedAt: new Date(),
            })
                .where(and(eq(libraryEntries.orgId, orgId), eq(libraryEntries.kind, "file"), eq(libraryEntries.sourceType, "workspace_file"), or(eq(libraryEntries.currentPath, directoryPath), like(libraryEntries.currentPath, `${directoryPath}/%`))));
        },
    };
}
//# sourceMappingURL=library-entries.js.map