/**
 * vertical-group-catalog.ts — Vertical group pack catalog computation.
 *
 * Thomas Layer 0 directive 2026-05-22 00:10 (FINAL canonical pricing model):
 *
 * Customers MUST buy a vertical group pack first.
 * A "group" = vertical × jurisdiction derived from the ACTIVE_PACKS registry.
 *
 * Group pricing is tiered by pack count:
 *   4 packs in group  → $4,000 / yr
 *   5 packs in group  → $5,000 / yr
 *   6 packs in group  → $6,000 / yr
 *   7+ packs in group → $7,000 / yr (auto-cap, includes full 143-pack catalog)
 *
 * After group purchase, individual add-ons from packs OUTSIDE the customer's
 * group are available at $400 / yr each.
 *
 * Hard billing cap: $7,000 / yr per customer. At-cap → full 143-pack catalog unlocked.
 *
 * @connexum/ai-governance
 */
import { getPacksByStatus } from './registry-expanded.js';
/**
 * Active packs + draft packs — the source of truth for group computation.
 *
 * Draft packs are content-complete packs pending Vera (Legal & Compliance) citation
 * review before promotion to ACTIVE. They appear in the catalog and in the
 * healthcare-us group (so the $7,000/yr group pricing is correct) but the
 * dashboard surfaces them with a "Coming Soon — In Verification" badge.
 * Draft-vs-active badge UI is Phase 2 of SE Blocker #1 RFC.
 *
 * SE Blocker #2 (2026-05-24): 6 Hospital pack drafts added to healthcare-us group.
 */
export const ACTIVE_PACKS = [
    ...getPacksByStatus('ACTIVE'),
    ...getPacksByStatus('draft'),
];
// ---------------------------------------------------------------------------
// Pricing constants
// ---------------------------------------------------------------------------
/** Hard annual billing cap per customer. At-cap → full 143-pack catalog unlocked. */
export const BILLING_CAP_USD = 7_000;
/** Per-pack add-on annual price (packs OUTSIDE the customer's purchased group). */
export const ADDON_PRICE_ANNUAL_USD = 400;
// ---------------------------------------------------------------------------
// Pricing formula
// ---------------------------------------------------------------------------
/**
 * Compute the annual group price given the number of packs in the group.
 *
 * Thomas directive 2026-05-22 00:10:
 *   - 1-3 packs: $1,000/pack (smaller groups, linear)
 *   - 4 packs: $4,000
 *   - 5 packs: $5,000
 *   - 6 packs: $6,000
 *   - 7+:       $7,000 (auto-cap)
 */
export function priceForGroupSize(packCount) {
    if (packCount <= 0)
        return 0;
    if (packCount <= 3)
        return packCount * 1_000;
    if (packCount === 4)
        return 4_000;
    if (packCount === 5)
        return 5_000;
    if (packCount === 6)
        return 6_000;
    return 7_000; // 7+ auto-caps at $7k (full-catalog unlock price)
}
// ---------------------------------------------------------------------------
// Group computation
// ---------------------------------------------------------------------------
/**
 * Derive a stable slug-safe group key from vertical and jurisdiction strings.
 * e.g. "Healthcare" + "US" → "healthcare-us"
 *      "Financial Services" + "EU" → "financial-services-eu"
 */
function toGroupKey(vertical, jurisdiction) {
    const slug = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
    return `${slug(vertical)}-${slug(jurisdiction)}`;
}
/**
 * Compute all vertical groups from the ACTIVE_PACKS catalog.
 *
 * Groups are keyed on (vertical × jurisdiction). Each group carries:
 *  - the full list of packs in that group
 *  - the computed annual price based on pack count
 *
 * Sorted descending by pack count so the largest (most value) groups appear first.
 */
export function computeVerticalGroups() {
    const groups = new Map();
    for (const pack of ACTIVE_PACKS) {
        const key = toGroupKey(pack.vertical, pack.jurisdiction);
        const arr = groups.get(key) ?? [];
        arr.push(pack);
        groups.set(key, arr);
    }
    return Array.from(groups.entries())
        .filter(([, packs]) => packs.length >= 1)
        .map(([groupKey, packs]) => {
        const representative = packs[0];
        const count = packs.length;
        // Build a partial group first so bundledLicensedPacks can inspect packs[].
        const partialGroup = {
            groupKey,
            vertical: representative.vertical,
            jurisdiction: representative.jurisdiction,
            displayName: `${representative.jurisdiction} ${representative.vertical}`,
            description: `Complete compliance coverage for ${representative.vertical} operations in ` +
                `${representative.jurisdiction}. Includes ${count} regulatory framework${count === 1 ? '' : 's'}.`,
            packs,
            priceAnnualUsd: priceForGroupSize(count),
        };
        return {
            ...partialGroup,
            includedBaselinePacks: bundledLicensedPacks(partialGroup),
        };
    })
        .sort((a, b) => b.packs.length - a.packs.length);
}
// ---------------------------------------------------------------------------
// Bundle-eligibility helpers (licensing-layer only)
//
// **Licensing-layer only.** Customer who licenses this group gets these packs
// licensed too (free, capability-bundling). Per-agent BINDING + per-rule
// VERIFICATION remain explicit customer actions in the wizard.
// ---------------------------------------------------------------------------
/**
 * EU member state jurisdiction strings recognised for GDPR bundling.
 * Matches on the full jurisdiction string (case-insensitive substring check
 * against known EU jurisdiction labels in the pack registry).
 */
const EU_JURISDICTION_PATTERNS = [
    'eu',
    'global',
    'international',
    'germany',
    'france',
    'italy',
    'spain',
    'netherlands',
    'belgium',
    'ireland',
    'austria',
    'sweden',
    'denmark',
    'finland',
    'poland',
    'czech republic',
    'portugal',
    'greece',
    'hungary',
    'romania',
    'bulgaria',
];
/**
 * Returns true for every group — ISO 27001 is a universal baseline licensed
 * with every group pack purchase.
 *
 * **Licensing-layer only.** The customer still must explicitly bind ISO 27001
 * to a specific agent and verify per-rule actions in the wizard.
 */
export function groupBundlesIso27001(_group) {
    return true;
}
/**
 * Returns true when the group's jurisdiction covers the EU or an EU member
 * state, in which case GDPR is bundled with the group license at no extra cost.
 *
 * **Licensing-layer only.** The customer still must explicitly bind GDPR
 * to a specific agent and verify per-rule actions in the wizard.
 */
export function groupBundlesGdpr(group) {
    const j = group.jurisdiction.toLowerCase();
    return EU_JURISDICTION_PATTERNS.some((pattern) => j.includes(pattern));
}
/**
 * Returns the list of pack IDs that are licensed for free with the given
 * group pack purchase.
 *
 * Always includes 'iso27001'. Also includes 'gdpr' when the group's
 * jurisdiction is EU / Global / International or an EU member state.
 *
 * Filters out any pack IDs already present in group.packs[] so that primary
 * group packs are never listed again as bundled extras.
 *
 * **Licensing-layer only.** Customer who licenses this group gets these packs
 * licensed too (free, capability-bundling). Per-agent BINDING + per-rule
 * VERIFICATION remain explicit customer actions in the wizard.
 */
export function bundledLicensedPacks(group) {
    const primaryIds = new Set(group.packs.map((p) => p.id));
    const bundles = [];
    if (groupBundlesIso27001(group) && !primaryIds.has('iso27001')) {
        bundles.push('iso27001');
    }
    if (groupBundlesGdpr(group) && !primaryIds.has('gdpr')) {
        bundles.push('gdpr');
    }
    return bundles;
}
// ---------------------------------------------------------------------------
// Lookup helpers
// ---------------------------------------------------------------------------
/**
 * Given a pack ID, find the group it belongs to.
 * Returns null if the pack is not found in any group.
 */
export function findGroupForPack(packId, groups) {
    const catalog = groups ?? computeVerticalGroups();
    for (const group of catalog) {
        if (group.packs.some((p) => p.id === packId)) {
            return group;
        }
    }
    return null;
}
//# sourceMappingURL=vertical-group-catalog.js.map