/**
 * ContentLibrary — persistent, cross-session state for content generation work.
 *
 * Mirrors the Trading vertical: Library is the state object, Budget is the
 * risk engine, store.ts is the persistence adapter, and tools/content-execute.ts
 * wires everything into agent-facing capabilities.
 *
 * Why this exists: stateless coding agents can't carry a content project
 * across sessions. If you start drafting a podcast episode Monday and come back
 * Wednesday, there's no concept of *the same* piece of work. Franklin tracks
 * outline → drafts → assets → distribution as one durable object and lets
 * the agent spend USDC (image generation, audio, stock footage) against a
 * budget that survives session boundaries.
 */
import { randomUUID } from 'node:crypto';
export class ContentLibrary {
    byId = new Map();
    create(opts) {
        if (opts.budgetUsd < 0) {
            throw new Error('budgetUsd must be non-negative');
        }
        const now = Date.now();
        const content = {
            id: randomUUID(),
            type: opts.type,
            title: opts.title,
            status: 'outline',
            drafts: [],
            assets: [],
            spentUsd: 0,
            budgetUsd: opts.budgetUsd,
            createdAt: now,
            distribution: [],
        };
        this.byId.set(content.id, content);
        return content;
    }
    get(id) {
        return this.byId.get(id);
    }
    list() {
        return [...this.byId.values()].sort((a, b) => b.createdAt - a.createdAt);
    }
    /** Replace a content record wholesale — used by the persistence layer. */
    restore(content) {
        this.byId.set(content.id, content);
    }
    /**
     * Record a generated asset against a content, enforcing the budget cap.
     * Returns `{ ok: false, reason }` on rejection so callers (including the
     * agent-facing capability) can surface the reason instead of catching an
     * exception. On the happy path mutates the Content in place and returns
     * the updated spendUsd.
     */
    addAsset(id, asset) {
        const content = this.byId.get(id);
        if (!content) {
            return { ok: false, reason: `Content ${id} not found` };
        }
        if (asset.costUsd < 0) {
            return { ok: false, reason: 'costUsd must be non-negative' };
        }
        const projected = content.spentUsd + asset.costUsd;
        if (projected > content.budgetUsd + 1e-9) {
            return {
                ok: false,
                reason: `Exceeds budget: spent $${content.spentUsd.toFixed(2)} + proposed ` +
                    `$${asset.costUsd.toFixed(2)} > cap $${content.budgetUsd.toFixed(2)}`,
            };
        }
        content.assets.push({ ...asset, createdAt: Date.now() });
        content.spentUsd = projected;
        return { ok: true, spentUsd: projected };
    }
}
