import { AxeBuilder } from '@axe-core/webdriverio';
import allure from '@wdio/allure-reporter';
import { css2xpath } from '../core/css2xpath.js';
import { AssertionError } from 'assert';  // Import Node's assertion error type

export default class AxeService {
    constructor(options = {}) {
        // Default options
        this.options = {
            // By default, only show violations and incomplete results
            showSections: {
                violations: true,
                incomplete: true,
                passes: false,
                inapplicable: false
            },
            // Configure which report formats to attach
            attachReports: {
                html: true,  // HTML report enabled by default
                json: false  // JSON report disabled by default
            },
            // All failure criteria are disabled by default - presence indicates enabled state
            // failOnAccessibility: {
            //     violations: {
            //         thresholds: { // Default thresholds if enabled
            //             critical: 0,
            //             serious: 0,
            //             moderate: 0,
            //             minor: 0
            //         }
            //     },
            //     incomplete: {
            //         thresholds: { // Default thresholds if enabled
            //             critical: 0,
            //             serious: 0
            //         }
            //     }
            // }
            ...options
        };
    }
    
    // This is called after the session has been created
    beforeSession() {
        // Nothing to do here for this service
    }

    // This is called after the browser has been initialized
    before() {
        const serviceOptions = this.options;
        
        // Add a custom command to the browser object
        browser.addCommand('runAxe', async function (options = {}) {
            // Create a new AxeBuilder instance
            const builder = new AxeBuilder({ client: this });
            
            // Apply any options like rules to include/exclude, etc.
            if (options.include) {
                builder.include(options.include);
            }
            
            if (options.exclude) {
                builder.exclude(options.exclude);
            }
            
            if (options.withTags) {
                builder.withTags(options.withTags);
            }
            
            if (options.disableRules) {
                builder.disableRules(options.disableRules);
            }
            
            if (options.enableRules) {
                builder.enableRules(options.enableRules);
            }
            
            // Run the analysis and get results
            const results = await builder.analyze();
            
            // Transform the results by adding XPath expressions for CSS selectors
            // Helper function to process nodes in a result category
            const processNodes = (nodes) => {
                return nodes.map(node => {
                    // Create a copy of the node to avoid modifying the original
                    const processedNode = {...node};
                    
                    // Ensure target is properly handled - it should be an array of strings
                    if (processedNode.target) {
                        // Ensure it's processed as strings
                        if (Array.isArray(processedNode.target)) {
                            processedNode.target = processedNode.target.map(selector => 
                                typeof selector === 'string' ? selector : JSON.stringify(selector)
                            );
                        }
                    }
                    
                    // Add XPath expressions for CSS selectors
                    if (processedNode.target && Array.isArray(processedNode.target) && processedNode.target.length > 0) {
                        try {
                            // Only try to convert if it's a string CSS selector
                            const cssSelector = processedNode.target[0];
                            if (typeof cssSelector === 'string') {
                                processedNode.xpath = css2xpath(cssSelector);
                            }
                        } catch (e) {
                            // Still add a placeholder to indicate the conversion failed
                            processedNode.xpath = "XPath conversion failed";
                        }
                    }
                    
                    return processedNode;
                });
            };
            
            // Create a deep copy of the results to avoid modifying the original
            const transformedResults = JSON.parse(JSON.stringify(results));
            
            // Process each category of results that contains nodes
            if (transformedResults.violations) {
                transformedResults.violations.forEach(violation => {
                    violation.nodes = processNodes(violation.nodes);
                });
            }
            
            if (transformedResults.passes) {
                transformedResults.passes.forEach(pass => {
                    pass.nodes = processNodes(pass.nodes);
                });
            }
            
            if (transformedResults.incomplete) {
                transformedResults.incomplete.forEach(incomplete => {
                    incomplete.nodes = processNodes(incomplete.nodes);
                });
            }
            
            if (transformedResults.inapplicable) {
                transformedResults.inapplicable.forEach(inapplicable => {
                    inapplicable.nodes = processNodes(inapplicable.nodes);
                });
            }
            
            // Format the results based on whether HTML is the primary output
            const formattedResults = serviceOptions.attachReports.html
                ? JSON.stringify(transformedResults) // Compact format if HTML is enabled
                : JSON.stringify(transformedResults, null, 2); // Pretty format if HTML is disabled
            
            // Attach the JSON results to the Allure report if configured
            if (serviceOptions.attachReports.json) {
                allure.addAttachment(
                    'Accessibility Results (JSON)', 
                    formattedResults, 
                    'application/json'
                );
            }
            
            // Generate and attach an HTML report if configured
            if (serviceOptions.attachReports.html) {
                const htmlReport = generateHtmlReport(transformedResults, this.config, serviceOptions);
                allure.addAttachment(
                    'Accessibility Results (HTML)',
                    htmlReport,
                    'text/html'
                );
            }
            
            // Log a summary of the results
            console.log(`Accessibility Test Results: ${results.violations.length} violations found`);
            
            // Check failure criteria if enabled - do this directly in the command
            if (serviceOptions.failOnAccessibility) {
                console.log("Checking against accessibility thresholds");
                const failConfig = serviceOptions.failOnAccessibility;
                let failureMessages = [];
                
                // Check for violations if configured
                if (failConfig.violations) {
                    const thresholds = failConfig.violations.thresholds || {
                        critical: 0,
                        serious: 0,
                        moderate: 0,
                        minor: 0
                    };
                    
                    console.log("Checking violations against thresholds:", thresholds);
                    
                    // Count violations by impact level
                    const violationCounts = {
                        critical: 0,
                        serious: 0,
                        moderate: 0,
                        minor: 0,
                        unknown: 0
                    };
                    
                    // Count all violations by impact level
                    results.violations.forEach(violation => {
                        const impact = violation.impact || 'unknown';
                        if (violationCounts.hasOwnProperty(impact)) {
                            violationCounts[impact]++;
                        } else {
                            violationCounts.unknown++;
                        }
                    });
                    
                    console.log("Violation counts by impact:", violationCounts);
                    
                    // Check each impact level against its threshold
                    for (const [impact, count] of Object.entries(violationCounts)) {
                        // Skip if this impact level doesn't have a threshold or if count is within threshold
                        if (!thresholds.hasOwnProperty(impact)) {
                            console.log(`No threshold defined for ${impact} violations, skipping`);
                            continue;
                        }
                        
                        if (count <= thresholds[impact]) {
                            console.log(`${impact} violations (${count}) within threshold (${thresholds[impact]})`);
                            continue;
                        }
                        
                        console.log(`${impact} violations (${count}) exceed threshold (${thresholds[impact]})`);
                        failureMessages.push(
                            `Found ${count} ${impact} accessibility violations ` +
                            `(threshold: ${thresholds[impact]})`
                        );
                    }
                }
                
                // Check for incomplete issues if configured
                if (failConfig.incomplete) {
                    const thresholds = failConfig.incomplete.thresholds || {
                        critical: 0,
                        serious: 0
                    };
                    
                    console.log("Checking incomplete against thresholds:", thresholds);
                    
                    // Count incomplete by impact level
                    const incompleteCounts = {
                        critical: 0,
                        serious: 0,
                        moderate: 0,
                        minor: 0,
                        unknown: 0
                    };
                    
                    // Count all incomplete by impact level
                    results.incomplete.forEach(item => {
                        const impact = item.impact || 'unknown';
                        if (incompleteCounts.hasOwnProperty(impact)) {
                            incompleteCounts[impact]++;
                        } else {
                            incompleteCounts.unknown++;
                        }
                    });
                    
                    console.log("Incomplete counts by impact:", incompleteCounts);
                    
                    // Check each impact level against its threshold
                    for (const [impact, count] of Object.entries(incompleteCounts)) {
                        // Skip if this impact level doesn't have a threshold or if count is within threshold
                        if (!thresholds.hasOwnProperty(impact)) {
                            console.log(`No threshold defined for ${impact} incomplete, skipping`);
                            continue;
                        }
                        
                        if (count <= thresholds[impact]) {
                            console.log(`${impact} incomplete (${count}) within threshold (${thresholds[impact]})`);
                            continue;
                        }
                        
                        console.log(`${impact} incomplete (${count}) exceed threshold (${thresholds[impact]})`);
                        failureMessages.push(
                            `Found ${count} ${impact} incomplete accessibility checks ` +
                            `(threshold: ${thresholds[impact]})`
                        );
                    }
                }
                
                // If we have failure messages, mark the test as failed, not broken
                if (failureMessages.length > 0) {
                    console.log("FAILING TEST with messages:", failureMessages);
                    
                    // Create a detailed failure message for the report
                    const failureMessage = `Accessibility test failed:\n${failureMessages.join('\n')}`;
                    
                    // Add issue information to the Allure report
                    allure.addIssue('Accessibility Failure');
                    
                    // Add more detailed information about the failures
                    allure.addDescription(failureMessage, 'text');
                    
                    // Use AssertionError instead of a generic Error
                    // This will mark the test as "failed" rather than "broken"
                    throw new AssertionError({
                        message: failureMessage,
                        actual: 'Found accessibility issues',
                        expected: ' No accessibility issues above thresholds',
                        operator: 'strictEqual'
                    });
                } else {
                    console.log("All accessibility checks passed thresholds");
                }
            }
            
            // Return the original results object for further processing in tests
            return results;
        });

        /**
         * Generates an HTML report from the accessibility test results
         * @param {Object} results - The axe-core results object
         * @param {Object} browserConfig - The browser configuration object
         * @param {Object} serviceOptions - The service configuration options
         * @returns {string} - HTML report
         */
        function generateHtmlReport(results, browserConfig = {}, serviceOptions = {}) {
            // Generate the CSS for the report - extending with filter styles and more
            const css = `
                body {
                    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
                    line-height: 1.6;
                    color: #333;
                    max-width: 1200px;
                    margin: 0 auto;
                    padding: 20px;
                }
                h1, h2, h3, h4 {
                    margin-top: 20px;
                    margin-bottom: 10px;
                }
                h1 {
                    border-bottom: 2px solid #eee;
                    padding-bottom: 10px;
                }
                .summary {
                    display: flex;
                    flex-wrap: wrap;
                    gap: 20px;
                    margin: 20px 0;
                }
                .summary-card {
                    border: 1px solid #ddd;
                    border-radius: 4px;
                    padding: 15px;
                    min-width: 150px;
                    flex: 1;
                    cursor: pointer;
                    transition: all 0.2s ease;
                }
                .summary-card:hover {
                    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
                }
                .summary-card.active {
                    border-width: 2px;
                    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
                }
                .summary-card.violations {
                    border-left: 5px solid #e74c3c;
                }
                .summary-card.passes {
                    border-left: 5px solid #2ecc71;
                }
                .summary-card.incomplete {
                    border-left: 5px solid #f39c12;
                }
                .summary-card.inapplicable {
                    border-left: 5px solid #95a5a6;
                }
                .card-count {
                    font-size: 2em;
                    font-weight: bold;
                    margin: 5px 0;
                }
                .result-item {
                    border: 1px solid #ddd;
                    border-radius: 4px;
                    margin-bottom: 20px;
                    padding: 15px;
                }
                .result-item.critical {
                    border-left: 5px solid #e74c3c;
                }
                .result-item.serious {
                    border-left: 5px solid #e67e22;
                }
                .result-item.moderate {
                    border-left: 5px solid #f39c12;
                }
                .result-item.minor {
                    border-left: 5px solid #95a5a6;
                }
                .result-item.pass {
                    border-left: 5px solid #2ecc71;
                }
                .result-item.incomplete {
                    border-left: 5px solid #f39c12;
                }
                .result-item.inapplicable {
                    border-left: 5px solid #95a5a6;
                }
                .impact {
                    display: inline-block;
                    padding: 2px 8px;
                    border-radius: 4px;
                    color: white;
                    font-weight: bold;
                    margin-right: 10px;
                }
                .impact.critical {
                    background-color: #e74c3c;
                }
                .impact.serious {
                    background-color: #e67e22;
                }
                .impact.moderate {
                    background-color: #f39c12;
                }
                .impact.minor {
                    background-color: #95a5a6;
                }
                .impact.pass {
                    background-color: #2ecc71;
                }
                .impact.incomplete {
                    background-color: #f39c12;
                }
                .impact.inapplicable {
                    background-color: #95a5a6;
                }
                .result-details {
                    margin-top: 10px;
                }
                .rule-desc {
                    margin: 10px 0;
                    font-style: italic;
                }
                .help-link {
                    display: inline-block;
                    margin: 5px 0;
                    color: #3498db;
                }
                .nodes {
                    margin-top: 15px;
                }
                .node {
                    background-color: #f9f9f9;
                    border: 1px solid #eee;
                    border-radius: 4px;
                    padding: 10px;
                    margin-bottom: 10px;
                }
                .selectors {
                    font-family: monospace;
                    margin: 10px 0;
                    white-space: nowrap;
                    overflow-x: auto;
                    padding: 5px;
                    background-color: #f0f0f0;
                    border-radius: 4px;
                }
                .selectors div {
                    margin-bottom: 5px;
                }
                .code {
                    font-family: monospace;
                    background-color: #f0f0f0;
                    padding: 2px 4px;
                    border-radius: 3px;
                }
                .html {
                    font-family: monospace;
                    white-space: pre-wrap;
                    margin: 10px 0;
                    padding: 10px;
                    background-color: #f0f0f0;
                    border-radius: 4px;
                    overflow-x: auto;
                }
                .copy-container {
                    position: relative;
                    display: inline-block;
                    cursor: pointer;
                }
                
                .copy-container:hover .code {
                    background-color: #e0e0e0;
                }
                
                .copy-container::after {
                    content: "📋";
                    margin-left: 5px;
                    font-size: 0.9em;
                    opacity: 0.6;
                }
                
                .copy-container:hover::after {
                    opacity: 1;
                }
                
                .copy-container .tooltip {
                    visibility: hidden;
                    background-color: #555;
                    color: #fff;
                    text-align: center;
                    border-radius: 6px;
                    padding: 5px;
                    position: absolute;
                    z-index: 1;
                    bottom: 100%;
                    left: 50%;
                    margin-left: -75px;
                    opacity: 0;
                    transition: opacity 0.3s;
                    font-size: 14px;
                    font-family: sans-serif;
                    pointer-events: none;
                }
                
                .copy-container .tooltip.show {
                    visibility: visible;
                    opacity: 1;
                }
                details {
                    margin: 5px 0;
                    border: 1px solid #eee;
                    border-radius: 4px;
                }
                summary {
                    padding: 10px;
                    cursor: pointer;
                    background-color: #f5f5f5;
                }
                details[open] summary {
                    border-bottom: 1px solid #eee;
                }
                .details-content {
                    padding: 10px;
                }
                .collapsible {
                    margin-top: 5px;
                }
                .filters {
                    display: flex;
                    flex-wrap: wrap;
                    gap: 15px;
                    background-color: #f9f9f9;
                    padding: 15px;
                    border-radius: 4px;
                    margin: 20px 0;
                    border: 1px solid #ddd;
                }
                .filter-dropdown {
                    position: relative;
                    min-width: 200px;
                    flex: 1;
                }
                .dropdown-button {
                    width: 100%;
                    background-color: white;
                    border: 1px solid #ddd;
                    padding: 8px 12px;
                    text-align: left;
                    border-radius: 4px;
                    cursor: pointer;
                    font-weight: bold;
                    position: relative;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                }
                .dropdown-button:hover {
                    background-color: #f5f5f5;
                }
                .dropdown-button:after {
                    content: "▼";
                    font-size: 10px;
                    margin-left: 10px;
                }
                .dropdown-content {
                    display: none;
                    position: absolute;
                    background-color: white;
                    min-width: 100%;
                    max-height: 300px;
                    overflow-y: auto;
                    z-index: 10;
                    border: 1px solid #ddd;
                    border-radius: 4px;
                    margin-top: 2px;
                    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
                }
                .dropdown-content.show {
                    display: block;
                }
                .dropdown-header {
                    padding: 8px 12px;
                    border-bottom: 1px solid #eee;
                    font-weight: bold;
                    background-color: #f9f9f9;
                    cursor: pointer;
                }
                .dropdown-header:hover {
                    background-color: #f0f0f0;
                }
                .dropdown-item {
                    padding: 8px 12px;
                    display: block;
                    cursor: pointer;
                    border-bottom: 1px solid #f5f5f5;
                }
                .dropdown-item:hover {
                    background-color: #f5f5f5;
                }
                .dropdown-item input[type="checkbox"] {
                    margin-right: 8px;
                }
                .search-container {
                    padding: 8px;
                    border-bottom: 1px solid #eee;
                }
                .search-container input {
                    width: 100%;
                    padding: 6px 8px;
                    border: 1px solid #ddd;
                    border-radius: 4px;
                }
                .summary-card.disabled {
                    opacity: 0.6;
                    cursor: not-allowed;
                    border-left-width: 2px;
                }
                .selected-count {
                    background-color: #3498db;
                    color: white;
                    border-radius: 12px;
                    padding: 2px 6px;
                    font-size: 12px;
                    font-weight: bold;
                    margin-left: 8px;
                }
                .no-results {
                    padding: 15px;
                    text-align: center;
                    color: #777;
                    font-style: italic;
                }
                .hidden {
                    display: none;
                }
                .tag-container {
                    margin: 8px 0;
                }
                
                .tag {
                    display: inline-block;
                    background-color: #f0f0f0;
                    border-radius: 4px;
                    padding: 2px 6px;
                    margin-right: 6px;
                    margin-bottom: 4px;
                    font-size: 0.9em;
                }
                .copyable {
                    position: relative;
                    display: inline-flex;
                    align-items: center;
                    cursor: pointer;
                    border-radius: 4px;
                    padding: 2px 8px;
                    margin: -2px 0;
                    transition: background-color 0.2s;
                }
                
                .copyable:hover {
                    background-color: #f0f0f0;
                }
                
                .copyable::after {
                    content: "📋";
                    font-size: 14px;
                    margin-left: 6px;
                    opacity: 0.7;
                }
                
                .copyable .tooltip {
                    position: absolute;
                    top: -30px;
                    left: 50%;
                    transform: translateX(-50%);
                    background-color: rgba(0, 0, 0, 0.8);
                    color: white;
                    padding: 4px 8px;
                    border-radius: 4px;
                    font-size: 12px;
                    opacity: 0;
                    transition: opacity 0.2s;
                    pointer-events: none;
                    white-space: nowrap;
                }
                
                .copyable:hover .tooltip {
                    opacity: 0.9;
                }
                
                .selector-wrapper {
                    display: flex;
                    align-items: flex-start;
                    position: relative;
                }
                
                .selector-text {
                    flex-grow: 1;
                    overflow-x: auto;
                }
                
                .copy-icon {
                    margin-left: 8px;
                    cursor: pointer;
                    color: #555;
                    font-size: 18px;
                    padding: 4px;
                    border-radius: 4px;
                    transition: all 0.2s ease;
                }
                
                .copy-icon:hover {
                    background-color: #f0f0f0;
                    color: #000;
                }
                
                .copy-icon .tooltip {
                    visibility: hidden;
                    width: 80px;
                    background-color: rgba(0, 0, 0, 0.8);
                    color: #fff;
                    text-align: center;
                    border-radius: 6px;
                    padding: 5px;
                    position: absolute;
                    z-index: 1;
                    bottom: 125%;
                    left: 50%;
                    margin-left: -40px;
                    opacity: 0;
                    transition: opacity 0.3s;
                    font-size: 12px;
                    pointer-events: none;
                }
                
                .copy-icon:hover .tooltip {
                    visibility: visible;
                    opacity: 1;
                }
            `;

            // Create a function to collect all unique tags across results
            const collectAllTags = () => {
                const allTags = new Set();
                
                // Only collect tags from sections that will be shown
                if (serviceOptions.showSections.violations && results.violations) {
                    results.violations.forEach(violation => {
                        if (violation.tags) {
                            violation.tags.forEach(tag => allTags.add(tag));
                        }
                    });
                }
                
                if (serviceOptions.showSections.passes && results.passes) {
                    results.passes.forEach(pass => {
                        if (pass.tags) {
                            pass.tags.forEach(tag => allTags.add(tag));
                        }
                    });
                }
                
                if (serviceOptions.showSections.incomplete && results.incomplete) {
                    results.incomplete.forEach(item => {
                        if (item.tags) {
                            item.tags.forEach(tag => allTags.add(tag));
                        }
                    });
                }
                
                if (serviceOptions.showSections.inapplicable && results.inapplicable) {
                    results.inapplicable.forEach(item => {
                        if (item.tags) {
                            item.tags.forEach(tag => allTags.add(tag));
                        }
                    });
                }
                
                return Array.from(allTags).sort();
            };

            // Get all unique tags
            const allTags = collectAllTags();

            // Create the filters UI - only show filter options for visible sections
            const createFilters = () => {
                // Create impact filter dropdown
                const impactOptions = [
                    { value: 'critical', label: 'Critical' },
                    { value: 'serious', label: 'Serious' },
                    { value: 'moderate', label: 'Moderate' },
                    { value: 'minor', label: 'Minor' },
                    { value: 'unknown', label: 'Unknown' }
                ];
                
                const impactDropdown = `
                    <div class="filter-dropdown">
                        <button class="dropdown-button" data-filter-type="impact">
                            Impact <span class="selected-count">5/5</span>
                        </button>
                        <div class="dropdown-content" id="impact-dropdown">
                            <div class="dropdown-header" data-action="toggle-all" data-target="impact">
                                Uncheck All
                            </div>
                            ${impactOptions.map(option => `
                                <label class="dropdown-item">
                                    <input type="checkbox" name="impact" value="${option.value}" checked>
                                    ${option.label}
                                </label>
                            `).join('')}
                        </div>
                    </div>
                `;
                
                // Create type filter dropdown - only include visible section types
                const typeOptions = [];
                
                if (serviceOptions.showSections.violations) {
                    typeOptions.push({ value: 'violations', label: 'Violations' });
                }
                
                if (serviceOptions.showSections.passes) {
                    typeOptions.push({ value: 'passes', label: 'Passes' });
                }
                
                if (serviceOptions.showSections.incomplete) {
                    typeOptions.push({ value: 'incomplete', label: 'Incomplete' });
                }
                
                if (serviceOptions.showSections.inapplicable) {
                    typeOptions.push({ value: 'inapplicable', label: 'Inapplicable' });
                }
                
                const typeDropdown = typeOptions.length > 0 ? `
                    <div class="filter-dropdown">
                        <button class="dropdown-button" data-filter-type="type">
                            Result Type <span class="selected-count">${typeOptions.length}/${typeOptions.length}</span>
                        </button>
                        <div class="dropdown-content" id="type-dropdown">
                            <div class="dropdown-header" data-action="toggle-all" data-target="type">
                                Uncheck All
                            </div>
                            ${typeOptions.map(option => `
                                <label class="dropdown-item">
                                    <input type="checkbox" name="type" value="${option.value}" checked>
                                    ${option.label}
                                </label>
                            `).join('')}
                        </div>
                    </div>
                ` : '';
                
                // Create tag filter dropdown
                const tagDropdown = `
                    <div class="filter-dropdown">
                        <button class="dropdown-button" data-filter-type="tag">
                            Tags <span class="selected-count">${allTags.length}/${allTags.length}</span>
                        </button>
                        <div class="dropdown-content" id="tag-dropdown">
                            <div class="dropdown-header" data-action="toggle-all" data-target="tag">
                                Uncheck All
                            </div>
                            <div class="tags-list">
                                ${allTags.map(tag => `
                                    <label class="dropdown-item tag-item">
                                        <input type="checkbox" name="tag" value="${escapeHtml(tag)}" checked>
                                        ${escapeHtml(tag)}
                                    </label>
                                `).join('')}
                            </div>
                        </div>
                    </div>
                `;
                
                return `
                    <div class="filters">
                        ${typeDropdown}
                        ${impactDropdown}
                        ${tagDropdown}
                    </div>
                `;
            };

            // Generate the summary section - include counts for all result types,
            // but only make clickable/active the ones that are visible
            const createSummary = () => {
                return `
                    <div class="summary">
                        <div class="summary-card violations ${serviceOptions.showSections.violations ? '' : 'disabled'}" 
                             data-type="violations" ${serviceOptions.showSections.violations ? '' : 'title="Not displayed in this report"'}>
                            <h3>Violations</h3>
                            <div class="card-count">${results.violations.length}</div>
                            <p>Accessibility issues that need to be fixed</p>
                        </div>
                        <div class="summary-card passes ${serviceOptions.showSections.passes ? '' : 'disabled'}" 
                             data-type="passes" ${serviceOptions.showSections.passes ? '' : 'title="Not displayed in this report"'}>
                            <h3>Passes</h3>
                            <div class="card-count">${results.passes.length}</div>
                            <p>Tests that passed</p>
                        </div>
                        <div class="summary-card incomplete ${serviceOptions.showSections.incomplete ? '' : 'disabled'}" 
                             data-type="incomplete" ${serviceOptions.showSections.incomplete ? '' : 'title="Not displayed in this report"'}>
                            <h3>Incomplete</h3>
                            <div class="card-count">${results.incomplete.length}</div>
                            <p>Tests that need manual review</p>
                        </div>
                        <div class="summary-card inapplicable ${serviceOptions.showSections.inapplicable ? '' : 'disabled'}" 
                             data-type="inapplicable" ${serviceOptions.showSections.inapplicable ? '' : 'title="Not displayed in this report"'}>
                            <h3>Inapplicable</h3>
                            <div class="card-count">${results.inapplicable.length}</div>
                            <p>Tests that did not apply to the page</p>
                        </div>
                    </div>
                `;
            };

            // Create HTML for tags
            const createTagsHtml = (tags) => {
                if (!tags || tags.length === 0) return '';
                
                return `
                    <div class="tag-container">
                        <strong>Tags:</strong> 
                        ${tags.map(tag => `<span class="tag">${escapeHtml(tag)}</span>`).join(' ')}
                    </div>
                `;
            };

            // Generate HTML for each node in a result
            const createNodeHtml = (node) => {
                const elementHtml = node.html ? `
                    <div class="element-html">
                        <h4>HTML:</h4>
                        <pre><code>${escapeHtml(node.html)}</code></pre>
                    </div>
                ` : '';
                
                // Safely handle CSS selector display with a clipboard icon
                let cssSelector = '';
                if (node.target && Array.isArray(node.target) && node.target.length > 0) {
                    const selectorText = typeof node.target[0] === 'string' 
                        ? node.target[0] 
                        : JSON.stringify(node.target[0]);
                        
                    cssSelector = `
                        <div class="selector-container">
                            <h4>CSS Selector:</h4>
                            <div class="selector-wrapper">
                                <pre class="selector-text"><code>${escapeHtml(selectorText)}</code></pre>
                                <span class="copy-icon" data-selector="${escapeHtml(selectorText)}">
                                    📋
                                    <span class="tooltip">Click to copy</span>
                                </span>
                            </div>
                        </div>
                    `;
                }
                
                // Safely handle XPath selector display with a clipboard icon
                let xpathSelector = '';
                if (node.xpath) {
                    xpathSelector = `
                        <div class="selector-container">
                            <h4>XPath:</h4>
                            <div class="selector-wrapper">
                                <pre class="selector-text"><code>${escapeHtml(node.xpath)}</code></pre>
                                <span class="copy-icon" data-selector="${escapeHtml(node.xpath)}">
                                    📋
                                    <span class="tooltip">Click to copy</span>
                                </span>
                            </div>
                        </div>
                    `;
                }
                
                let html = `<div class="node">`;
                
                html += elementHtml;
                html += cssSelector;
                html += xpathSelector;
                
                if (node.failureSummary) {
                    html += `
                        <details>
                            <summary>Failure Summary</summary>
                            <div class="details-content">
                                <pre>${escapeHtml(node.failureSummary)}</pre>
                            </div>
                        </details>
                    `;
                }
                
                html += `</div>`;
                return html;
            };

            // Generic function to create HTML for any result item
            const createResultItemHtml = (item, type) => {
                const impactClass = item.impact || type;
                const impactLabel = item.impact ? item.impact.charAt(0).toUpperCase() + item.impact.slice(1) : type.charAt(0).toUpperCase() + type.slice(1);
                
                return `
                    <div class="result-item ${impactClass}" 
                         data-type="${type}" 
                         data-impact="${item.impact || 'none'}"
                         data-tags="${item.tags ? item.tags.join(' ') : ''}">
                        <h3>
                            <span class="impact ${impactClass}">${impactLabel}</span>
                            ${escapeHtml(item.id)}
                        </h3>
                        <div class="result-details">
                            <div class="rule-desc">${escapeHtml(item.description)}</div>
                            <a href="${item.helpUrl}" class="help-link" target="_blank">Learn more about this rule</a>
                            
                            ${createTagsHtml(item.tags)}
                            
                            <details class="collapsible">
                                <summary>Affected Elements (${item.nodes ? item.nodes.length : 0})</summary>
                                <div class="details-content">
                                    <div class="nodes">
                                        ${item.nodes ? item.nodes.map(createNodeHtml).join('') : 'No elements affected'}
                                    </div>
                                </div>
                            </details>
                        </div>
                    </div>
                `;
            };

            // Generate violations section
            const createViolationsSection = () => {
                if (!results.violations || results.violations.length === 0) {
                    return `<div class="section-container violations-container">
                                <h2>Violations</h2>
                                <div><p>No violations found. Great job!</p></div>
                            </div>`;
                }

                // Group violations by impact
                const violationsByImpact = {
                    critical: results.violations.filter(v => v.impact === 'critical'),
                    serious: results.violations.filter(v => v.impact === 'serious'),
                    moderate: results.violations.filter(v => v.impact === 'moderate'),
                    minor: results.violations.filter(v => v.impact === 'minor'),
                    unknown: results.violations.filter(v => !v.impact)
                };

                let html = `<div class="section-container violations-container">
                            <h2>Violations (${results.violations.length})</h2>`;
                
                // Critical violations
                if (violationsByImpact.critical.length > 0) {
                    html += `
                        <h3>Critical Violations (${violationsByImpact.critical.length})</h3>
                        <p>These issues have a severe impact on users with disabilities and should be fixed immediately.</p>
                        ${violationsByImpact.critical.map(v => createResultItemHtml(v, 'violations')).join('')}
                    `;
                }
                
                // Serious violations
                if (violationsByImpact.serious.length > 0) {
                    html += `
                        <h3>Serious Violations (${violationsByImpact.serious.length})</h3>
                        <p>These issues have a significant impact on users with disabilities.</p>
                        ${violationsByImpact.serious.map(v => createResultItemHtml(v, 'violations')).join('')}
                    `;
                }
                
                // Moderate violations
                if (violationsByImpact.moderate.length > 0) {
                    html += `
                        <h3>Moderate Violations (${violationsByImpact.moderate.length})</h3>
                        <p>These issues have a moderate impact on users with disabilities.</p>
                        ${violationsByImpact.moderate.map(v => createResultItemHtml(v, 'violations')).join('')}
                    `;
                }
                
                // Minor violations
                if (violationsByImpact.minor.length > 0) {
                    html += `
                        <h3>Minor Violations (${violationsByImpact.minor.length})</h3>
                        <p>These issues have a minor impact on users with disabilities.</p>
                        ${violationsByImpact.minor.map(v => createResultItemHtml(v, 'violations')).join('')}
                    `;
                }
                
                // Unknown impact violations
                if (violationsByImpact.unknown.length > 0) {
                    html += `
                        <h3>Other Violations (${violationsByImpact.unknown.length})</h3>
                        <p>These issues have an unknown impact level.</p>
                        ${violationsByImpact.unknown.map(v => createResultItemHtml(v, 'violations')).join('')}
                    `;
                }
                
                html += `</div>`;
                return html;
            };

            // Generate passes section
            const createPassesSection = () => {
                if (!results.passes || results.passes.length === 0) {
                    return `<div class="section-container passes-container">
                                <h2>Passes</h2>
                                <div><p>No passing tests found.</p></div>
                            </div>`;
                }

                return `
                    <div class="section-container passes-container">
                        <h2>Passes (${results.passes.length})</h2>
                        <p>These tests have passed and indicate accessible features.</p>
                        ${results.passes.map(p => createResultItemHtml(p, 'passes')).join('')}
                    </div>
                `;
            };

            // Generate incomplete section
            const createIncompleteSection = () => {
                if (!results.incomplete || results.incomplete.length === 0) {
                    return `<div class="section-container incomplete-container">
                                <h2>Incomplete</h2>
                                <div><p>No incomplete tests found.</p></div>
                            </div>`;
                }

                return `
                    <div class="section-container incomplete-container">
                        <h2>Incomplete (${results.incomplete.length})</h2>
                        <p>These tests require manual review to determine if they pass or fail.</p>
                        ${results.incomplete.map(i => createResultItemHtml(i, 'incomplete')).join('')}
                    </div>
                `;
            };

            // Generate inapplicable section
            const createInapplicableSection = () => {
                if (!results.inapplicable || results.inapplicable.length === 0) {
                    return `<div class="section-container inapplicable-container">
                                <h2>Inapplicable</h2>
                                <div><p>No inapplicable tests found.</p></div>
                            </div>`;
                }

                return `
                    <div class="section-container inapplicable-container">
                        <h2>Inapplicable (${results.inapplicable.length})</h2>
                        <p>These tests did not apply to any elements on the page.</p>
                        ${results.inapplicable.map(i => createResultItemHtml(i, 'inapplicable')).join('')}
                    </div>
                `;
            };

            // Helper function to escape HTML
            function escapeHtml(unsafe) {
                if (!unsafe) return '';
                return unsafe
                    .toString()
                    .replace(/&/g, "&amp;")
                    .replace(/</g, "&lt;")
                    .replace(/>/g, "&gt;")
                    .replace(/"/g, "&quot;")
                    .replace(/'/g, "&#039;");
            }

            // URL being tested
            const testedUrl = results.url || 'Unknown URL';
            
            // Check for logged in user
            const loggedInUser = browserConfig.loggedInUser || null;

            // Add JavaScript for filtering and copy functionality
            const jsCode = `
                document.addEventListener('DOMContentLoaded', function() {
                    initializeDropdowns();
                    initializeCopyToClipboard();
                    initializeFilters();
                    initializeSummaryCards();
                });
                
                function initializeDropdowns() {
                    // Handle dropdown toggling
                    const dropdownButtons = document.querySelectorAll('.dropdown-button');
                    
                    dropdownButtons.forEach(button => {
                        button.addEventListener('click', function() {
                            const dropdownContent = this.nextElementSibling;
                            
                            // Close all other dropdowns
                            document.querySelectorAll('.dropdown-content.show').forEach(openDropdown => {
                                if (openDropdown !== dropdownContent) {
                                    openDropdown.classList.remove('show');
                                }
                            });
                            
                            // Toggle this dropdown
                            dropdownContent.classList.toggle('show');
                        });
                    });
                    
                    // Close dropdowns when clicking outside
                    document.addEventListener('click', function(event) {
                        if (!event.target.matches('.dropdown-button') && 
                            !event.target.closest('.dropdown-content')) {
                            document.querySelectorAll('.dropdown-content.show').forEach(dropdown => {
                                dropdown.classList.remove('show');
                            });
                        }
                    });
                    
                    // Handle toggle-all functionality
                    const toggleAllButtons = document.querySelectorAll('[data-action="toggle-all"]');
                    
                    toggleAllButtons.forEach(button => {
                        button.addEventListener('click', function() {
                            const targetType = this.getAttribute('data-target');
                            const checkboxes = document.querySelectorAll(\`input[name="\${targetType}"]\`);
                            const allChecked = Array.from(checkboxes).every(cb => cb.checked);
                            
                            checkboxes.forEach(checkbox => {
                                checkbox.checked = !allChecked;
                            });
                            
                            // Update button text
                            this.textContent = allChecked ? 'Check All' : 'Uncheck All';
                            
                            // Update the count in the dropdown button
                            updateSelectedCount(targetType);
                            
                            // Apply filters
                            applyFilters();
                        });
                    });
                }
                
                function updateSelectedCount(filterType) {
                    const checkboxes = document.querySelectorAll(\`input[name="\${filterType}"]\`);
                    const checkedCount = Array.from(checkboxes).filter(cb => cb.checked).length;
                    const totalCount = checkboxes.length;
                    
                    const countElement = document.querySelector(\`[data-filter-type="\${filterType}"] .selected-count\`);
                    if (countElement) {
                        countElement.textContent = \`\${checkedCount}/\${totalCount}\`;
                    }
                    
                    // Update the toggle-all button text
                    const toggleButton = document.querySelector(\`[data-action="toggle-all"][data-target="\${filterType}"]\`);
                    if (toggleButton) {
                        toggleButton.textContent = checkedCount === totalCount ? 'Uncheck All' : 'Check All';
                    }
                }
                
                function initializeCopyToClipboard() {
                    // Handle copy icons for selectors
                    document.querySelectorAll('.copy-icon').forEach(icon => {
                        icon.addEventListener('click', function() {
                            const selector = this.getAttribute('data-selector');
                            const tooltip = this.querySelector('.tooltip');
                            
                            // Copy to clipboard
                            const textarea = document.createElement('textarea');
                            textarea.value = selector;
                            textarea.setAttribute('readonly', '');
                            textarea.style.position = 'absolute';
                            textarea.style.left = '-9999px';
                            document.body.appendChild(textarea);
                            textarea.select();
                            document.execCommand('copy');
                            document.body.removeChild(textarea);
                            
                            // Update tooltip text
                            if (tooltip) {
                                tooltip.textContent = 'Copied!';
                                setTimeout(() => {
                                    tooltip.textContent = 'Click to copy';
                                }, 2000);
                            }
                        });
                    });
                    
                    // Handle copyable elements like usernames
                    document.querySelectorAll('.copyable').forEach(el => {
                        el.addEventListener('click', function() {
                            const textToCopy = this.getAttribute('data-copy');
                            const tooltip = this.querySelector('.tooltip');
                            
                            const textarea = document.createElement('textarea');
                            textarea.value = textToCopy;
                            textarea.setAttribute('readonly', '');
                            textarea.style.position = 'absolute';
                            textarea.style.left = '-9999px';
                            document.body.appendChild(textarea);
                            textarea.select();
                            document.execCommand('copy');
                            document.body.removeChild(textarea);
                            
                            if (tooltip) {
                                tooltip.textContent = 'Copied!';
                                setTimeout(() => {
                                    tooltip.textContent = 'Click to copy';
                                }, 2000);
                            }
                        });
                    });
                }
                
                function initializeFilters() {
                    // Get all checkboxes
                    const typeCheckboxes = document.querySelectorAll('input[name="type"]');
                    const impactCheckboxes = document.querySelectorAll('input[name="impact"]');
                    const tagCheckboxes = document.querySelectorAll('input[name="tag"]');
                    
                    // Add event listeners to all checkboxes
                    typeCheckboxes.forEach(checkbox => {
                        checkbox.addEventListener('change', function() {
                            updateSelectedCount('type');
                            applyFilters();
                        });
                    });
                    
                    impactCheckboxes.forEach(checkbox => {
                        checkbox.addEventListener('change', function() {
                            updateSelectedCount('impact');
                            applyFilters();
                        });
                    });
                    
                    tagCheckboxes.forEach(checkbox => {
                        checkbox.addEventListener('change', function() {
                            updateSelectedCount('tag');
                            applyFilters();
                        });
                    });
                    
                    // Apply filters initially
                    applyFilters();
                }
                
                function initializeSummaryCards() {
                    const summaryCards = document.querySelectorAll('.summary-card:not(.disabled)');
                    
                    summaryCards.forEach(card => {
                        card.addEventListener('click', function() {
                            const type = this.getAttribute('data-type');
                            
                            // Uncheck all type checkboxes
                            document.querySelectorAll('input[name="type"]').forEach(checkbox => {
                                checkbox.checked = false;
                            });
                            
                            // Check only the clicked type
                            const typeCheckbox = document.querySelector('input[name="type"][value="' + type + '"]');
                            if (typeCheckbox) {
                                typeCheckbox.checked = true;
                            }
                            
                            // Apply filters
                            applyFilters();
                            
                            // Scroll to the section
                            const section = document.querySelector('.' + type + '-container');
                            if (section) {
                                section.scrollIntoView({ behavior: 'smooth', block: 'start' });
                            }
                        });
                    });
                }
                
                function applyFilters() {
                    // Get selected filter values
                    const selectedTypes = Array.from(document.querySelectorAll('input[name="type"]:checked')).map(cb => cb.value);
                    const selectedImpacts = Array.from(document.querySelectorAll('input[name="impact"]:checked')).map(cb => cb.value);
                    const selectedTags = Array.from(document.querySelectorAll('input[name="tag"]:checked')).map(cb => cb.value);
                    
                    // Hide/show section containers based on type filter
                    document.querySelectorAll('.section-container').forEach(section => {
                        const sectionType = section.classList[1].split('-')[0]; // Get section type from class
                        if (selectedTypes.includes(sectionType)) {
                            section.classList.remove('hidden');
                        } else {
                            section.classList.add('hidden');
                        }
                    });
                    
                    // Filter individual result items
                    document.querySelectorAll('.result-item').forEach(item => {
                        const itemType = item.getAttribute('data-type');
                        const itemImpact = item.getAttribute('data-impact');
                        const itemTagsStr = item.getAttribute('data-tags');
                        const itemTags = itemTagsStr ? itemTagsStr.split(' ') : [];
                        
                        // Check if the item type is selected
                        const typeMatch = selectedTypes.includes(itemType);
                        
                        // Check if the item impact is selected or if it has no impact
                        const impactMatch = itemImpact === 'none' || selectedImpacts.includes(itemImpact);
                        
                        // Check if any of the item's tags are selected
                        let tagMatch = true;
                        if (itemTags.length > 0 && selectedTags.length > 0) {
                            tagMatch = itemTags.some(tag => selectedTags.includes(tag));
                        }
                        
                        // Apply visibility based on all filters
                        if (typeMatch && impactMatch && tagMatch) {
                            item.classList.remove('hidden');
                        } else {
                            item.classList.add('hidden');
                        }
                    });
                    
                    // Update summary card active state
                    updateSummaryCardActiveState();
                    
                    // Check if there are any visible results
                    checkForNoResults();
                    
                    // Update the counts
                    updateSelectedCount('type');
                    updateSelectedCount('impact');
                    updateSelectedCount('tag');
                }
                
                function updateSummaryCardActiveState() {
                    const selectedTypes = Array.from(document.querySelectorAll('input[name="type"]:checked')).map(cb => cb.value);
                    
                    document.querySelectorAll('.summary-card').forEach(card => {
                        const cardType = card.getAttribute('data-type');
                        if (selectedTypes.includes(cardType) && selectedTypes.length === 1) {
                            card.classList.add('active');
                        } else {
                            card.classList.remove('active');
                        }
                    });
                }
                
                function checkForNoResults() {
                    document.querySelectorAll('.section-container').forEach(section => {
                        if (!section.classList.contains('hidden')) {
                            const visibleItems = section.querySelectorAll('.result-item:not(.hidden)');
                            const noResultsDiv = section.querySelector('.no-results');
                            
                            if (visibleItems.length === 0) {
                                // Create no results message if it doesn't exist
                                if (!noResultsDiv) {
                                    const newNoResultsDiv = document.createElement('div');
                                    newNoResultsDiv.className = 'no-results';
                                    newNoResultsDiv.textContent = 'No results match the current filters';
                                    section.appendChild(newNoResultsDiv);
                                }
                            } else {
                                // Remove no results message if it exists
                                if (noResultsDiv) {
                                    noResultsDiv.remove();
                                }
                            }
                        }
                    });
                }
            `;

            // Generate HTML for each result section, but only include if configured to show
            let sectionsHtml = '';
            
            if (serviceOptions.showSections.violations) {
                sectionsHtml += createViolationsSection();
            }
            
            if (serviceOptions.showSections.passes) {
                sectionsHtml += createPassesSection();
            }
            
            if (serviceOptions.showSections.incomplete) {
                sectionsHtml += createIncompleteSection();
            }
            
            if (serviceOptions.showSections.inapplicable) {
                sectionsHtml += createInapplicableSection();
            }

            // Full HTML report with filtering and copy functionality
            return `
                <!DOCTYPE html>
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <meta name="viewport" content="width=device-width, initial-scale=1.0">
                    <title>Accessibility Test Report</title>
                    <style>${css}</style>
                </head>
                <body>
                    <h1>Accessibility Test Report</h1>
                    <p>URL tested: <strong><a href="${escapeHtml(testedUrl)}" target="_blank">${escapeHtml(testedUrl)}</a></strong></p>
                    <p>Test date: <strong>${new Date().toLocaleString()}</strong></p>
                    ${loggedInUser ? `<p>Logged in as: <span class="copyable" data-copy="${escapeHtml(loggedInUser)}"><strong>${escapeHtml(loggedInUser)}</strong><span class="tooltip">Click to copy</span></span></p>` : ''}
                    
                    ${createSummary()}
                    
                    ${createFilters()}
                    
                    <div class="results-container">
                        ${sectionsHtml}
                    </div>
                    
                    <script>${jsCode}</script>
                </body>
                </html>
            `;
        }
    }
    
    // We no longer need the afterTest hook to check accessibility thresholds
    // So we can remove or simplify it:
    afterTest() {
        // No longer needed for accessibility checks
    }
    
    // Cleanup methods
    after() {
        // No longer need to clean up accessibilityResults
    }
    
    afterSession() {
        // Nothing to clean up
    }
} 