// engine/estimator/calculations.ts — Token, cost, model, and strategy calculations
// SPEC-460: No invented token counts. Cost from real pricing only.
import { roundTo } from '../estimator-helpers.js';
import { DEFAULT_CONFIG, BASE_HOURS_BY_TYPE, SCOPE_MULTIPLIER, DIFFICULTY_MULTIPLIER, REVIEW_RATIO, } from './constants.js';
import { resolvePricing } from '../llm-runtime/index.js';
// === Model selection ===
export function determineRecommendedModel(difficulty, scope) {
    if (difficulty >= 4 || scope === 'architectural') {
        return 'opus';
    }
    if (difficulty <= 2 && (scope === 'trivial' || scope === 'feature')) {
        return 'sonnet';
    }
    return 'mixed';
}
// === Token strategy ===
export function determineTokenStrategy(type, scope, difficulty) {
    if (scope === 'trivial' && difficulty <= 2) {
        return {
            mode: 'template',
            reasoning: `Simple ${type} with trivial scope can use template-based generation to minimize token usage.`,
            estimatedTokens: 0,
            savings: '~70% vs full-llm',
        };
    }
    if (difficulty <= 2 && type !== 'project') {
        return {
            mode: 'light-llm',
            reasoning: `Low difficulty ${type} works well with Sonnet-only approach for cost efficiency.`,
            estimatedTokens: 0,
            savings: '~40% vs full-llm',
        };
    }
    if (difficulty >= 4 || scope === 'architectural') {
        return {
            mode: 'full-llm',
            reasoning: `High difficulty (${String(difficulty)}/5) with ${scope} scope requires Opus-level reasoning for correctness.`,
            estimatedTokens: 0,
            savings: 'none — quality prioritized',
        };
    }
    return {
        mode: 'local',
        reasoning: `Medium complexity ${type} benefits from local analysis augmented with targeted LLM calls.`,
        estimatedTokens: 0,
        savings: '~50% vs full-llm',
    };
}
// === API cost from real pricing ===
export function calculateApiCost(config) {
    // If user has configured pricing explicitly, use that
    if (config.pricingOpusPerMToken > 0 || config.pricingSonnetPerMToken > 0) {
        return 0; // Can't calculate without real token counts
    }
    // Try to resolve from model-pricing.json
    const pricing = resolvePricing();
    if (!pricing) {
        return 0; // No model detected — don't invent costs
    }
    // We don't have real token counts at estimation time — only after execution
    // So API cost at estimation = 0 (will be filled with real data in actuals)
    return 0;
}
// === Core estimation ===
/**
 * Calculate estimation. Token and cost fields are 0 when not measurable.
 * Real values come from: session token tracker (SPEC-460) + pricing-resolver.
 */
export function calculateEstimation(type, scope, difficulty, config = {}) {
    const cfg = { ...DEFAULT_CONFIG, ...config };
    const baseHours = BASE_HOURS_BY_TYPE[type];
    const scopeMult = SCOPE_MULTIPLIER[scope];
    const safeDifficulty = Math.max(1, Math.min(5, difficulty));
    const diffMult = DIFFICULTY_MULTIPLIER[safeDifficulty];
    const devHours = roundTo(baseHours * scopeMult * diffMult, 1);
    const reviewHours = roundTo(devHours * REVIEW_RATIO[safeDifficulty], 1);
    const tokenStrategy = determineTokenStrategy(type, scope, difficulty);
    const recommendedModel = determineRecommendedModel(difficulty, scope);
    // Token counts: 0 at estimation time. Real counts come from session tracker.
    const tokensOpus = 0;
    const tokensSonnet = 0;
    // API cost: 0 at estimation time. Real cost computed from actual tokens × real pricing.
    const apiCostUsd = 0;
    // Human cost: only if hourlyRate is configured (> 0)
    const humanCostUsd = cfg.hourlyRate > 0 ? roundTo((devHours + reviewHours) * cfg.hourlyRate, 2) : 0;
    const totalCostUsd = roundTo(apiCostUsd + humanCostUsd, 2);
    return {
        devHours,
        reviewHours,
        recommendedModel,
        tokensOpus,
        tokensSonnet,
        apiCostUsd,
        hourlyRate: cfg.hourlyRate,
        humanCostUsd,
        totalCostUsd,
        tokenOptimization: tokenStrategy,
    };
}
//# sourceMappingURL=calculations.js.map