/**
 * Disclosure-Accounting Report Template (P3.5)
 *
 * Generates a per-data-subject disclosure accounting report from the canonical
 * audit event chain. Directly satisfies:
 *   - HIPAA §164.528 (Accounting of Disclosures of Protected Health Information):
 *     Each disclosure of PHI must be recorded with the date, recipient, description
 *     of the PHI disclosed, and purpose of the disclosure.
 *   - FERPA 34 CFR §99.32 (Record of Disclosures):
 *     Institutions must maintain a record of each request for access and each
 *     disclosure made to parties other than the student/parent.
 *   - RESPA 12 CFR §1024.10 / §1024.17:
 *     Settlement record and escrow accounting documentation.
 *   - Title IX 34 CFR §106.45:
 *     Procedural records for Title IX investigations and hearings.
 *
 * The report is produced from PackEnforcementAuditEvent records that carry
 * five-dimensional identity (P3.5):
 *   1. agentId (dimension 1)
 *   2. operatorId (dimension 2)
 *   3. dataSubjectId (dimension 3, pseudonymized SHA-256)
 *   4. recipientId / recipientType (dimension 4)
 *   5. transportMechanism / transportIntegrity (dimension 5)
 *
 * @connexum/ai-governance
 */
// ---------------------------------------------------------------------------
// Plaintext transport mechanisms (matches TS set in pack-driven-classifier)
// ---------------------------------------------------------------------------
const PLAINTEXT_MECHANISMS = new Set(['sms', 'fax', 'print']);
// ---------------------------------------------------------------------------
// Generator
// ---------------------------------------------------------------------------
/**
 * Generate a disclosure-accounting report for a single data subject.
 *
 * @param dataSubjectId Pseudonymized SHA-256 subject hash.
 * @param events        Array of PackEnforcementAuditEvents from drainAuditEvents()
 *                      or from the persisted audit chain query.
 * @param options       Optional filters: startDate, endDate (ISO strings), packId.
 *
 * @returns DisclosureAccountingReport ready for rendering or API response.
 *
 * @example
 * ```ts
 * const classifier = new PackDrivenClassifier();
 * // ... load packs ...
 * const events = classifier.drainAuditEvents();
 * const report = generateDisclosureAccountingReport(
 *   'sha256:abc123...',
 *   events,
 *   { startDate: '2026-01-01', endDate: '2026-12-31', packId: 'hipaa' },
 * );
 * ```
 */
export function generateDisclosureAccountingReport(dataSubjectId, events, options = {}) {
    const { startDate = null, endDate = null, packId = null } = options;
    const generatedAt = new Date().toISOString();
    // Filter events by subject, date range, and packId
    const filtered = events.filter(ev => {
        if (ev.dataSubjectId !== dataSubjectId)
            return false;
        if (startDate && ev.timestamp < startDate)
            return false;
        if (endDate && ev.timestamp > endDate)
            return false;
        if (packId && ev.packId !== packId)
            return false;
        // Skip meta-events that are warnings, not primary disclosures
        if (ev.type === 'disclosure.missing-subject-id')
            return false;
        return true;
    });
    // Build line items
    const lineItems = filtered.map(ev => ({
        auditId: ev.decisionId,
        timestamp: ev.timestamp,
        packId: ev.packId,
        categoryId: ev.categoryId,
        action: ev.action,
        agentId: undefined, // agentId is on the ClassificationContext, not on the event itself
        operatorId: ev.operatorId,
        recipientId: ev.recipientId,
        recipientType: ev.recipientType,
        transportMechanism: ev.transportMechanism,
        transportIntegrity: ev.transportIntegrity,
        plaintextTransportWarning: PLAINTEXT_MECHANISMS.has(ev.transportMechanism ?? '') || ev.transportIntegrity === 'plaintext',
        attributionMethod: ev.attributionMethod,
    }));
    // Group by category > recipient
    const categoryMap = new Map();
    for (const item of lineItems) {
        const catKey = `${item.packId}::${item.categoryId}`;
        const recipKey = item.recipientId ?? 'unattributed';
        if (!categoryMap.has(catKey))
            categoryMap.set(catKey, new Map());
        const recipMap = categoryMap.get(catKey);
        if (!recipMap.has(recipKey))
            recipMap.set(recipKey, []);
        recipMap.get(recipKey).push(item);
    }
    const disclosures = [];
    for (const [catKey, recipMap] of categoryMap) {
        const [packIdFromKey, categoryId] = catKey.split('::');
        const byRecipient = [];
        let total = 0;
        for (const [recipientId, items] of recipMap) {
            const transports = [...new Set(items.map(i => i.transportMechanism ?? 'unknown'))];
            byRecipient.push({
                recipientId,
                recipientType: items[0]?.recipientType ?? 'unknown',
                transports,
                count: items.length,
                events: items,
            });
            total += items.length;
        }
        disclosures.push({
            categoryId,
            packId: packIdFromKey,
            totalDisclosures: total,
            byRecipient,
        });
    }
    const plaintextTransportCount = lineItems.filter(i => i.plaintextTransportWarning).length;
    const unattributedRecipientCount = lineItems.filter(i => !i.recipientId).length;
    // Regulatory basis
    const basis = ['HIPAA §164.528'];
    if (disclosures.some(d => d.packId === 'ferpa'))
        basis.push('FERPA 34 CFR §99.32');
    if (disclosures.some(d => d.packId === 'us-respa' || d.packId === 'respa'))
        basis.push('RESPA 12 CFR §1024.10');
    if (disclosures.some(d => d.packId === 'ferpa' && d.categoryId.includes('TITLE_IX'))) {
        basis.push('Title IX 34 CFR §106.45');
    }
    return {
        dataSubjectId,
        startDate,
        endDate,
        packId,
        regulatoryBasis: basis,
        generatedAt,
        totalDisclosures: lineItems.length,
        plaintextTransportCount,
        unattributedRecipientCount,
        disclosures,
        lineItems,
    };
}
/**
 * Render a disclosure-accounting report to a human-readable text summary.
 * Suitable for printing, email delivery, or inclusion in a PDF.
 *
 * @param report The report generated by generateDisclosureAccountingReport.
 * @returns Multi-line text string.
 */
export function renderDisclosureAccountingReport(report) {
    const lines = [
        '=== DISCLOSURE ACCOUNTING REPORT ===',
        `Data Subject ID (pseudonymized): ${report.dataSubjectId}`,
        `Report Generated:                ${report.generatedAt}`,
        `Period:                          ${report.startDate ?? 'all'} to ${report.endDate ?? 'all'}`,
        `Pack Filter:                     ${report.packId ?? 'all packs'}`,
        `Regulatory Basis:                ${report.regulatoryBasis.join(', ')}`,
        '',
        `Total Disclosures:               ${report.totalDisclosures}`,
        `Plaintext Transport Warnings:    ${report.plaintextTransportCount}`,
        `Unattributed Recipient Events:   ${report.unattributedRecipientCount}`,
        '',
    ];
    if (report.totalDisclosures === 0) {
        lines.push('No disclosures found for this data subject in the specified period.');
        return lines.join('\n');
    }
    for (const group of report.disclosures) {
        lines.push(`--- Category: ${group.packId}::${group.categoryId} (${group.totalDisclosures} disclosures) ---`);
        for (const recip of group.byRecipient) {
            lines.push(`  Recipient: ${recip.recipientId} (${recip.recipientType})`);
            lines.push(`  Transports: ${recip.transports.join(', ')}`);
            lines.push(`  Events (${recip.count}):`);
            for (const ev of recip.events) {
                const ptWarning = ev.plaintextTransportWarning ? ' [PLAINTEXT TRANSPORT WARNING]' : '';
                const operator = ev.operatorId ? ` | operator: ${ev.operatorId}` : '';
                lines.push(`    ${ev.timestamp} | ${ev.action} | transport: ${ev.transportMechanism ?? 'unknown'}${ptWarning}${operator}`);
            }
        }
        lines.push('');
    }
    return lines.join('\n');
}
//# sourceMappingURL=disclosure-accounting.js.map