
/**
 * Playbook Grading & Utility Logic
 * Separated to avoid circular dependencies between aiService and gradingService
 */

const getPlaybookVersion = (alert) => {
    if (!alert) return 1;
    if (alert.playbook_solution) {
        if (typeof alert.playbook_solution === 'string') {
            try {
                const pb = JSON.parse(alert.playbook_solution);
                return pb.playbook_version || 2;
            } catch (e) {
                return 2;
            }
        }
        return alert.playbook_solution.playbook_version || 2;
    }
    return 1;
};


const gradeV2Investigation = (submission, playbook) => {
    let score = 0;
    const breakdown = {
        verdictScore: 0,
        artifactsScore: 0,
        actionsScore: 0,
        feedback: [],
        sections: {
            verdict: { status: 'fail', score: 0, max_score: 40, feedback: '' },
            artifacts: { status: 'fail', score: 0, max_score: 30, feedback: '', missed_items: [], caught_items: [] },
            actions: { status: 'fail', score: 0, max_score: 30, feedback: '', missed_items: [], correct_items: [] }
        }
    };

    // 1. Verdict (40 points)
    const submittedVerdict = submission.verdict;
    const correctVerdict = playbook.expected_verdict || playbook.verdict || 'true_positive'; 
    const normSubmitted = (submittedVerdict || '').toLowerCase().replace(' ', '_');
    const normCorrect = (correctVerdict || '').toLowerCase().replace(' ', '_');

    if (normSubmitted === normCorrect) {
        score += 40;
        breakdown.verdictScore = 40;
        breakdown.sections.verdict = { 
            status: 'pass', 
            score: 40, 
            max_score: 40, 
            feedback: 'Correct Verdict' 
        };
        breakdown.feedback.push("Verdict is correct (+40)");
    } else {
        breakdown.sections.verdict = { 
            status: 'fail', 
            score: 0, 
            max_score: 40, 
            feedback: `Expected ${correctVerdict.replace('_', ' ')}, got ${submittedVerdict}` 
        };
        breakdown.feedback.push(`Incorrect verdict. Expected ${correctVerdict}, got ${submittedVerdict}`);
    }

    // 2. Artifacts (30 points)
    const artifacts = playbook.artifacts || [];
    const criticalArtifacts = artifacts.filter(a => a.is_critical || a.critical);
    const userCheckedIds = submission.checkedArtifacts || [];
    
    if (criticalArtifacts.length > 0) {
        // CRITICAL FIX: Match by VALUE, not by ID
        // Frontend generates dynamic IDs like "ip-203.0.113.45" or "hash-3a7bd3e2"
        // We need to extract the value part and match against playbook artifact values
        
        const extractValueFromId = (id) => {
            // If id is already an object (enriched by controller), return its value
            if (id && typeof id === 'object' && id.value) {
                return id.value;
            }

            // Otherwise, it's a string ID. Handle dynamic formats:
            // "ip-{value}", "hash-{first8chars}", "domain-{first12chars}", "cmd-1", "proc-cmd-0"
            if (typeof id !== 'string') return null;

            if (id.startsWith('ip-')) return id.slice(3);
            if (id.startsWith('hash-')) return id.slice(5); // Only first 8 chars
            if (id.startsWith('domain-')) return id.slice(7);
            if (id.startsWith('cmd-') || id.startsWith('proc-cmd-')) return null; // Can't reverse these
            return id; // Fallback: try as-is (might be original playbook ID)
        };
        
        const userCheckedValues = userCheckedIds.map(id => extractValueFromId(id)).filter(v => v);
        
        // Match critical artifacts: check if value matches OR if value starts with extracted prefix (for truncated hashes)
        const caughtCritical = criticalArtifacts.filter(a => {
            const artifactValue = a.value || '';
            return userCheckedIds.includes(a.id) || // Original ID match
                   userCheckedValues.includes(artifactValue) || // Exact value match
                   userCheckedValues.some(v => artifactValue.startsWith(v) || v.startsWith(artifactValue.slice(0, 8))); // Prefix match for hashes
        });
        const missedCritical = criticalArtifacts.filter(a => !caughtCritical.includes(a));
        
        const artifactRatio = caughtCritical.length / criticalArtifacts.length;
        const artifactPoints = Math.round(artifactRatio * 30);
        score += artifactPoints;
        breakdown.artifactsScore = artifactPoints;

        breakdown.sections.artifacts = {
            status: artifactPoints === 30 ? 'pass' : (artifactPoints > 0 ? 'partial' : 'fail'),
            score: artifactPoints,
            max_score: 30,
            feedback: artifactPoints === 30 ? 'All critical artifacts found' : `${caughtCritical.length}/${criticalArtifacts.length} Critical Artifacts Found`,
            missed_items: missedCritical.map(a => `${a.type}: ${a.value}`),
            caught_items: caughtCritical.map(a => `${a.type}: ${a.value}`)
        };
        
        if (caughtCritical.length === criticalArtifacts.length) {
            breakdown.feedback.push("All critical artifacts identified (+30)");
        } else {
            const missedText = missedCritical.map(a => `${a.type || 'Artifact'} ${a.value}`).join(', ');
            breakdown.feedback.push(`Missed critical artifacts: ${missedText} (${caughtCritical.length}/${criticalArtifacts.length})`);
        }

    } else {
        score += 30;
        breakdown.artifactsScore = 30;
        breakdown.sections.artifacts = { status: 'pass', score: 30, max_score: 30, feedback: 'No critical artifacts to analyze', missed_items: [], caught_items: [] };
        breakdown.feedback.push("Artifact analysis completed (+30)");
    }

    // 3. Actions (30 points)
    const expectedActions = playbook.expected_actions || playbook.actions || [];
    const userActions = submission.selectedActions || [];
    
    if (expectedActions.length > 0) {
        const correctActions = expectedActions.filter(action => userActions.includes(action));
        const missedActions = expectedActions.filter(action => !userActions.includes(action));
        const actionRatio = correctActions.length / expectedActions.length;
        const actionPoints = Math.round(actionRatio * 30);
        score += actionPoints;
        breakdown.actionsScore = actionPoints;
        
        breakdown.sections.actions = {
            status: actionPoints === 30 ? 'pass' : (actionPoints > 0 ? 'partial' : 'fail'),
            score: actionPoints,
            max_score: 30,
            feedback: actionPoints === 30 ? 'Correct response actions' : `${correctActions.length}/${expectedActions.length} Actions Correct`,
            missed_items: missedActions,
            correct_items: correctActions
        };

        if (actionPoints === 30) {
            breakdown.feedback.push("Response actions correct (+30)");
        } else {
            breakdown.feedback.push(`Missed response actions (${correctActions.length}/${expectedActions.length})`);
        }
    } else {
        if (userActions.length === 0) {
            score += 30;
            breakdown.actionsScore = 30;
             breakdown.sections.actions = { status: 'pass', score: 30, max_score: 30, feedback: 'Correctly took no action', missed_items: [], correct_items: [] };
            breakdown.feedback.push("Correctly took no action (+30)");
        } else {
            score += 15;
            breakdown.actionsScore = 15;
            breakdown.sections.actions = { status: 'partial', score: 15, max_score: 30, feedback: 'Unnecessary actions taken', missed_items: [], correct_items: [] };
            breakdown.feedback.push("Unnecessary actions taken (+15)");
        }
    }

    return {
        grade: score,
        feedback: breakdown.feedback.join('. '),
        breakdown,
        ai_summary: {
            verdict_correctness: score >= 40 ? "Correct" : "Incorrect",
            key_findings: breakdown.feedback.join('. '),
            missed_items: [...breakdown.sections.artifacts.missed_items, ...breakdown.sections.actions.missed_items],
            strengths: score > 80 ? "Solid analysis" : "Needs improvement"
        }
    };
};

const validateV2Playbook = (playbook) => {
    return playbook && playbook.artifacts && Array.isArray(playbook.artifacts);
};

module.exports = {
    getPlaybookVersion,
    gradeV2Investigation,
    validateV2Playbook
};
