"use strict";
/**
 * Pricing Calculator — deterministic price estimation for agent jobs.
 *
 * No LLM needed. All calculations are pure math based on the pricing tables.
 * Use `estimateJobCost` for raw cost and `recommendPrice` for pricing guidance.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.privacyPremium = privacyPremium;
exports.estimateJobCost = estimateJobCost;
exports.calculateListedPrice = calculateListedPrice;
exports.budgetToTokens = budgetToTokens;
exports.recommendPrice = recommendPrice;
const tables_js_1 = require("./tables.js");
// ────────────────────────────────────────────
// Privacy Premium Multipliers
// ────────────────────────────────────────────
const PRIVACY_MULTIPLIERS = {
    standard: 1.0,
    private: 1.33,
    sovereign: 1.83,
};
/**
 * Apply privacy tier premium to a base price.
 *
 * @param basePrice - Base price in USD
 * @param tier - Privacy tier
 * @returns Adjusted price with privacy premium
 */
function privacyPremium(basePrice, tier) {
    return basePrice * (PRIVACY_MULTIPLIERS[tier] ?? 1.0);
}
/**
 * Estimate the raw cost of a job based on model usage and API calls.
 * Returns cost in USD.
 *
 * @param model - Model name (must match LLM_COSTS table)
 * @param inputTokens - Number of input tokens
 * @param outputTokens - Number of output tokens
 * @param additionalApis - Optional additional API costs
 * @returns Raw cost in USD
 */
function estimateJobCost(model, inputTokens, outputTokens, additionalApis) {
    // Validate token counts
    if (!Number.isFinite(inputTokens) || inputTokens < 0) {
        throw new Error(`inputTokens must be a non-negative finite number, got: ${inputTokens}`);
    }
    if (!Number.isFinite(outputTokens) || outputTokens < 0) {
        throw new Error(`outputTokens must be a non-negative finite number, got: ${outputTokens}`);
    }
    // Find model in cost table
    const modelCost = tables_js_1.LLM_COSTS.find(m => m.model === model);
    if (!modelCost) {
        throw new Error(`Unknown model: ${model}. Available: ${tables_js_1.LLM_COSTS.map(m => m.model).join(', ')}`);
    }
    // LLM cost
    const llmCost = (inputTokens / 1000) * modelCost.inputPer1k
        + (outputTokens / 1000) * modelCost.outputPer1k;
    // API costs
    let apiCost = 0;
    if (additionalApis) {
        for (const { api, count } of additionalApis) {
            if (!Number.isFinite(count) || count < 0) {
                throw new Error(`API call count for "${api}" must be a non-negative finite number, got: ${count}`);
            }
            const apiEntry = tables_js_1.API_COSTS.find(a => a.api === api);
            if (apiEntry) {
                apiCost += apiEntry.costPerRequest * count;
            }
        }
    }
    return llmCost + apiCost;
}
function calculateListedPrice(params) {
    const { model, inputTokens, outputTokens, markupPercent, additionalApis } = params;
    if (!Number.isFinite(markupPercent) || markupPercent < 1 || markupPercent > 50) {
        throw new Error(`markupPercent must be between 1 and 50, got: ${markupPercent}`);
    }
    const rawCost = estimateJobCost(model, inputTokens, outputTokens, additionalApis);
    const listedPrice = round(rawCost * (1 + markupPercent / 100), 6);
    return { rawCost: round(rawCost, 6), listedPrice, markupPercent };
}
// ────────────────────────────────────────────
// Budget to Tokens (reverse calculation)
// ────────────────────────────────────────────
function budgetToTokens(model, budgetUsd) {
    if (!Number.isFinite(budgetUsd) || budgetUsd <= 0) {
        throw new Error(`budget must be a positive finite number, got: ${budgetUsd}`);
    }
    const modelCost = tables_js_1.LLM_COSTS.find(m => m.model === model);
    if (!modelCost) {
        throw new Error(`Unknown model: ${model}. Available: ${tables_js_1.LLM_COSTS.map(m => m.model).join(', ')}`);
    }
    const blendedPer1k = (modelCost.inputPer1k + modelCost.outputPer1k) / 2;
    if (blendedPer1k <= 0) {
        throw new Error(`Model ${model} has zero cost — cannot convert budget to tokens`);
    }
    return Math.floor((budgetUsd / blendedPer1k) * 1000);
}
/**
 * Generate pricing recommendations for a job.
 *
 * Returns four price points (minimum, recommended, premium, ceiling)
 * in both USD and VRSC, with margin percentages.
 *
 * @param params - Pricing parameters
 * @returns Price recommendation with multiple tiers
 */
function recommendPrice(params) {
    const { model, inputTokens, outputTokens, category, privacyTier = 'standard', vrscUsdRate = 1.0, additionalApis, } = params;
    // Validate VRSC/USD rate
    if (vrscUsdRate <= 0 || !Number.isFinite(vrscUsdRate)) {
        throw new Error(`vrscUsdRate must be a finite positive number, got: ${vrscUsdRate}`);
    }
    // Calculate raw cost
    const rawCost = estimateJobCost(model, inputTokens, outputTokens, additionalApis);
    // Apply privacy premium to base cost
    const adjustedCost = privacyPremium(rawCost, privacyTier);
    const multiplier = PRIVACY_MULTIPLIERS[privacyTier] ?? 1.0;
    // Get markup range for category
    const markup = tables_js_1.CATEGORY_MARKUPS[category];
    if (!markup) {
        throw new Error(`Unknown category: ${category}. Available: ${Object.keys(tables_js_1.CATEGORY_MARKUPS).join(', ')}`);
    }
    // Calculate price points
    // Minimum: seller needs adjustedCost after platform deducts PLATFORM_FEE from listed price
    // If listed = adjustedCost / (1 - fee), seller receives listed * (1 - fee) = adjustedCost
    if (tables_js_1.PLATFORM_FEE >= 1) {
        throw new Error('PLATFORM_FEE must be less than 1 (100%)');
    }
    const minUsd = adjustedCost / (1 - tables_js_1.PLATFORM_FEE);
    // Recommended: midpoint of category markup
    const midMarkup = (markup.min + markup.max) / 2;
    const recUsd = adjustedCost * midMarkup;
    // Premium: high end of category
    const premUsd = adjustedCost * markup.max;
    // Ceiling: 1.5x the premium (absolute max reasonable)
    const ceilUsd = premUsd * 1.5;
    const makePricePoint = (usd) => ({
        usd: round(usd, 6),
        vrsc: round(usd / vrscUsdRate, 6),
        marginPercent: adjustedCost > 0 ? round(((usd - adjustedCost) / adjustedCost) * 100, 1) : 0,
    });
    return {
        rawCost: round(rawCost, 6),
        platformFee: round(adjustedCost * tables_js_1.PLATFORM_FEE, 6),
        privacyMultiplier: multiplier,
        minimum: makePricePoint(minUsd),
        recommended: makePricePoint(recUsd),
        premium: makePricePoint(premUsd),
        ceiling: makePricePoint(ceilUsd),
    };
}
// ────────────────────────────────────────────
// Helpers
// ────────────────────────────────────────────
function round(n, decimals) {
    const factor = Math.pow(10, decimals);
    return Math.round(n * factor) / factor;
}
//# sourceMappingURL=calculator.js.map