/**
 * Cost Estimator - AI execution cost estimation
 *
 * Estimates the cost of autonomous workflow execution based on
 * AI API calls, task count, and complexity.
 *
 * Part of increment 0039: Ultra-Smart Next Command
 *
 * @module core/workflow/cost-estimator
 * @since v0.22.0
 */
import * as fs from '../../utils/fs-native.js';
import * as path from 'path';
/**
 * Risk level for cost
 */
export var RiskLevel;
(function (RiskLevel) {
    /** < $1 */
    RiskLevel["LOW"] = "low";
    /** $1 - $5 */
    RiskLevel["MEDIUM"] = "medium";
    /** $5 - $20 */
    RiskLevel["HIGH"] = "high";
    /** > $20 */
    RiskLevel["CRITICAL"] = "critical";
})(RiskLevel || (RiskLevel = {}));
/**
 * Cost Estimator - Estimate autonomous execution costs
 */
export class CostEstimator {
    constructor(config = {}) {
        this.costPerCall = config.costPerCall || 0.01;
        this.lowThreshold = config.lowThreshold || 1.0;
        this.mediumThreshold = config.mediumThreshold || 5.0;
        this.highThreshold = config.highThreshold || 20.0;
    }
    /**
     * Estimate cost for increment execution
     *
     * @param incrementPath - Path to increment directory
     * @returns Cost estimate
     */
    async estimateIncrement(incrementPath) {
        const breakdown = [];
        let totalCost = 0;
        const planningCost = this.estimatePlanning();
        breakdown.push(planningCost);
        totalCost += planningCost.cost;
        // Execution phase: Based on task count
        const executionCost = await this.estimateExecution(incrementPath);
        breakdown.push(executionCost);
        totalCost += executionCost.cost;
        // Validation phase: 1 AI call (PM validation)
        const validationCost = this.estimateValidation();
        breakdown.push(validationCost);
        totalCost += validationCost.cost;
        // QA phase: 1 AI call (judge LLM)
        const qaCost = this.estimateQA();
        breakdown.push(qaCost);
        totalCost += qaCost.cost;
        // Determine risk level
        const riskLevel = this.determineRiskLevel(totalCost);
        // Calculate confidence based on data availability
        const confidence = await this.calculateConfidence(incrementPath);
        return {
            estimatedCost: totalCost,
            breakdown,
            riskLevel,
            explanation: this.generateExplanation(totalCost, riskLevel, breakdown),
            confidence
        };
    }
    /**
     * Estimate planning cost (Architect + Planner = 2 calls)
     */
    estimatePlanning() {
        return {
            phase: 'Planning',
            aiCalls: 2,
            cost: 2 * this.costPerCall
        };
    }
    /**
     * Estimate execution cost based on task count
     */
    async estimateExecution(incrementPath) {
        const tasksPath = path.join(incrementPath, 'tasks.md');
        let taskCount = 0;
        // Try to count tasks from tasks.md
        if (await fs.pathExists(tasksPath)) {
            try {
                const content = await fs.readFile(tasksPath, 'utf-8');
                // Count task headers (#### T-XXX:)
                const taskMatches = content.match(/^####\s+T-\d+:/gm);
                taskCount = taskMatches ? taskMatches.length : 0;
            }
            catch (error) {
                // If can't read tasks, estimate based on spec
                taskCount = 10; // Default estimate
            }
        }
        else {
            // No tasks.md yet, estimate from spec.md
            taskCount = await this.estimateTasksFromSpec(incrementPath);
        }
        // Assume 3 AI calls per task (avg: simple=1, medium=3, complex=5)
        const aiCalls = taskCount * 3;
        return {
            phase: 'Execution',
            aiCalls,
            cost: aiCalls * this.costPerCall
        };
    }
    /**
     * Estimate task count from spec.md
     */
    async estimateTasksFromSpec(incrementPath) {
        const specPath = path.join(incrementPath, 'spec.md');
        if (!await fs.pathExists(specPath)) {
            return 10; // Default estimate
        }
        try {
            const content = await fs.readFile(specPath, 'utf-8');
            // Count acceptance criteria as rough proxy for tasks
            const acMatches = content.match(/^- \[.\] AC-/gm);
            const acCount = acMatches ? acMatches.length : 0;
            // Rough heuristic: 2 ACs ≈ 1 task
            return Math.max(Math.floor(acCount / 2), 5);
        }
        catch (error) {
            return 10;
        }
    }
    /**
     * Estimate validation cost
     */
    estimateValidation() {
        // Validation = 1 PM validation call
        return {
            phase: 'Validation',
            aiCalls: 1,
            cost: 1 * this.costPerCall
        };
    }
    /**
     * Estimate QA cost
     */
    estimateQA() {
        // QA = 1 judge LLM call
        return {
            phase: 'QA',
            aiCalls: 1,
            cost: 1 * this.costPerCall
        };
    }
    /**
     * Determine risk level based on total cost
     */
    determineRiskLevel(cost) {
        if (cost < this.lowThreshold)
            return RiskLevel.LOW;
        if (cost < this.mediumThreshold)
            return RiskLevel.MEDIUM;
        if (cost < this.highThreshold)
            return RiskLevel.HIGH;
        return RiskLevel.CRITICAL;
    }
    /**
     * Calculate confidence in estimate based on available files
     */
    async calculateConfidence(incrementPath) {
        const tasksExists = await fs.pathExists(path.join(incrementPath, 'tasks.md'));
        const planExists = await fs.pathExists(path.join(incrementPath, 'plan.md'));
        const specExists = await fs.pathExists(path.join(incrementPath, 'spec.md'));
        if (tasksExists && planExists)
            return 0.9;
        if (specExists)
            return 0.6;
        return 0.3;
    }
    /**
     * Generate human-readable explanation
     */
    generateExplanation(totalCost, riskLevel, breakdown) {
        const parts = [];
        parts.push(`Estimated cost: $${totalCost.toFixed(2)} (Risk: ${riskLevel.toUpperCase()})`);
        parts.push('\nBreakdown:');
        breakdown.forEach(item => {
            parts.push(`  - ${item.phase}: ${item.aiCalls} AI calls ($${item.cost.toFixed(2)})`);
        });
        if (riskLevel === RiskLevel.CRITICAL) {
            parts.push('\n⚠️  CRITICAL: Cost exceeds $20. Consider manual execution or splitting work.');
        }
        else if (riskLevel === RiskLevel.HIGH) {
            parts.push('\n⚠️  HIGH: Cost is significant ($5-$20). Confirm before proceeding.');
        }
        return parts.join('\n');
    }
    /**
     * Check if cost exceeds threshold
     *
     * @param estimate - Cost estimate
     * @returns True if cost exceeds HIGH threshold
     */
    checkThreshold(estimate) {
        return estimate.riskLevel === RiskLevel.HIGH || estimate.riskLevel === RiskLevel.CRITICAL;
    }
}
//# sourceMappingURL=cost-estimator.js.map