/**
 * @file wally-analysis-modes.js
 * @description Analysis mode configurations for Wally Monitor.
 *              Defines which rule engines run per analysis mode and
 *              provides tagging/filtering utilities.
 *
 * Available modes:
 *   - "wcag"     → axe-core only (pure WCAG 2.2 analysis)
 *   - "nbr"      → Custom rules only (NBR 17.225 + IF-THEN rules)
 *
 * @module WallyMonitor.AnalysisModes
 * @since 1.3.0
 */
(function($) {
    'use strict';

    window.WallyMonitor = window.WallyMonitor || {};
    WallyMonitor.AnalysisModes = WallyMonitor.AnalysisModes || {};

    // ─── Mode Definitions ──────────────────────────────────────────────

    /**
     * @typedef {Object} AnalysisModeConfig
     * @property {string}   id          - Mode identifier
     * @property {string}   label       - Human-readable label (pt-BR)
     * @property {string}   description - Short description (pt-BR)
     * @property {boolean}  useAxeCore  - Whether to run axe-core engine
     * @property {boolean}  useCustom   - Whether to run WallyMonitor.Rules (13 custom)
     * @property {boolean}  useNBR      - Whether to run WallyMonitor.NBRRules (48 NBR)
     * @property {boolean}  useIFThen   - Whether to run WallyMonitor.IFThenRules (57 IF-THEN)
     * @property {string}   source      - Source label for results tagging
     */

    /** @type {Object.<string, AnalysisModeConfig>} */
    WallyMonitor.AnalysisModes.modes = {
        wcag: {
            id:          'wcag',
            label:       'WCAG 2.2',
            description: 'Análise padrão internacional com regras WCAG 2.2 + regras WordPress complementares.',
            useAxeCore:  true,
            useCustom:   true,
            useNBR:      false,
            useIFThen:   false,
            source:      'wcag'
        },
        nbr: {
            id:          'nbr',
            label:       'NBR 17.225 (Regras Brasileiras)',
            description: 'Análise exclusiva com as regras brasileiras NBR 17.225 + regras IF-THEN condicionais + regras WordPress customizadas.',
            useAxeCore:  false,
            useCustom:   true,
            useNBR:      true,
            useIFThen:   true,
            source:      'wally-nbr'
        }
    };

    /** @type {string} Default analysis mode */
    WallyMonitor.AnalysisModes.defaultMode = 'wcag';

    // ─── Mode Access ───────────────────────────────────────────────────

    /**
     * Get the current analysis mode from wallyData settings.
     * Falls back to defaultMode if not set.
     *
     * @returns {string} Current mode id ('wcag' or 'nbr')
     */
    WallyMonitor.AnalysisModes.getCurrentMode = function() {
        if (typeof wallyData !== 'undefined' && wallyData.analysisMode) {
            var mode = wallyData.analysisMode;
            if (WallyMonitor.AnalysisModes.modes[mode]) {
                return mode;
            }
        }
        return WallyMonitor.AnalysisModes.defaultMode;
    };

    /**
     * Get the full configuration object for the current (or specified) mode.
     *
     * @param {string} [modeId] - Optional mode id; uses current if omitted
     * @returns {AnalysisModeConfig}
     */
    WallyMonitor.AnalysisModes.getConfig = function(modeId) {
        var id = modeId || WallyMonitor.AnalysisModes.getCurrentMode();
        return WallyMonitor.AnalysisModes.modes[id] || WallyMonitor.AnalysisModes.modes.wcag;
    };

    // ─── Scan Execution ────────────────────────────────────────────────

    /**
     * Run the appropriate rule engines based on the given analysis mode.
     * Returns a promise that resolves with an array of all violations found.
     *
     * @param {Document}  doc     - The document (or iframe contentDocument) to scan
     * @param {string}    [modeId] - Analysis mode id; uses current if omitted
     * @returns {Promise<{violations: Array, source: string, mode: string}>}
     */
    WallyMonitor.AnalysisModes.runAnalysis = async function(doc, modeId) {
        var config = WallyMonitor.AnalysisModes.getConfig(modeId);
        var allViolations = [];

        // ── 1. axe-core (WCAG 2.2) ──────────────────────────────────
        if (config.useAxeCore && typeof axe !== 'undefined') {
            var axeConfig = WallyMonitor.AnalysisModes.buildAxeConfig();
            var axeResults;
            var axeRetries = 0;
            var axeMaxRetries = 3;

            // Determine a valid context for axe.run
            var axeContext;
            if (doc && doc.body && doc.body.nodeType === 1) {
                axeContext = doc.body;
            } else if (doc && doc.documentElement && doc.documentElement.nodeType === 1) {
                axeContext = doc.documentElement;
            } else if (doc && doc.nodeType === 1) {
                // doc is already an Element
                axeContext = doc;
            } else {
                throw new Error('Não foi possível acessar o conteúdo do documento para análise. Tente novamente.');
            }

            while (true) {
                try {
                    axeResults = await axe.run(axeContext, axeConfig);
                    break;
                } catch (axeError) {
                    if (axeError.message && axeError.message.indexOf('already running') !== -1 && axeRetries < axeMaxRetries) {
                        axeRetries++;
                        await new Promise(function(r) { setTimeout(r, 2000); });
                    } else {
                        throw axeError;
                    }
                }
            }
            // Tag WCAG 2.2 violations with source
            axeResults.violations.forEach(function(v) {
                v._source = 'wcag';
                v._engine = 'WCAG 2.2';
            });
            Array.prototype.push.apply(allViolations, axeResults.violations);
        }

        // ── 2. Custom Rules (WordPress-specific) ─────────────────────
        if (config.useCustom && WallyMonitor.Rules && WallyMonitor.Rules.runAllChecks) {
            var customViolations = WallyMonitor.Rules.runAllChecks(doc);
            customViolations.forEach(function(v) {
                v._source = 'wally-custom';
                v._engine = 'WallyMonitor.Rules';
            });
            Array.prototype.push.apply(allViolations, customViolations);
        }

        // ── 3. NBR 17.225 Rules ──────────────────────────────────────
        if (config.useNBR && WallyMonitor.NBRRules && WallyMonitor.NBRRules.runAllChecks) {
            var nbrViolations = WallyMonitor.NBRRules.runAllChecks(doc);
            nbrViolations.forEach(function(v) {
                v._source = 'wally-nbr';
                v._engine = 'WallyMonitor.NBRRules';
            });
            Array.prototype.push.apply(allViolations, nbrViolations);
        }

        // ── 4. IF-THEN Rules (NBR 17.225 conditionals) ──────────────
        if (config.useIFThen && WallyMonitor.IFThenRules && WallyMonitor.IFThenRules.runAllChecks) {
            var iftViolations = WallyMonitor.IFThenRules.runAllChecks(doc);
            iftViolations.forEach(function(v) {
                v._source = 'wally-ifthen';
                v._engine = 'WallyMonitor.IFThenRules';
            });
            Array.prototype.push.apply(allViolations, iftViolations);
        }

        return {
            violations: allViolations,
            source:     config.source,
            mode:       config.id,
            label:      config.label,
            engines:    WallyMonitor.AnalysisModes.getActiveEngines(config)
        };
    };

    // ─── axe-core Configuration ────────────────────────────────────────

    /**
     * Build axe.run() configuration object based on current WCAG level setting.
     *
     * @returns {Object} axe RunOptions
     */
    WallyMonitor.AnalysisModes.buildAxeConfig = function() {
        var level = 'AA'; // default
        if (typeof wallyData !== 'undefined' && wallyData.wcagLevel) {
            level = wallyData.wcagLevel;
        }

        // Map WCAG level to axe-core runOnly tags
        var runTags = ['wcag2a', 'wcag21a', 'wcag22a'];
        if (level === 'AA' || level === 'AAA') {
            runTags.push('wcag2aa', 'wcag21aa', 'wcag22aa');
        }
        if (level === 'AAA') {
            runTags.push('wcag2aaa', 'wcag21aaa', 'wcag22aaa');
        }
        // Always include best-practice for comprehensive coverage
        runTags.push('best-practice');

        return {
            runOnly: {
                type: 'tag',
                values: runTags
            },
            resultTypes: ['violations', 'incomplete']
        };
    };

    // ─── Utilities ─────────────────────────────────────────────────────

    /**
     * Get a list of active engine names for the given config.
     *
     * @param {AnalysisModeConfig} config
     * @returns {string[]}
     */
    WallyMonitor.AnalysisModes.getActiveEngines = function(config) {
        var engines = [];
        if (config.useAxeCore)  engines.push('WCAG 2.2');
        if (config.useCustom)   engines.push('Custom Rules (17)');
        if (config.useNBR)      engines.push('NBR 17.225 (48)');
        if (config.useIFThen)   engines.push('IF-THEN (57)');
        return engines;
    };

    /**
     * Filter violations by source engine.
     *
     * @param {Array}  violations - Array of violation objects
     * @param {string} source     - Source to filter by ('wcag', 'wally-custom', 'wally-nbr', 'wally-ifthen')
     * @returns {Array}
     */
    WallyMonitor.AnalysisModes.filterBySource = function(violations, source) {
        return violations.filter(function(v) {
            return v._source === source;
        });
    };

    /**
     * Group violations by their source engine.
     *
     * @param {Array} violations
     * @returns {Object.<string, Array>}
     */
    WallyMonitor.AnalysisModes.groupBySource = function(violations) {
        var groups = {};
        violations.forEach(function(v) {
            var src = v._source || 'unknown';
            if (!groups[src]) { groups[src] = []; }
            groups[src].push(v);
        });
        return groups;
    };

    /**
     * Get a human-readable summary of the analysis mode and its engines.
     *
     * @param {string} [modeId]
     * @returns {string}
     */
    WallyMonitor.AnalysisModes.getSummaryText = function(modeId) {
        var config = WallyMonitor.AnalysisModes.getConfig(modeId);
        var engines = WallyMonitor.AnalysisModes.getActiveEngines(config);
        return config.label + ' — Motores: ' + engines.join(', ');
    };

    // ─── NBR ↔ WCAG Cross-Reference Map ────────────────────────────────

    /**
     * Static cross-reference: NBR 17.225 section → WCAG 2.2 Success Criterion.
     * Used for reporting, documentation, and rule-level mapping.
     *
     * @type {Object.<string, {wcagSC: string, wcagTitle: string, level: string}>}
     */
    WallyMonitor.AnalysisModes.nbrToWcagMap = {
        // 5.1 – Text Alternatives
        '5.1.1':  { wcagSC: '1.1.1', wcagTitle: 'Non-text Content', level: 'A' },
        // 5.2 – Time-based Media
        '5.2.1':  { wcagSC: '1.2.1', wcagTitle: 'Audio-only and Video-only (Prerecorded)', level: 'A' },
        '5.2.2':  { wcagSC: '1.2.2', wcagTitle: 'Captions (Prerecorded)', level: 'A' },
        '5.2.3':  { wcagSC: '1.2.3', wcagTitle: 'Audio Description or Media Alternative (Prerecorded)', level: 'A' },
        '5.2.4':  { wcagSC: '1.2.4', wcagTitle: 'Captions (Live)', level: 'AA' },
        '5.2.5':  { wcagSC: '1.2.5', wcagTitle: 'Audio Description (Prerecorded)', level: 'AA' },
        // 5.3 – Adaptable
        '5.3.1':  { wcagSC: '1.3.1', wcagTitle: 'Info and Relationships', level: 'A' },
        '5.3.2':  { wcagSC: '1.3.2', wcagTitle: 'Meaningful Sequence', level: 'A' },
        '5.3.3':  { wcagSC: '1.3.3', wcagTitle: 'Sensory Characteristics', level: 'A' },
        '5.3.4':  { wcagSC: '1.3.4', wcagTitle: 'Orientation', level: 'AA' },
        '5.3.5':  { wcagSC: '1.3.5', wcagTitle: 'Identify Input Purpose', level: 'AA' },
        // 5.4 – Distinguishable
        '5.4.1':  { wcagSC: '1.4.1', wcagTitle: 'Use of Color', level: 'A' },
        '5.4.2':  { wcagSC: '1.4.2', wcagTitle: 'Audio Control', level: 'A' },
        '5.4.3':  { wcagSC: '1.4.3', wcagTitle: 'Contrast (Minimum)', level: 'AA' },
        '5.4.4':  { wcagSC: '1.4.4', wcagTitle: 'Resize Text', level: 'AA' },
        '5.4.5':  { wcagSC: '1.4.5', wcagTitle: 'Images of Text', level: 'AA' },
        '5.4.10': { wcagSC: '1.4.10', wcagTitle: 'Reflow', level: 'AA' },
        '5.4.11': { wcagSC: '1.4.11', wcagTitle: 'Non-text Contrast', level: 'AA' },
        '5.4.12': { wcagSC: '1.4.12', wcagTitle: 'Text Spacing', level: 'AA' },
        '5.4.13': { wcagSC: '1.4.13', wcagTitle: 'Content on Hover or Focus', level: 'AA' },
        // 5.5 – Keyboard & Input
        '5.5.1':  { wcagSC: '2.1.1', wcagTitle: 'Keyboard', level: 'A' },
        '5.5.2':  { wcagSC: '2.1.2', wcagTitle: 'No Keyboard Trap', level: 'A' },
        '5.5.4':  { wcagSC: '2.1.4', wcagTitle: 'Character Key Shortcuts', level: 'A' },
        '5.5.5':  { wcagSC: '2.2.2', wcagTitle: 'Pause, Stop, Hide', level: 'A' },
        '5.5.6':  { wcagSC: '2.3.1', wcagTitle: 'Three Flashes or Below Threshold', level: 'A' },
        '5.5.8':  { wcagSC: '2.3.3', wcagTitle: 'Animation from Interactions', level: 'AAA' },
        // 5.6 – Navigation
        '5.6.1':  { wcagSC: '2.4.1', wcagTitle: 'Bypass Blocks', level: 'A' },
        '5.6.2':  { wcagSC: '2.4.2', wcagTitle: 'Page Titled', level: 'A' },
        '5.6.3':  { wcagSC: '2.4.3', wcagTitle: 'Focus Order', level: 'A' },
        '5.6.4':  { wcagSC: '2.4.4', wcagTitle: 'Link Purpose (In Context)', level: 'A' },
        '5.6.5':  { wcagSC: '2.4.5', wcagTitle: 'Multiple Ways', level: 'AA' },
        '5.6.7':  { wcagSC: '2.4.7', wcagTitle: 'Focus Visible', level: 'AA' },
        '5.6.10': { wcagSC: '2.4.10', wcagTitle: 'Section Headings', level: 'AAA' },
        '5.6.11': { wcagSC: '2.4.11', wcagTitle: 'Focus Not Obscured (Minimum)', level: 'AA' },
        '5.6.13': { wcagSC: '2.4.13', wcagTitle: 'Focus Appearance', level: 'AAA' },
        // 5.7 – Pointer Input
        '5.7.2':  { wcagSC: '2.5.2', wcagTitle: 'Pointer Cancellation', level: 'A' },
        '5.7.7':  { wcagSC: '2.5.7', wcagTitle: 'Dragging Movements', level: 'AA' },
        '5.7.8':  { wcagSC: '2.5.8', wcagTitle: 'Target Size (Minimum)', level: 'AA' },
        // 5.8 – Predictable & Readable
        '5.8.1':  { wcagSC: '3.1.1', wcagTitle: 'Language of Page', level: 'A' },
        '5.8.2':  { wcagSC: '3.1.2', wcagTitle: 'Language of Parts', level: 'AA' },
        '5.8.3':  { wcagSC: '3.2.3', wcagTitle: 'Consistent Navigation', level: 'AA' },
        '5.8.4':  { wcagSC: '3.2.4', wcagTitle: 'Consistent Identification', level: 'AA' },
        '5.8.5':  { wcagSC: '3.1.5', wcagTitle: 'Reading Level', level: 'AAA' },
        '5.8.6':  { wcagSC: '3.2.6', wcagTitle: 'Consistent Help', level: 'A' },
        // 5.9 – Input Assistance
        '5.9.1':  { wcagSC: '3.3.1', wcagTitle: 'Error Identification', level: 'A' },
        '5.9.2':  { wcagSC: '3.3.2', wcagTitle: 'Labels or Instructions', level: 'A' },
        '5.9.3':  { wcagSC: '3.3.3', wcagTitle: 'Error Suggestion', level: 'AA' },
        '5.9.4':  { wcagSC: '3.3.4', wcagTitle: 'Error Prevention (Legal, Financial, Data)', level: 'AA' },
        '5.9.7':  { wcagSC: '3.3.7', wcagTitle: 'Redundant Entry', level: 'A' },
        '5.9.8':  { wcagSC: '3.3.8', wcagTitle: 'Accessible Authentication (Minimum)', level: 'AA' },
        // 5.10 – Compatible
        '5.10.2': { wcagSC: '4.1.2', wcagTitle: 'Name, Role, Value', level: 'A' },
        '5.10.3': { wcagSC: '4.1.3', wcagTitle: 'Status Messages', level: 'AA' }
    };

    /**
     * Look up WCAG SC for a given NBR section.
     *
     * @param {string} nbrSection - e.g. '5.3.1'
     * @returns {{wcagSC: string, wcagTitle: string, level: string}|null}
     */
    WallyMonitor.AnalysisModes.lookupWcag = function(nbrSection) {
        return WallyMonitor.AnalysisModes.nbrToWcagMap[nbrSection] || null;
    };

    /**
     * Extract NBR section from violation tags.
     *
     * @param {string[]} tags
     * @returns {string|null} e.g. '5.3.1'
     */
    WallyMonitor.AnalysisModes.extractNbrSection = function(tags) {
        if (!tags || !tags.length) { return null; }
        for (var i = 0; i < tags.length; i++) {
            var match = tags[i].match(/^nbr17225-([\d.]+)$/);
            if (match) { return match[1]; }
        }
        return null;
    };

})(jQuery);
