"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.recommendPatterns = recommendPatterns;
exports.explainRecommendation = explainRecommendation;
exports.recordFeedback = recordFeedback;
const similarity_engine_1 = require("../../../core/similarity-engine");
const developer_profile_1 = require("./developer-profile");
const crypto_1 = require("crypto");
function recommendPatterns(developerId, patterns, outcomesMap, allProfiles) {
    const start = Date.now();
    let profile = allProfiles.get(developerId);
    if (!profile) {
        profile = (0, developer_profile_1.buildProfile)(developerId, patterns, outcomesMap);
    }
    const similarityEngine = new similarity_engine_1.SimilarityEngine();
    const similarDevs = similarityEngine.findSimilar(developerId, allProfiles, 30);
    const similarCategories = new Set(profile.topCategories);
    for (const sd of similarDevs) {
        const dp = allProfiles.get(sd.developerId);
        if (dp) {
            for (const cat of dp.topCategories) {
                similarCategories.add(cat);
            }
        }
    }
    const candidates = [];
    for (const p of patterns) {
        const outcome = outcomesMap.get(p.patternId);
        if (!outcome)
            continue;
        if (outcome.successRate <= 0.5)
            continue;
        const categoryOk = similarCategories.size === 0 || similarCategories.has(p.category);
        if (!categoryOk)
            continue;
        const score = computeScore(p, outcome, profile);
        candidates.push({ pattern: p, outcome, score });
    }
    candidates.sort((a, b) => b.score - a.score);
    const byCategory = new Map();
    for (const c of candidates) {
        const cat = c.pattern.category;
        if (!byCategory.has(cat))
            byCategory.set(cat, []);
        byCategory.get(cat).push(c);
    }
    const diversified = [];
    for (const [, group] of byCategory) {
        diversified.push(...group.slice(0, 3));
    }
    diversified.sort((a, b) => b.score - a.score);
    const top = diversified.slice(0, 20);
    const recommendations = top.map((c) => {
        const devLangMatch = profile.languages[c.pattern.meta.language] !== undefined;
        const reasons = explainRecommendation(c.pattern, c.outcome, profile, similarDevs, devLangMatch);
        return {
            patternId: c.pattern.patternId,
            category: c.pattern.category,
            description: c.pattern.description,
            from: c.pattern.from,
            to: c.pattern.to,
            score: Math.round(c.score * 10000) / 10000,
            confidence: c.outcome.confidence,
            health: c.outcome.health,
            successRate: c.outcome.successRate,
            reasons,
        };
    });
    return {
        developerId,
        recommendations,
        generatedAt: Date.now(),
        latencyMs: Date.now() - start,
        totalCandidates: candidates.length,
    };
}
function computeScore(pattern, outcome, profile) {
    const usageCap = Math.min(outcome.usageCount / 10, 1);
    const outcomeScore = outcome.successRate * usageCap;
    const confidenceScore = outcome.confidence;
    const healthScore = outcome.health / 100;
    const projectMatch = profile.languages[pattern.meta.language] ? 0.15 : 0;
    const failurePenalty = outcome.failureRate > 0.5 ? -0.5 : 0;
    return (outcomeScore * 0.30 +
        confidenceScore * 0.25 +
        healthScore * 0.20 +
        projectMatch +
        failurePenalty);
}
function explainRecommendation(pattern, outcome, profile, similarDevs, devLangMatch) {
    const reasons = [];
    if (similarDevs.length > 0) {
        const topSim = similarDevs.slice(0, 3);
        reasons.push({
            type: 'similar_developer',
            description: `${topSim.length} similar developer${topSim.length > 1 ? 's' : ''} use this pattern category (${pattern.category})`,
            value: topSim.reduce((s, d) => s + d.score, 0) / topSim.length,
            developerCount: topSim.length,
        });
    }
    if (outcome.successRate > 0) {
        reasons.push({
            type: 'outcome_evidence',
            description: `${(outcome.successRate * 100).toFixed(0)}% success rate across ${outcome.usageCount} uses`,
            value: outcome.successRate,
            successRate: outcome.successRate,
        });
    }
    if (devLangMatch) {
        reasons.push({
            type: 'project_match',
            description: `Matches your language: ${pattern.meta.language}`,
            value: 0.15,
        });
    }
    if (outcome.confidence > 0.7) {
        reasons.push({
            type: 'high_confidence',
            description: `High confidence (${(outcome.confidence * 100).toFixed(0)}%)`,
            value: outcome.confidence,
            confidence: outcome.confidence,
        });
    }
    if (outcome.health > 70) {
        reasons.push({
            type: 'high_health',
            description: `Healthy pattern (health: ${outcome.health})`,
            value: outcome.health / 100,
            health: outcome.health,
        });
    }
    if (outcome.failureRate > 0.5) {
        reasons.push({
            type: 'failure_warning',
            description: `High failure rate (${(outcome.failureRate * 100).toFixed(0)}%)`,
            value: -outcome.failureRate,
            successRate: outcome.failureRate,
        });
    }
    return reasons;
}
function recordFeedback(store, developerId, patternId, action) {
    const event = {
        id: (0, crypto_1.randomUUID)(),
        developerId,
        patternId,
        action,
        timestamp: Date.now(),
    };
    store.recordFeedback(event);
}
//# sourceMappingURL=recommendation-engine.js.map