// engine/estimator/calculations.ts — Token, cost, model, and strategy calculations
import { roundTo } from '../estimator-helpers.js';
import { DEFAULT_CONFIG, BASE_HOURS_BY_TYPE, SCOPE_MULTIPLIER, DIFFICULTY_MULTIPLIER, REVIEW_RATIO, TOKENS_PER_DEV_HOUR, MODE_REDUCTION, } from './constants.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, devHours) {
    if (scope === 'trivial' && difficulty <= 2) {
        return {
            mode: 'template',
            reasoning: `Simple ${type} with trivial scope can use template-based generation to minimize token usage.`,
            estimatedTokens: Math.round(devHours * TOKENS_PER_DEV_HOUR.sonnet * 0.3),
            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: Math.round(devHours * TOKENS_PER_DEV_HOUR.sonnet * 0.6),
            savings: '~40% vs full-llm',
        };
    }
    if (difficulty >= 4 || scope === 'architectural') {
        return {
            mode: 'full-llm',
            reasoning: `High difficulty (${difficulty}/5) with ${scope} scope requires Opus-level reasoning for correctness.`,
            estimatedTokens: Math.round(devHours * TOKENS_PER_DEV_HOUR.opus),
            savings: 'none — quality prioritized',
        };
    }
    return {
        mode: 'local',
        reasoning: `Medium complexity ${type} benefits from local analysis augmented with targeted LLM calls.`,
        estimatedTokens: Math.round(devHours * TOKENS_PER_DEV_HOUR.sonnet * 0.5),
        savings: '~50% vs full-llm',
    };
}
// === Token counts ===
export function calculateTokens(devHours, model, mode) {
    const factor = MODE_REDUCTION[mode];
    const baseOpus = devHours * TOKENS_PER_DEV_HOUR.opus;
    const baseSonnet = devHours * TOKENS_PER_DEV_HOUR.sonnet;
    switch (model) {
        case 'opus':
            return {
                tokensOpus: Math.round(baseOpus * factor),
                tokensSonnet: Math.round(baseSonnet * factor * 0.2),
            };
        case 'sonnet':
            return {
                tokensOpus: 0,
                tokensSonnet: Math.round(baseSonnet * factor),
            };
        case 'mixed':
            return {
                tokensOpus: Math.round(baseOpus * factor * 0.4),
                tokensSonnet: Math.round(baseSonnet * factor * 0.6),
            };
    }
}
// === API cost ===
export function calculateApiCost(tokensOpus, tokensSonnet, config) {
    const opusCost = (tokensOpus / 1_000_000) * config.pricingOpusPerMToken;
    const sonnetCost = (tokensSonnet / 1_000_000) * config.pricingSonnetPerMToken;
    return roundTo(opusCost + sonnetCost, 2);
}
// === Core estimation ===
/**
 * Calculate raw estimation without historical adjustment.
 * Useful for new projects with no history.
 */
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 diffMult = DIFFICULTY_MULTIPLIER[difficulty];
    const devHours = roundTo(baseHours * scopeMult * diffMult, 1);
    const reviewHours = roundTo(devHours * REVIEW_RATIO[difficulty], 1);
    const tokenStrategy = determineTokenStrategy(type, scope, difficulty, devHours);
    const recommendedModel = determineRecommendedModel(difficulty, scope);
    const { tokensOpus, tokensSonnet } = calculateTokens(devHours, recommendedModel, tokenStrategy.mode);
    const apiCostUsd = calculateApiCost(tokensOpus, tokensSonnet, cfg);
    const humanCostUsd = roundTo((devHours + reviewHours) * cfg.hourlyRate, 2);
    const totalCostUsd = roundTo(apiCostUsd + humanCostUsd, 2);
    return {
        devHours,
        reviewHours,
        recommendedModel,
        tokensOpus,
        tokensSonnet,
        apiCostUsd,
        hourlyRate: cfg.hourlyRate,
        humanCostUsd,
        totalCostUsd,
        tokenOptimization: tokenStrategy,
    };
}
//# sourceMappingURL=calculations.js.map