"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDataAtLevel = getDataAtLevel;
exports.validateNoLeakage = validateNoLeakage;
exports.composeTeamStyle = composeTeamStyle;
exports.detectKnowledgeSilos = detectKnowledgeSilos;
exports.calculateBusFactor = calculateBusFactor;
exports.suggestKnowledgeTransfer = suggestKnowledgeTransfer;
exports.generateOnboardingDoc = generateOnboardingDoc;
exports.analyzeReviewPatterns = analyzeReviewPatterns;
exports.suggestPRReview = suggestPRReview;
exports.getTeamHealth = getTeamHealth;
exports.generateSprintRetro = generateSprintRetro;
exports.generateHandoff = generateHandoff;
const database_1 = require("../../06-memory/database/database");
// ─── 3-Level Data Separation ────────────────────────────────────────────────
function getDataAtLevel(level, project) {
    (0, database_1.initializeDatabase)();
    const db = (0, database_1.getDb)();
    if (level === 'personal') {
        const profile = db.prepare('SELECT * FROM user_profile WHERE id = 1').get();
        const sessions = db.prepare('SELECT COUNT(*) as count FROM sessions').get();
        const decisions = db.prepare('SELECT * FROM decisions ORDER BY created_at DESC LIMIT 10').all();
        return {
            level: 'personal',
            profile: profile || null,
            totalSessions: sessions.count,
            recentDecisions: decisions,
            note: 'This data is YOURS only — never shared with team or community',
        };
    }
    if (level === 'team') {
        const members = db.prepare('SELECT * FROM collaborators ORDER BY commit_count DESC').all();
        const silos = db.prepare('SELECT * FROM silos WHERE risk_level = ?').all('high');
        const teamSessions = db.prepare('SELECT tool_name, COUNT(*) as count FROM sessions GROUP BY tool_name').all();
        return {
            level: 'team',
            members,
            highRiskSilos: silos,
            toolUsage: teamSessions,
            note: 'Team data — visible to all team members',
        };
    }
    // community
    const signals = db.prepare('SELECT * FROM community_signals ORDER BY frequency DESC LIMIT 20').all();
    const trends = db.prepare('SELECT trend, COUNT(*) as count FROM community_signals GROUP BY trend').all();
    return {
        level: 'community',
        topSignals: signals,
        trends,
        note: 'Anonymous community data — no PII, 300-byte max payload',
    };
}
function validateNoLeakage(fromLevel, toLevel) {
    const forbidden = {
        personal: ['team', 'community'],
        team: ['community'],
        community: [],
    };
    if (forbidden[fromLevel].includes(toLevel)) {
        return {
            safe: false,
            reason: `Data leakage detected: ${fromLevel} data must NOT be shared with ${toLevel} level`,
        };
    }
    return { safe: true, reason: 'Data flow is safe' };
}
// ─── Team Style Composer ─────────────────────────────────────────────────────
function composeTeamStyle(project) {
    const db = (0, database_1.getDb)();
    const patterns = db.prepare(project
        ? "SELECT rule, category, confidence FROM patterns WHERE project = ? ORDER BY confidence DESC LIMIT 20"
        : "SELECT rule, category, confidence FROM patterns ORDER BY confidence DESC LIMIT 20").all(...(project ? [project] : []));
    const languages = db.prepare('SELECT language, file_count FROM skills ORDER BY file_count DESC LIMIT 5').all();
    const sessions = db.prepare('SELECT files_touched FROM sessions WHERE end_time IS NOT NULL LIMIT 20').all();
    let totalFiles = 0;
    let fileCount = 0;
    for (const s of sessions) {
        try {
            const files = JSON.parse(s.files_touched);
            totalFiles += files.length;
            fileCount++;
        }
        catch { /* skip */ }
    }
    const testFiles = db.prepare("SELECT COUNT(DISTINCT file_path) as cnt FROM behavior_events WHERE file_path LIKE '%.test.%' OR file_path LIKE '%.spec.%'").get();
    const totalSourceFiles = db.prepare("SELECT COUNT(DISTINCT file_path) as cnt FROM behavior_events").get();
    const testRatio = totalSourceFiles.cnt > 0 ? testFiles.cnt / totalSourceFiles.cnt : 0;
    const hasReview = db.prepare("SELECT COUNT(*) as cnt FROM behavior_events WHERE event_type = 'review'").get();
    return {
        languages: languages.map(l => l.language),
        patterns: patterns.slice(0, 10).map(p => p.rule.slice(0, 80)),
        conventions: patterns.filter(p => p.category === 'convention').map(p => p.rule.slice(0, 80)),
        avgFileSize: fileCount > 0 ? Math.round(totalFiles / fileCount) : 0,
        testCoverage: testRatio >= 0.5 ? 'high' : testRatio >= 0.2 ? 'medium' : testRatio > 0 ? 'low' : 'none',
        codeReviewStyle: hasReview.cnt > 10 ? 'thorough' : hasReview.cnt > 0 ? 'light' : 'none',
        description: `Team uses ${languages.map(l => l.language).join(', ') || 'unknown stack'} with ${patterns.length} learned patterns`,
    };
}
// ─── Knowledge Transfer ──────────────────────────────────────────────────────
function detectKnowledgeSilos() {
    const db = (0, database_1.getDb)();
    const silos = [];
    const dbSilos = db.prepare('SELECT * FROM silos ORDER BY risk_level DESC').all();
    for (const s of dbSilos) {
        const members = safeJson(String(s.members || '[]')) || [];
        silos.push({
            name: String(s.name || ''),
            members,
            knowledgeArea: String(s.knowledge_area || ''),
            riskLevel: String(s.risk_level || 'low'),
            busFactor: Number(s.bus_factor || 1),
            description: `Knowledge area "${s.name}" known by ${members.length} members (bus factor: ${s.bus_factor})`,
        });
    }
    const collaborators = db.prepare('SELECT name, skills FROM collaborators WHERE skills IS NOT NULL').all();
    const skillMap = new Map();
    for (const c of collaborators) {
        const skills = safeJson(c.skills) || [];
        for (const skill of skills) {
            if (!skillMap.has(skill))
                skillMap.set(skill, []);
            skillMap.get(skill).push(c.name);
        }
    }
    for (const [skill, experts] of skillMap) {
        if (experts.length === 1) {
            const existing = silos.find(s => s.knowledgeArea === skill);
            if (!existing) {
                silos.push({
                    name: `${skill} Expert`,
                    members: experts,
                    knowledgeArea: skill,
                    riskLevel: 'high',
                    busFactor: 1,
                    description: `"${skill}" is known only to ${experts[0]} — single point of failure`,
                });
            }
        }
    }
    return silos.sort((a, b) => {
        const riskOrder = { high: 3, medium: 2, low: 1 };
        return (riskOrder[b.riskLevel] || 0) - (riskOrder[a.riskLevel] || 0);
    });
}
function calculateBusFactor() {
    const db = (0, database_1.getDb)();
    const collaborators = db.prepare('SELECT name, commit_count, skills, collaboration_score FROM collaborators ORDER BY commit_count DESC').all();
    const members = collaborators.map(c => {
        const skills = safeJson(c.skills) || [];
        const score = Math.min(100, Math.round((c.commit_count * 2) + (c.collaboration_score * 30)));
        return {
            name: c.name,
            score,
            criticalAreas: skills.slice(0, 5),
            risk: score >= 70 ? 'high' : score >= 40 ? 'medium' : 'low',
        };
    });
    const overallScore = members.length > 0
        ? Math.round(members.reduce((sum, m) => sum + m.score, 0) / members.length)
        : 0;
    const singlePointsOfFailure = members
        .filter(m => m.criticalAreas.length > 0 && m.risk === 'high')
        .map(m => `${m.name} (${m.criticalAreas.join(', ')})`);
    return { overallScore, members, singlePointsOfFailure };
}
function suggestKnowledgeTransfer() {
    const suggestions = [];
    const silos = detectKnowledgeSilos();
    const db = (0, database_1.getDb)();
    const members = db.prepare('SELECT name FROM collaborators ORDER BY commit_count DESC').all();
    const memberNames = members.map(m => m.name);
    for (const silo of silos) {
        if (silo.riskLevel === 'high' && silo.members.length === 1) {
            const expert = silo.members[0];
            const learners = memberNames.filter(n => n !== expert).slice(0, 2);
            for (const learner of learners) {
                suggestions.push({
                    area: silo.knowledgeArea,
                    from: expert,
                    to: learner,
                    priority: 'high',
                });
            }
        }
    }
    return suggestions;
}
// ─── Onboarding Assistant ────────────────────────────────────────────────────
function generateOnboardingDoc(teamName, project) {
    const db = (0, database_1.getDb)();
    const style = composeTeamStyle(project);
    const silos = detectKnowledgeSilos();
    const busFactor = calculateBusFactor();
    const members = db.prepare('SELECT name, skills, commit_count FROM collaborators ORDER BY commit_count DESC LIMIT 5').all();
    const keyMembers = members.map(m => ({
        name: m.name,
        expertise: safeJson(m.skills) || [],
    }));
    const commonBugs = db.prepare("SELECT description, COUNT(*) as cnt FROM behavior_events WHERE event_type = 'bug_fix' GROUP BY description ORDER BY cnt DESC LIMIT 5").all();
    const whoToAsk = keyMembers.slice(0, 4).map(m => ({
        area: m.expertise[0] || 'general',
        person: m.name,
    }));
    return {
        teamName,
        generatedAt: new Date().toISOString(),
        stack: style.languages,
        patterns: style.patterns.slice(0, 5),
        commonBugs: commonBugs.map(b => b.description.slice(0, 80)),
        keyMembers,
        styleGuide: style.description,
        firstWeekTasks: [
            'Set up local dev environment',
            'Read team style guide',
            'Review top 3 patterns in the codebase',
            'Pair with a team member on a small task',
            'Submit first PR with team review',
        ],
        whoToAsk,
    };
}
// ─── Code Review Intelligence ────────────────────────────────────────────────
function analyzeReviewPatterns() {
    const db = (0, database_1.getDb)();
    const insights = [];
    const reviewers = db.prepare("SELECT name, commit_count FROM collaborators ORDER BY commit_count DESC LIMIT 10").all();
    for (const r of reviewers) {
        const reviewBugs = db.prepare("SELECT description FROM behavior_events WHERE event_type = 'bug_fix' AND project IN (SELECT project FROM collaborators WHERE name = ?)").all(r.name);
        const nitpickRate = Math.min(1, reviewBugs.length / Math.max(1, r.commit_count));
        const approvalRate = Math.max(0.3, 1 - nitpickRate);
        const commonIssues = [...new Set(reviewBugs.map(b => b.description.slice(0, 50)))].slice(0, 3);
        let style = 'balanced';
        if (nitpickRate > 0.6)
            style = 'thorough';
        else if (nitpickRate < 0.2)
            style = 'light';
        insights.push({
            reviewer: r.name,
            style,
            nitpickRate: Math.round(nitpickRate * 100) / 100,
            approvalRate: Math.round(approvalRate * 100) / 100,
            commonIssues,
            strength: style === 'thorough' ? 'Catches edge cases early' : style === 'light' ? 'Keeps momentum going' : 'Good balance of quality and speed',
            suggestion: style === 'thorough' ? 'Consider being less nitpicky on minor issues to keep PR cycle time low' : style === 'light' ? 'Consider adding more thorough reviews for critical paths' : 'Maintain current balanced approach',
        });
    }
    return insights;
}
function suggestPRReview(filePaths) {
    const suggestions = [];
    const db = (0, database_1.getDb)();
    for (const file of filePaths) {
        const bugs = db.prepare("SELECT description, COUNT(*) as cnt FROM behavior_events WHERE file_path = ? AND event_type = 'bug_fix' GROUP BY description ORDER BY cnt DESC LIMIT 3").all(file);
        if (bugs.length > 0) {
            suggestions.push(`⚠ ${file}: Historical bugs — ${bugs.map(b => b.description.slice(0, 40)).join('; ')}`);
        }
        const isTest = /\.(test|spec)\./.test(file);
        if (!isTest && (file.endsWith('.ts') || file.endsWith('.js'))) {
            const hasTryCatch = db.prepare("SELECT COUNT(*) as cnt FROM behavior_events WHERE file_path = ? AND description LIKE '%null%' OR description LIKE '%undefined%'").get(file);
            if (hasTryCatch.cnt > 0) {
                suggestions.push(`🔍 ${file}: Check for null/undefined safety — historical issue`);
            }
        }
    }
    return suggestions;
}
// ─── Team Health ─────────────────────────────────────────────────────────────
function getTeamHealth(project) {
    const busFactor = calculateBusFactor();
    const silos = detectKnowledgeSilos();
    const style = composeTeamStyle(project);
    const highRiskSilos = silos.filter(s => s.riskLevel === 'high');
    const singlePoints = busFactor.singlePointsOfFailure;
    const skillGaps = [];
    if (style.testCoverage === 'none' || style.testCoverage === 'low')
        skillGaps.push('Testing');
    if (style.codeReviewStyle === 'none')
        skillGaps.push('Code Review');
    if (highRiskSilos.length > 0)
        skillGaps.push(...highRiskSilos.map(s => s.knowledgeArea));
    const strengths = [];
    if (style.testCoverage === 'high')
        strengths.push('Strong test coverage');
    if (style.codeReviewStyle === 'thorough')
        strengths.push('Thorough code reviews');
    if (busFactor.overallScore >= 60)
        strengths.push('Good bus factor distribution');
    if (highRiskSilos.length === 0)
        strengths.push('No critical knowledge silos');
    const recommendations = [];
    if (singlePoints.length > 0)
        recommendations.push(`Knowledge transfer needed: ${singlePoints.join(', ')}`);
    if (highRiskSilos.length > 0)
        recommendations.push(`${highRiskSilos.length} high-risk knowledge silos detected`);
    if (style.testCoverage === 'none')
        recommendations.push('No test coverage detected — add tests');
    if (busFactor.overallScore < 40)
        recommendations.push('Bus factor is low — distribute knowledge');
    const score = Math.max(0, Math.min(100, 50
        + (busFactor.overallScore > 50 ? 15 : -10)
        - (highRiskSilos.length * 10)
        + (style.testCoverage === 'high' ? 10 : style.testCoverage === 'medium' ? 5 : -5)
        + (style.codeReviewStyle === 'thorough' ? 10 : 0)));
    return {
        score,
        busFactor: busFactor.overallScore,
        siloCount: silos.length,
        collaborationEdges: 0,
        skillGaps,
        strengths,
        recommendations,
    };
}
// ─── Sprint Retro ────────────────────────────────────────────────────────────
function generateSprintRetro(days = 14, project) {
    const db = (0, database_1.getDb)();
    const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
    const commits = db.prepare(project
        ? "SELECT COUNT(*) as cnt FROM behavior_events WHERE created_at >= ? AND project = ?"
        : "SELECT COUNT(*) as cnt FROM behavior_events WHERE created_at >= ?").get(...(project ? [since, project] : [since]));
    const bugFixes = db.prepare(project
        ? "SELECT COUNT(*) as cnt FROM behavior_events WHERE event_type = 'bug_fix' AND created_at >= ? AND project = ?"
        : "SELECT COUNT(*) as cnt FROM behavior_events WHERE event_type = 'bug_fix' AND created_at >= ?").get(...(project ? [since, project] : [since]));
    const sessions = db.prepare("SELECT tool_name, COUNT(*) as cnt FROM sessions WHERE start_time >= ? GROUP BY tool_name ORDER BY cnt DESC").all(since);
    const decisions = db.prepare("SELECT technology, reason FROM decisions WHERE created_at >= ? ORDER BY created_at DESC LIMIT 5").all(since);
    const newPatterns = db.prepare("SELECT COUNT(*) as cnt FROM patterns WHERE created_at >= ?").get(since);
    const summary = [
        `${commits.cnt} behavior events tracked`,
        `${bugFixes.cnt} bugs fixed`,
        `${decisions.length} key decisions made`,
        `${newPatterns.cnt} new patterns learned`,
        `Tools used: ${sessions.map(s => `${s.tool_name}(${s.cnt})`).join(', ') || 'none'}`,
    ].join('. ');
    return {
        period: `Last ${days} days`,
        commits: commits.cnt,
        filesChanged: 0,
        topContributors: sessions.map(s => ({ name: s.tool_name, commits: s.cnt })),
        keyDecisions: decisions.map(d => `${d.technology}: ${d.reason}`),
        bugsFixed: bugFixes.cnt,
        newPatterns: newPatterns.cnt,
        summary,
    };
}
// ─── Handoff ─────────────────────────────────────────────────────────────────
function generateHandoff(from, to, project) {
    const db = (0, database_1.getDb)();
    const lastSession = db.prepare('SELECT key_decisions, files_touched, context_snapshot FROM sessions WHERE project = ? ORDER BY start_time DESC LIMIT 1').get(project);
    const recentBugs = db.prepare("SELECT description FROM behavior_events WHERE event_type = 'bug_fix' AND project = ? ORDER BY created_at DESC LIMIT 3").all(project);
    const decisions = lastSession
        ? safeJson(String(lastSession.key_decisions || '[]'))
        : [];
    return {
        from,
        to,
        project,
        currentTasks: decisions.slice(0, 5),
        keyDecisions: decisions,
        blockers: recentBugs.map(b => b.description.slice(0, 80)),
        contextNotes: String(lastSession?.context_snapshot || 'No context available'),
    };
}
// ─── Utility ─────────────────────────────────────────────────────────────────
function safeJson(val) {
    if (!val || val === '[]' || val === '{}')
        return null;
    try {
        return JSON.parse(val);
    }
    catch {
        return val;
    }
}
//# sourceMappingURL=team-collaboration.js.map