import { contentBriefFromMetadata, contentBriefToMetadata, generateContentBrief, supportsContentBrief, } from './issue-content-brief.js';
import { contentResearchFromMetadata, contentResearchToMetadata, generateContentResearch, supportsContentResearch, } from './issue-content-research.js';
export const BATCH_BRIEF_MAX_ISSUES = 15;
export const BATCH_BRIEF_CONCURRENCY = 2;
function asRecord(value) {
    if (!value || typeof value !== 'object' || Array.isArray(value))
        return {};
    return value;
}
async function mapWithConcurrency(items, concurrency, fn) {
    const results = new Array(items.length);
    let index = 0;
    async function worker() {
        while (index < items.length) {
            const i = index++;
            results[i] = await fn(items[i]);
        }
    }
    const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());
    await Promise.all(workers);
    return results;
}
export async function batchGenerateContentBriefs(issues, contexts, deps, options = {}) {
    const skipExisting = options.skipExisting !== false;
    const includeResearch = options.includeResearch === true;
    const capped = issues.filter((i) => supportsContentBrief(i.type)).slice(0, BATCH_BRIEF_MAX_ISSUES);
    const results = await mapWithConcurrency(capped, BATCH_BRIEF_CONCURRENCY, async (issue) => {
        if (!issue.entityId) {
            return { issueId: issue.id, status: 'failed', error: 'Not linked to content.' };
        }
        const ctx = contexts.get(issue.entityId);
        if (!ctx) {
            return { issueId: issue.id, status: 'failed', error: 'Content not found.' };
        }
        if (skipExisting) {
            const existing = contentBriefFromMetadata(issue.metadata, issue.type, issue.entityId, ctx.updatedAt);
            if (existing) {
                return { issueId: issue.id, status: 'skipped' };
            }
        }
        let research = null;
        if (includeResearch && supportsContentResearch(issue.type)) {
            const cachedResearch = contentResearchFromMetadata(issue.metadata, issue.type, issue.entityId, ctx.updatedAt);
            if (cachedResearch) {
                research = cachedResearch;
            }
            else {
                const researchResult = await generateContentResearch(issue, { entity: ctx.entity, updatedAt: ctx.updatedAt }, { ...deps, collection: ctx.collection }, { competitorUrls: options.competitorUrls });
                if (!researchResult.ok) {
                    return { issueId: issue.id, status: 'failed', error: researchResult.message };
                }
                research = researchResult.research;
            }
        }
        const briefResult = await generateContentBrief(issue, { entity: ctx.entity, updatedAt: ctx.updatedAt }, { ...deps, collection: ctx.collection }, research ? { research } : undefined);
        if (!briefResult.ok) {
            return { issueId: issue.id, status: 'failed', error: briefResult.message };
        }
        const metaPatch = {
            ...asRecord(issue.metadata),
            ...contentBriefToMetadata(briefResult.brief),
        };
        if (research) {
            Object.assign(metaPatch, contentResearchToMetadata(research));
        }
        await deps.db.seoIssue.update({
            where: { id: issue.id },
            data: { metadata: metaPatch },
        });
        return { issueId: issue.id, status: 'generated' };
    });
    let generated = 0;
    let skipped = 0;
    let failed = 0;
    for (const r of results) {
        if (r.status === 'generated')
            generated++;
        else if (r.status === 'skipped')
            skipped++;
        else
            failed++;
    }
    return { generated, skipped, failed, results };
}
//# sourceMappingURL=issue-batch-briefs.js.map