export class ScoreCalculator {
    // Theoretical max score based on boosting logic:
    // Base (~15) + Resource Match (500) + Action Match (50) + Buffer = ~600
    static MAX_POSSIBLE_SCORE = 600.0;
    // Boost Constants
    static RESOURCE_MATCH_BOOST = 500.0;
    static RESOURCE_PARTIAL_BOOST = 50.0;
    static RESOURCE_MISMATCH_PENALTY = 50.0; // [R17] New Penalty
    static ACTION_MATCH_BOOST = 50.0;
    static ACTION_COMPATIBLE_BOOST = 2.0;
    static ACTION_MISMATCH_PENALTY = 50.0;
    static V2_VERSION_BOOST = 0.3; // [R20] Prefer v2 over v1 (tiebreaker)
    // [R17] Related Resources Whitelist (Bidirectional validity)
    // These pairs are considered "safe" and will NOT trigger a mismatch penalty.
    static RELATED_RESOURCES = {
        'block-diagram': ['block-node', 'node', 'tree-search'], // [R35]
        'block-node': ['block-diagram'],
        'fault-tree': ['failure-mode'],
        'failure-mode': ['fault-tree', 'fmm-diagram'], // FTA contains failure modes, FMM is a diagram view
        'fmm-diagram': ['failure-mode', 'tree-search'], // [R19] [R35]
        'project': ['document', 'file', 'member', 'join-request', 'worksheet', 'block-diagram', 'approval', 'board'], // Project contains everything [R39]
        'approval': ['project', 'board'], // [R39] Approval is related to projects and boards
        'board': ['approval', 'project'], // [R39] Board comments are part of approval workflow
        'knowledge': ['category'],
        'category': ['knowledge'],
        'oauth': ['auth'],
        'auth': ['oauth'],
        'context-version': ['system'],
        'system': ['context-version'],
        'evaluation': ['significance-criteria'], // [R33]
        'significance-criteria': ['evaluation'], // [R33]
        'tree-search': ['block-diagram', 'fmm-diagram', 'failure-mode'], // [R35] Tree search spans FMM and block-diagram domains
        'join-request': ['project', 'user', 'member'],
        'admin-user': ['user'], // [R19]
        'user': ['admin-user'] // [R19]
        // Note: Inverse is NOT necessarily true (searching for 'document' shouldn't show 'project' root unless necessary, but let's be strict for now)
    };
    /**
     * Calculates the final normalized score based on intent and document metadata.
     * @param baseScore The initial score provided by the search engine (Orama)
     * @param intent The detected user intent
     * @param doc The document being scored
     * @returns Normalized score between 0.0 and 1.0
     */
    calculate(baseScore, intent, doc) {
        let score = baseScore;
        const docResource = doc.resourceType || 'unknown';
        const docAction = doc.actionType || 'other';
        // A. Action Intent Scoring
        if (intent.action && docAction !== 'other') {
            // Compatible Actions: List implies Read (viewing items), Export implies Read, Import implies Create
            const isCompatible = (intent.action === 'list' && docAction === 'read')
                || (intent.action === 'export' && docAction === 'read') // [R19] Download/export is a form of read
                || (intent.action === 'import' && docAction === 'create'); // [R19] Import is a form of create
            if (intent.action === docAction) {
                score += ScoreCalculator.ACTION_MATCH_BOOST;
            }
            else if (isCompatible) {
                score += ScoreCalculator.ACTION_COMPATIBLE_BOOST;
                // Optimization: Compatible actions don't count as full match but don't penalty either
            }
            else {
                score -= ScoreCalculator.ACTION_MISMATCH_PENALTY;
            }
        }
        // B. Resource Intent Scoring
        // Only apply massive resource boost if action matches (or no specific action intent)
        // This prevents "PUT /projects" (Right Resource, Wrong Action) from outscoring "GET /projects"
        let applyResourceBoost = true;
        if (intent.action && docAction !== 'other' && intent.action !== docAction) {
            const isCompatible = (intent.action === 'list' && docAction === 'read')
                || (intent.action === 'export' && docAction === 'read') // [R19]
                || (intent.action === 'import' && docAction === 'create'); // [R19]
            if (!isCompatible) {
                applyResourceBoost = false;
            }
        }
        if (intent.resource) {
            const normalizedDocResource = docResource.replace(/-/g, '');
            const normalizedIntentResource = intent.resource.replace(/-/g, '');
            const isExactMatch = normalizedDocResource === normalizedIntentResource;
            const isPartialMatch = normalizedDocResource.includes(normalizedIntentResource) || normalizedIntentResource.includes(normalizedDocResource);
            if (applyResourceBoost) {
                if (isExactMatch) {
                    score += ScoreCalculator.RESOURCE_MATCH_BOOST;
                }
                else if (isPartialMatch) {
                    score += ScoreCalculator.RESOURCE_PARTIAL_BOOST;
                }
            }
            // [R17] Cross-Resource Mismatch Penalty
            // If user wants Resource A, but Doc is Resource B, and they are NOT related -> PENALTY
            if (!isExactMatch && !isPartialMatch) {
                // Check whitelist
                const validRelations = ScoreCalculator.RELATED_RESOURCES[intent.resource] || [];
                const isRelated = validRelations.includes(docResource);
                if (!isRelated && docResource !== 'unknown' && docResource !== 'other') {
                    // STRONG PENALTY for explicitly different resources
                    score -= ScoreCalculator.RESOURCE_MISMATCH_PENALTY;
                }
            }
        }
        // C. Version Boost — prefer v2 endpoints over v1 [R20]
        if (doc.version === 'v2') {
            score += ScoreCalculator.V2_VERSION_BOOST;
        }
        return this.normalize(score);
    }
    /**
     * Normalizes any score to the 0.0 - 1.0 range.
     */
    normalize(score) {
        if (score < 0)
            return 0.0;
        return Math.min(score / ScoreCalculator.MAX_POSSIBLE_SCORE, 1.0);
    }
}
