/**
 * Read-only projection service for the review queue surface.
 */
import { REVIEW_PROJECTION_DECISIONS, REVIEW_PROJECTION_PUBLIC_SOURCE, REVIEW_PROJECTION_STATUSES, isUnsafePublicString, readReviewLabel, toneForReviewStatus, } from "./reviewProjectionContract.js";
const STATUSES = new Set(REVIEW_PROJECTION_STATUSES);
const DECISIONS = new Set(REVIEW_PROJECTION_DECISIONS);
export class ReviewProjectionService {
    store;
    constructor(store) {
        this.store = store;
    }
    listReviewQueue(workspaceId) {
        const generatedAt = new Date().toISOString();
        const items = [];
        const rows = this.store.listReviewQueue(workspaceId);
        const decisions = this.store.listReviewDecisions(workspaceId);
        const decisionsByReview = new Map();
        // listReviewDecisions returns decided_at DESC — first per reviewId wins.
        for (const decision of decisions) {
            if (!decisionsByReview.has(decision.reviewId)) {
                decisionsByReview.set(decision.reviewId, decision);
            }
        }
        for (const row of rows) {
            if (!STATUSES.has(row.status))
                continue;
            const headline = readReviewLabel(row.headline);
            if (!headline)
                continue;
            if (isUnsafePublicString(row.workspaceId))
                continue;
            if (isUnsafePublicString(row.id))
                continue;
            const status = row.status;
            const summaryLabel = readReviewLabel(row.summaryLabel ?? null);
            const decision = decisionsByReview.get(row.id);
            let mappedDecision = null;
            let decisionReason = null;
            let decisionNote = null;
            let decidedAt = null;
            if (decision && DECISIONS.has(decision.decision)) {
                mappedDecision = decision.decision;
                decisionReason = readReviewLabel(decision.reasonCode ?? null);
                decisionNote = readReviewLabel(decision.noteLabel ?? null);
                decidedAt = decision.decidedAt;
            }
            items.push({
                source: REVIEW_PROJECTION_PUBLIC_SOURCE,
                id: row.id,
                workspaceId: row.workspaceId,
                status,
                tone: toneForReviewStatus(status),
                headline,
                summaryLabel,
                decision: mappedDecision,
                decisionReason,
                decisionNote,
                decidedAt,
            });
        }
        return { contractVersion: "v1", generatedAt, items };
    }
}
