$(document).ready(function() {
    if (Variables.IsChangelogPage) {
        $('#wh_publication_toc').remove();
        PrependClToc();
        CreateHeadingParasAndLists();
        CreateNewToc();
        ModifyCSS();
        if (Variables.IsAuthoring) {
            sortChangelogNewFeatures();
            sortChangelogNavEnhancements();
            sortChangelogNavDefects();
            NumberOfReleaseNotes();
        }

        // #region changelog ec
        $('.simpletable').each(function () {
            var x = Math.floor(Math.random() * 10000);
            $(this).find('.rntitle').first().addClass('parent').attr('id', x).css('border-bottom','0');
            // add type button
            var TypeFullText = $(this).find("li").first().text();
            var trimType = $.trim(TypeFullText);
            var type = trimType.split(" ").pop();
            var truncated = type.substr(0, 3);
            $(this).find('.rntitle').first().prepend ('<span class="clType ' + type + '">' + truncated + '</span');
            $(this).find('tbody > tr').each(function() {
                $(this).attr('class', ('child-' + x))
            });
        });

        $('th.parent')  
            .css("cursor", "pointer")  
            .attr("title", "Click to expand/collapse")  
            .click(function () {  
                var id = $(this).attr('id');
                var childId = 'child-' + id;
                $('.' + childId).toggle('slow');
            });
            
            
        $('.simpletable > tbody > tr[class*="child-"]').toggle();
        $('.-').css({'margin-top':'0'});
        $('section div.-').css({'display' : 'block'});
        $('.simpletable-container').css({'border-bottom' : 'none'});
        $('.wh_topic_toc').hide();        // Create Changelog Tools from the clToc
        const changelogToolsHtml = `
            <h4 id='CLToolsHeading'>Changelog Tools</h4>
            <h5 id='CLToolsPara'>Filter</h5>
            <div class='btn-group' id='FilterButtons' role='group' aria-label='Filter Buttons'>
                <button type='button' class='btn btn-primary' title='Show only Feature release notes' onclick='FilterFeature();'>Features</button>
                <button type='button' class='btn btn-success' title='Show only Enhancement release notes' onclick='FilterEnhancement();'>Enhancements</button>
                <button type='button' class='btn btn-danger' title='Show only Defects release notes' onclick='FilterDefect()'>Defects</button>
                <button type='button' class='btn btn-secondary' onclick='ShowAllTables()'>Reset</button>
            </div>
            <h5 id='CLToolsPara'>Folding</h5>
            <div class='btn-group' id='FoldingButtons' role='group' aria-label='Folding Buttons'>
                <button type='button' class='btn btn-primary' title='Show all release notes' onclick='ShowAll()'><i class='bi bi-chevron-double-down'></i> Show All</button>
                <button type='button' class='btn btn-primary' title='Hide all release notes' onclick='HideAll()'><i class='bi bi-chevron-double-up'></i> Hide all</button>
                <button type='button' class='btn btn-primary' data-html='true' title='Show hidden release notes, Hide visible release notes' onclick='ToggleParents()'><i class='bi bi-toggles'></i> Toggle all</button>
            </div>
            <button type='button' class='btn btn-info ms-2' id='CopyToClipboardBtn' title='Copy selected text to clipboard' onclick='CopyTextToClipboard()'><i class='bi bi-clipboard'></i></button>
        `;
        $('.clToc').empty().attr('id', 'clToc').append(changelogToolsHtml);// Create a function to position the tools at the correct fixed position
        function setupFixedPosition() {
            var placeholder = $('.clToc-placeholder');
            
            if (placeholder.length) {
                var placeholderPos = placeholder.offset();
                
                // Get the header height or other top elements
                var headerOffset = $('.wh_header').outerHeight() || 0;
                var topNavOffset = $('.wh_top_menu_and_indexterms_link').outerHeight() || 0;
                var breadcrumbOffset = $('.wh_breadcrumb').outerHeight() || 0;
                var additionalOffset = 20; // Additional padding
                
                // Calculate the total top offset needed
                var topOffset = headerOffset + topNavOffset + breadcrumbOffset + additionalOffset;
                
                // Ensure we're not positioning it too high
                if (topOffset < 207) {
                    topOffset = 207; // Minimum offset based on observed issue
                }
                
                console.log('Positioning clToc with top offset:', topOffset);
                  // Apply fixed positioning to the changelog tools based on the placeholder's position
                $('.clToc').css({
                    'position': 'fixed',
                    'top': topOffset + 'px',
                    'left': placeholderPos.left + 'px',
                    'width': placeholder.width() + 'px', // Match placeholder width
                    'max-height': 'calc(100vh - ' + (topOffset + 20) + 'px)', // Adjust max height based on top offset
                    'overflow-y': 'auto', // Add scrollbar if content is too tall
                    'z-index': 100 // Ensure it's above other content
                });
                
                // Add a safety check to ensure the changelog tools are visible
                setTimeout(function() {
                    var clTocPosition = $('.clToc').offset();
                    if (clTocPosition && clTocPosition.top < 0) {
                        console.log('Changelog tools positioned off-screen, adjusting...');
                        $('.clToc').css('top', '207px'); // Fallback to known good position
                    }
                }, 500);
            }
        }        // Style the placeholder to maintain layout
        $('.clToc-placeholder').css({
            'min-height': '1px', // Minimal height to ensure it takes space
            'visibility': 'hidden' // Hide it but keep its space in the layout
        });
        
        // Ensure the positioning is set after all elements are fully loaded
        $(window).on('load', function() {
            console.log('Window loaded, setting up fixed position');
            setupFixedPosition();
        });
        
        // Also set up immediately for faster response
        setTimeout(function() {
            setupFixedPosition();
        }, 100);
        
        // Update position on window resize and scroll
        $(window).on('resize scroll', function() {
            setupFixedPosition();
        });
        
        $('.simpletable > tbody > tr > td').css({ 'padding-left': '40px' });
        $('.btn_revision').parent().css('display', 'block');
        // #endregion

        // #region Filter
            // Create input box and buttons
        //Within wh_tools toolbar
        console.log($("#FilterButtons").length); // Should be > 0
        console.log("Inserting FilterContainer");
        const DefaultFilterInputText = "Enter text to start filtering";
        if ($("#FilterButtons").length) {
            $('<div class="FilterContainer">' +
                '<div id="FilterIntro" class="ph">Filter this page</div>' +
                '<div id="FilterControls">' +
                '<input type="text" id="filterText" value="' + DefaultFilterInputText + '" />' +
                '<input type="button" id="clearButton" value="Clear" />' +
                '</div>' +
                '</div>').insertBefore($("#FilterButtons"));
        } else {
            console.error("FilterButtons not found");
        }

        // Insert no match message
        const $noMatchMessage = $('<p id="noMatchMessage" style="color: red; display: none;">The term you typed is not available on this page.</p>');
        $noMatchMessage.insertAfter($('.FilterContainer'));

        $('.FilterContainer').css({
            'border': '1px solid rgba(0, 0, 0, 0.2)',
            'border-radius': '6px',
            'display': 'flex',
            'align-items': 'center',
            'margin-bottom': '10px',
            'width': '340px',
            'background-color': '#ecf2f9'
        });
        $('#FilterControls').css({
            'display': 'flex', // Use flexbox for layout
            'margin-top': '-10px',
            'margin-bottom': '4px',
            'flex-grow': '1', // Allow it to grow
            'width': '100%' // Ensure it takes full width
        });
        $('#filterText').css({
            'color': 'black',
            'font-size': 'smaller',
            'flex-grow': '1', // Allow the input to stretch
            'padding': '0 6px 0 6px',
            'margin-right': '5px',
            'border': 'none',
            'margin-top': '3px',
            'border-radius': '6px',
            // 'height': '36px', // Set a height to match the button if needed
            // 'line-height': '36px' // Center text vertically
        });
        $('#clearButton').css({
            'color': 'black',
            'font-size': 'small',
            'border-radius': '6px',
            'cursor': 'pointer',
            'margin-top': '4px',
            'background-color': '#ffffff',
            'border': '2px solid darkgrey',
            'margin-right': '4px',
        });
        $('#FilterIntro').css({
            'color': '#6d6d6d',
            'font-size': 'small',
            'font-weight': '500',
            'margin-right': '10px',
            'margin-left': '4px',
            'flex-shrink': '0' // Prevent wrapping by not allowing it to shrink
        });

        //Select all of the input box when it gets the focus
        $('#filterText').focus(function() {
            $(this).select();
        });
        
        // Cache jQuery selectors
        const $filterText = $('#filterText');
        const $tables = $('table');
        const $listItems = $('li');

        $filterText.on('keyup', function (e) {
            if (e.key === "Escape") {
                // Show tables
                $tables.show();
                // Show list items
                $listItems.show();
                // Clear text box
                $filterText.val('Enter text (case-sensitive)');
                $filterText.select();
                // Hide no match message
                $noMatchMessage.hide();
            } else {
                // Create the regular expression
                const regEx = new RegExp($.map($(this).val().trim().split(' '), function (v) {
                    return '(?=.*?' + v + ')';
                }).join(''), 'i');

                // Select all list items, hide and filter by the regex then show
                const newFeaturesMatch = $('#NewFeaturesList li').hide().filter(function () {
                    return regEx.exec($(this).text());
                }).show().length;

                const enhancementsMatch = $('#EnhancementsList li').hide().filter(function () {
                    return regEx.exec($(this).text());
                }).show().length;

                const defectsMatch = $('#DefectsList li').hide().filter(function () {
                    return regEx.exec($(this).text());
                }).show().length;

                const tablesMatch = $('.rntitle').closest('.simpletable').hide().filter(function () {
                    return regEx.exec($(this).text());
                }).show().length;

                if (newFeaturesMatch + enhancementsMatch + defectsMatch + tablesMatch === 0) {
                    $noMatchMessage.show();
                } else {
                    $noMatchMessage.hide();
                }
            }
        });

        $('#clearButton').click(function () {
            // Show tables
            $tables.show();
            // Show list items
            $listItems.show();
            // Clear text box
            $filterText.val(DefaultFilterInputText);
            $filterText.select();
            // Hide no match message
            $noMatchMessage.hide();
        });

        // #endregion
    }

});

function NumberOfReleaseNotes() {
    // Counting the number of .simpletable-container and .table-container elements
    var simpleTableCount = $('.simpletable-container').length;
    var tableCount = $('.table-container').length;
    var totalCount = simpleTableCount + tableCount;
    
    console.log('Number of .simpletable-container elements:', simpleTableCount);
    console.log('Number of .table-container elements:', tableCount);
    console.log('Total number of elements:', totalCount);
    
    // Selecting the target <p> element
    var targetP = $('h1#ariaid-title1').next('div').find('section').first().find('p').first();

    // Creating a span element for the totalCount and giving it an ID of 'RnCount'
    var countSpan = $('<span>', {
        id: 'RnCount',
        text: totalCount
    });

    // Creating a new span element with the totalCount span and the desired ID for the outer span
    var spanElement = $('<span>', {
        id: 'NumOfRNs',
        text: '   Number of release notes: '
    }).append(countSpan);

    // Appending the span element to the target <p> element
    targetP.append(spanElement);
}



function CreateHeadingParasAndLists() {
    $('.ChangelogNav').append('<p style="color: black"><b>New Features</b></p>' +
        '<ul id="NewFeaturesList"></ul>' +
        '<p style="color: black"><b>Enhancements</b></p>' +
        '<ul id="EnhancementsList"></ul>' +
        '<p style="color: black"><b>Defect Corrections</b></p>' +
        '<ul id="DefectsList"></ul>');
}

function CreateNewToc() {
    $(".simpletable").each(function () {
        var ReleasenoteEqualsDatarev = false;
    });
}

function FilterDefect() {
    $('table').show();
    $('.rntitle').each(function () {
        var text = $(this).closest('.simpletable').find('li:first').text();
        if (text.indexOf('Defect') === -1) {
            $(this).closest('table').hide();
        }
    });
}

function FilterEnhancement() {
    $('table').show();
    $('.rntitle').each(function () {
        var text = $(this).closest('.simpletable').find('li:first').text();
        if (text.indexOf('Enhancement') === -1) {
            $(this).closest('table').hide();
        }
    });
}

function FilterFeature() {
    $('table').show();
    $('.rntitle').each(function () {
        var text = $(this).closest('.simpletable').find('li:first').text();
        if (text.indexOf('Feature') === -1) {
            $(this).closest('table').hide();
        }
    });
}

function HideAll(){
    $('th.parent').each(function (index) {
        var id = $(this).attr('id');
        var childId = 'child-' + id;
        $('.' + childId).animate( { "opacity": "hide", top:"150"} , 800 );
    })
}

function InsertCurrentReleaseTitle() {
    if (Variables.IsPnP || IsWKHosted) {
        if (revLevel !== null) {
            $('.ChangelogNav').append('<p><b>Current Release:</b>  ' + revLevel + '</p>');
        } else {
            $('.ChangelogNav').append('<p><b>Current Release:</b>  </p>');
        }
    }
}

function ModifyCSS() { $('.ChangelogLink').css({ });
}

function PrependClToc() {
    $('#wh_topic_body').attr("class", "col-lg-8 col-sm-12");

    // Create a placeholder div to maintain page layout
    $('<div class="clToc-placeholder col-lg-4 d-none d-lg-block"></div>').insertAfter('#wh_topic_body');
    
    // Create the actual clToc element that will be fixed
    $('<nav class="clToc col-lg-4 d-none d-lg-block navbar d-print-none"><section class="section ChangelogNav" style="background-color: #C5C5C5; border-radius: 10px; padding: 10px 20px;"></section></nav>').appendTo('body');
}

function sortChangelogNavDefects() {
    var myDeflist = $('#DefectsList');
    var DefListItems = myDeflist.children('li').get();
    DefListItems.sort(function (a, b) {
        return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
    })
    $.each(DefListItems, function (idx, itm) {
        myDeflist.append(itm);
    });
}

function sortChangelogNavEnhancements() {
    var myEnhlist = $('#EnhancementsList');
    var EnhListItems = myEnhlist.children('li').get();
    EnhListItems.sort(function (a, b) {
        return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
    })
    $.each(EnhListItems, function (idx, itm) {
        myEnhlist.append(itm);
    });
}

function sortChangelogNewFeatures() {
    var myFeatlist = $('#NewFeaturesList');
    var NewFeatureListItems = myFeatlist.children('li').get();
    NewFeatureListItems.sort(function (a, b) {
        return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
    })
    $.each(NewFeatureListItems, function (idx, itm) {
        myFeatlist.append(itm);
    });
}

function ShowAll(){
    $('th.parent').each(function (index) {
        var id = $(this).attr('id');
        var childId = 'child-' + id;
        $('.' + childId).animate( { "opacity": "show", top:"150"} , 1000 );
    })
}

function ShowAllTables(){
    $('table').show();
}

function ToggleParents(){
    $('th.parent').each(function (index) {
        var id = $(this).attr('id');
        var childId = 'child-' + id;
        $('.' + childId).toggle('slow');
    })
}

function CopyTextToClipboard() {
    // Check if there is any selected text
    var selection = window.getSelection();
    if (!selection || selection.toString().trim() === '') {
        // No text is selected, show a prompt
        alert('Please select some text on the page to copy.');
        return;
    }
      // Get the selected HTML
    var range = selection.getRangeAt(0);
    var fragment = range.cloneContents();
    var div = document.createElement('div');
    div.appendChild(fragment);
    var html = div.innerHTML;    // First, let's identify and specially mark bulleted and numbered content
    html = html
        // Ensure we properly handle all list items within unordered lists
        .replace(/<ul[^>]*>([\s\S]*?)<\/ul>/gi, function(match, listContent) {
            return '<ul>' + listContent.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, function(liMatch, liContent) {
                return '<li>##BULLET_START##' + liContent + '##BULLET_END##</li>';
            }) + '</ul>';
        })
        
        // Handle any remaining individual list items (outside of proper lists)
        .replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, function(match, content) {
            return '<li>##BULLET_START##' + content + '##BULLET_END##</li>';
        })
        
        // Identify and mark any numbered lists (ol) specifically
        .replace(/<ol[^>]*>([\s\S]*?)<\/ol>/gi, function(match, listContent) {
            // Process each list item and add its number
            var counter = 1;
            return '<ol>' + listContent.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, function(liMatch, liContent) {
                var result = '<li>##NUMBER_' + counter + '_START##' + liContent + '##NUMBER_END##</li>';
                counter++;
                return result;
            }) + '</ol>';
        })
        
        // Handle numeric list patterns that might be in plain text (not in OL/LI tags)
        .replace(/(\s|^)(\d+)\.\s+([^\n<]+)/g, function(match, space, number, content) {
            return space + '##TEXT_NUMBER_' + number + '_START##' + content + '##TEXT_NUMBER_END##';
        });
    
    // Pre-process to mark positions for newlines before removing tags
    html = html
        // Mark paragraph breaks with special tokens
        .replace(/<\/p>\s*<p[^>]*>/gi, '##PARA_BREAK##')
        .replace(/<p[^>]*>/gi, '')
        .replace(/<\/p>/gi, '##PARA_BREAK##')
        
        // Mark div breaks
        .replace(/<\/div>\s*<div[^>]*>/gi, '##PARA_BREAK##')
        .replace(/<div[^>]*>/gi, '')
        .replace(/<\/div>/gi, '##PARA_BREAK##')
        
        // Mark heading breaks
        .replace(/<\/h[1-6]>\s*<h[1-6][^>]*>/gi, '##PARA_BREAK##')
        .replace(/<h[1-6][^>]*>/gi, '##PARA_BREAK##')
        .replace(/<\/h[1-6]>/gi, '##PARA_BREAK##')
          // Enhanced handling of list items
        .replace(/<\/li>\s*<li[^>]*>/gi, '##LIST_BREAK##')
        .replace(/<li[^>]*>(?!##NUMBER_|##BULLET_)/gi, '##BULLET##')  // Only replace li tags that haven't been marked
        .replace(/<\/li>/gi, '')  // Remove closing li tags without adding breaks
        .replace(/<ul[^>]*>/gi, '##UL_START##')  // Mark unordered list start
        .replace(/<\/ul>/gi, '##UL_END##')  // Mark unordered list end
        .replace(/<ol[^>]*>/gi, '##OL_START##')  // Mark ordered list start  
        .replace(/<\/ol>/gi, '##OL_END##')  // Mark ordered list end
        
    // Mark br tags and handle tables
        .replace(/<br[^>]*>/gi, '##LINE_BREAK##')
        .replace(/<\/tr>\s*<tr[^>]*>/gi, '##LINE_BREAK##')  // Handle table rows
        .replace(/<\/td>\s*<td[^>]*>/gi, '\t')  // Use tabs between table cells
          // Handle special document patterns
        .replace(/Summary:/gi, '##HEADER##Summary:')
        .replace(/Details:/gi, '##HEADER##Details:')
        .replace(/Solution:/gi, '##HEADER##Solution:')
        .replace(/Resolution:/gi, '##HEADER##Resolution:') // Keep Resolution as-is without replacing
        .replace(/What Was Affected:/gi, '##HEADER##What Was Affected:')
        .replace(/How to Verify:/gi, '##HEADER##How to Verify:')
        .replace(/Implementation Notes:/gi, '##HEADER##Implementation Notes:')
        
        // Mark strong/bold tags to preserve emphasis
        .replace(/<strong>|<b>/gi, '')
        .replace(/<\/strong>|<\/b>/gi, '')
        
        // Remove all remaining HTML tags
        .replace(/<[^>]*>/g, '');
      // Decode HTML entities
    html = html
        .replace(/&nbsp;/g, ' ')
        .replace(/&amp;/g, '&')
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&quot;/g, '"')
        .replace(/&apos;/g, "'");
      
    // Process whitespace (but preserve our marked tokens)
    html = html.replace(/\s+/g, ' ');
    
    // Preserve formatting for common documentation patterns
    html = html.replace(/([A-Za-z ]+):\s+/g, '$1: ');    // Handle special document patterns like "What Was Affected:" before general conversion
    html = html.replace(/([A-Za-z][A-Za-z\s]+):\s*##PARA_BREAK##/g, '$1:\n##PARA_BREAK##');
      // Process document headers with special formatting
    html = html.replace(/##HEADER##([^#]+)/g, function(match, header) {
        return '\n' + header + '\n';
    });
    
    // Process the specially marked bullet and numbered content
    html = html
        // Process all ##BULLET_START## and ##BULLET_END## markers first
        .replace(/##BULLET_START##([\s\S]*?)##BULLET_END##/g, function(match, content) {
            // Make sure to fully process these markers and add proper bullet point
            return '• ' + content.trim();
        })
        // Handle any remaining bullet markers (for safety)
        .replace(/##BULLET_START##|##BULLET_END##/g, '')
          // Handle numbered items - replace with the number + content
        .replace(/##NUMBER_(\d+)_START##([\s\S]*?)##NUMBER_END##/g, function(match, number, content) {
            return '##NUM_ITEM_' + number + '##' + content.trim();
        })
        // Process text-based numbered items
        .replace(/##TEXT_NUMBER_(\d+)_START##([\s\S]*?)##TEXT_NUMBER_END##/g, function(match, number, content) {
            return '##NUM_ITEM_' + number + '##' + content.trim();
        })
        // Direct processing for entries that might have numeric list markers but weren't tokenized
        .replace(/(\n|^)(\d+)\.\s+([^\n]+)/g, function(match, newline, number, content) {
            return newline + '##NUM_ITEM_' + number + '##' + content.trim();
        })
        // Clean up any remaining numbered markers (for safety)
        .replace(/##NUMBER_\d+_START##|##NUMBER_END##|##TEXT_NUMBER_\d+_START##|##TEXT_NUMBER_END##/g, '')
        
        // Identify standalone numbered lists (not marked by our special tokens)
        .replace(/(\d+)\.\s+/g, function(match, number) {
            return '##NUM_ITEM_' + number + '## ';
        });
      // Now restore the marked tokens with proper formatting
    var text = html
        // Handle paragraph and section breaks first
        .replace(/##PARA_BREAK##/g, '\n\n')
        
        // Handle list formatting
        .replace(/##UL_START##/g, '\n')  // Unordered list start
        .replace(/##UL_END##/g, '\n')    // Unordered list end
        .replace(/##OL_START##/g, '\n')  // Ordered list start
        .replace(/##OL_END##/g, '\n')    // Ordered list end
        
    // Apply bullet points consistently and ensure every list item has its marker
        .replace(/##BULLET##/g, '\n• ')
        
        // Add newlines after each list item
        .replace(/##LIST_BREAK##/g, '\n')
        
    // Process numbered items with proper formatting (ensure they start on a new line)
        .replace(/##NUM_ITEM_(\d+)##/g, function(match, number) {
            return '\n' + number + '. ';
        })
        
        // Fix consecutive numbered items to ensure proper formatting
        .replace(/(\d+\. [^\n]+)(\n+)(\d+\. )/g, '$1\n$3')
        
        // Handle line breaks
        .replace(/##LINE_BREAK##/g, '\n')
        
        // Clean up all remaining processing tokens
        .replace(/##BULLET_START##|##BULLET_END##/g, '')
        .replace(/##NUMBER_\d+_START##|##NUMBER_END##/g, '')
        .replace(/##TEXT_NUMBER_\d+_START##|##TEXT_NUMBER_END##/g, '')
        
        // Fix label/value pairs like "Solution:" to be on their own line
        .replace(/([A-Za-z][A-Za-z\s]+:)(\s*)([^\n])/g, '$1$2\n$3')
        
        // Clean up bullet point formatting
        // Make sure bullets always start on their own line
        .replace(/([^\n])• /g, '$1\n• ')
        
        // Remove excess whitespace between bullets and their content
        .replace(/• \s+/g, '• ')
        
        // Ensure consistent spacing between bullet items
        .replace(/\n{2,}• /g, '\n• ')
        
        // Make sure bullets after colons are properly formatted
        .replace(/(:\s*)\n*• /g, ':\n• ')
        
        // Fix excessive newlines while maintaining paragraph structure
        .replace(/\n{3,}/g, '\n\n')
        
        // Fix bullet point sequences to ensure each is on its own line
        .replace(/• ([^\n]+)([^\n• ])• /g, '• $1$2\n• ')
        
        // Improve handling of label/value pairs in documentation
        .replace(/(\w+):\s+([^\n]+)/g, function(match, label, value) {
            return label + ': ' + value.trim();
        })
        
        // Fix multi-line bullet points
        .replace(/• ([^\n]+)(\n)([^•\n])/g, '• $1 $3')
        
        // Final cleanup of any remaining whitespace issues
        .replace(/\n\s+/g, '\n')
        .trim();    // Special patterns handling for common document structures    // Handle the specific case with "What Was Affected:" followed by bullet points
    // Don't automatically add a bullet point after the heading - it will be handled by the actual list
    text = text.replace(/(What Was Affected:)([^\n•]*?)(\n)/g, '$1$2$3');        
    
    // Ensure the "Reviewed Conditions" pattern gets properly bulleted
    text = text.replace(/(What Was Affected:.*?\n)(• .*?\n)([^\n•]+Reviewed Conditions)/g, '$1$2• $3');
    
    // Specific handling for "How to Verify:" followed by numbered list items
    text = text.replace(/(How to Verify:)(\s*)([^1-9\n])/g, '$1\n$3');
    text = text.replace(/(How to Verify:)(\s*)(\n+)([^•\n])/g, '$1\n$4');
    
    // Ensure numbered lists after colons start on a new line
    text = text.replace(/(:)(\s+)(\d+\.)/g, '$1\n$3');
    
    // Proper numbered list formatting - ensure consecutive items are properly formatted
    text = text.replace(/(\d+\.)([^\n]+)(\n)(\d+\.)/g, '$1$2$3$4');
    
    // Apply final text normalization before copying
    text = normalizeClipboardText(text);    // Final scan for any missed bullet points in common patterns
    text = text.replace(/(\n)([A-Za-z][A-Za-z\s]*?Conditions and Iterators)/g, '$1• $2');    // Special case for "How to Verify:" section with numbered lists
    text = text.replace(/(How to Verify:)([^\n]*?)(\d+\.)/g, '$1\n$3');
    text = text.replace(/(How to Verify:)(\s*)(\n)/g, '$1\n');
    text = text.replace(/(CODING:|TODO:)( *?)(\n *?)/g, '$1$2\n');
      // Improve numbered list formatting specifically
    text = text.replace(/\n(\d+\.)(\s*)\n•\s/g, '\n$1$2');
    text = text.replace(/\n(\d+\.)(\s*)\n/g, '\n$1$2 ');
    
    // Ensure there's a space after each number in numbered lists
    text = text.replace(/(\d+\.)([^\s])/g, '$1 $2');
    
    // Make sure text is fully cleaned up before final processing
    text = cleanupProcessingTokens(text);// Final post-processing to fix remaining specific issues
    text = text
        // Fix issues with missing bullets in lists
        .replace(/(\n• [^\n]+\n)([^\n•\d][^\n]+)(\n• )/g, '$1• $2$3')
        
        // Remove any lone "Re" that appears on a line by itself
        .replace(/\n\s*Re\s*\n/g, '\n')
        
        // Fix issues with CODING: and TODO: breaking across lines
        .replace(/(CODING:)(\s*)(\n)/g, '$1 ')
        .replace(/(TODO:)(\s*)(\n)/g, '$1 ')
        
        // Fix numbered lists with bullet points - remove bullets from numbered items
        .replace(/\n• (\d+\.)\s+/g, '\n$1 ')
        
        // Preserve "Resolution:" instead of replacing with "Solution:"
        .replace(/Solution: /g, 'Resolution: ')
          // Remove unwanted "Implementation Notes:" if not in original
        .replace(/\s*Implementation Notes:.*$/, '');
      // Final sanity check to remove any processing tokens that might remain
    text = cleanupProcessingTokens(text);
    
    // Apply numbered list formatting fix
    text = fixNumberedLists(text);
    
    // Use modern Clipboard API with fallback to execCommand
    if (navigator.clipboard && navigator.clipboard.writeText) {
        // Modern approach using Clipboard API
        navigator.clipboard.writeText(text)
            .then(() => {
                showCopySuccess();
                console.log('Text copied successfully with improved formatting');
            })
            .catch(err => {
                console.error('Could not copy text: ', err);
                fallbackCopyTextToClipboard(text);
            });
    } else {
        // Fallback for browsers that don't support the Clipboard API
        fallbackCopyTextToClipboard(text);
    }
}

function fallbackCopyTextToClipboard(text) {
    // Create a temporary textarea to copy the text
    var $temp = $('<textarea>');
    $('body').append($temp);
    $temp.val(text).select();
    
    try {
        // Execute copy command
        var successful = document.execCommand('copy');
        if (successful) {
            showCopySuccess();
        } else {
            console.error('Failed to copy text');
        }
    } catch (err) {
        console.error('Copy to clipboard failed:', err);
    }
    
    // Remove the temporary textarea
    $temp.remove();
}

// Utility function to ensure all processing tokens are removed 
function cleanupProcessingTokens(text) {
    if (!text) {
        return text;
    }
    
    // First pass - look for any ## tokens and remove them
    text = text.replace(/##[A-Z0-9_]+##/g, '');
    
    // Second pass - look specifically for common marker tokens
    text = text
        .replace(/##BULLET_START##|##BULLET_END##/g, '')
        .replace(/##NUMBER_\d+_START##|##NUMBER_END##/g, '')
        .replace(/##TEXT_NUMBER_\d+_START##|##TEXT_NUMBER_END##/g, '')
        .replace(/##NUM_ITEM_\d+##/g, '')
        .replace(/##PARA_BREAK##/g, '\n')
        .replace(/##LINE_BREAK##/g, '\n')
        .replace(/##LIST_BREAK##/g, '\n')
        .replace(/##BULLET##/g, '• ')
        .replace(/##UL_START##|##UL_END##|##OL_START##|##OL_END##/g, '')
        .replace(/##HEADER##/g, '');
    
    // Third pass - look for any patterns with numbers in them
    text = text.replace(/##[A-Z_]+\d+[A-Z_]*##/g, '');
    text = text.replace(/##[A-Z_]*\d+[A-Z_]+##/g, '');
    
    // Final pass - look for any remaining ## pattern that might have been missed
    text = text.replace(/##[^#]*##/g, '');
    
    // Last resort - if we still have ## tokens, do a blind replace of anything between ##
    if (text.indexOf('##') !== -1) {
        text = text.replace(/##[^#]*?##/g, '');
    }
    
    return text;
}

// Utility function for normalizing whitespace in the final text
function normalizeClipboardText(text) {
    // First, remove any processing tokens that might have been missed
    text = cleanupProcessingTokens(text);
    
    return text
        // Fix the issue with too many consecutive line breaks
        .replace(/\n{3,}/g, '\n\n')      // Fix specific formatting pattern for "What Was Affected:" followed by bullet points
        .replace(/(What Was Affected:)(\s*)(\n+)/g, '$1\n')
        // Don't automatically add bullet points after section headers
        // .replace(/(What Was Affected:)(\s*)([^\n•])/g, '$1\n• $3')
        
        // Remove standalone "Re" line that sometimes appears
        .replace(/\n\s*Re\s*\n/g, '\n')
        
        // Ensure proper bullet formatting - first ensure bullets are on their own line
        .replace(/([^\n])• /g, '$1\n• ')
        
        // Make sure all bullets start with a newline
        .replace(/(^|[^\n])• /g, '$1\n• ')
        
        // Apply similar formatting to numbered items
        .replace(/([^\n])(\d+\. )/g, '$1\n$2');
}

function showCopySuccess() {
    // Show success feedback - change button appearance temporarily
    var $btn = $('#CopyToClipboardBtn');
    var originalIcon = $btn.html();
    
    $btn.removeClass('btn-info').addClass('btn-success');
    $btn.html('<i class="bi bi-clipboard-check"></i>');
    
    // Reset button appearance after a short delay
    setTimeout(function() {
        $btn.removeClass('btn-success').addClass('btn-info');
        $btn.html(originalIcon);
    }, 2000);
}

function fixNumberedLists(text) {
    if (!text) {
        return text;
    }
    
    // Find all numbered list items and ensure they don't have bullet points
    let result = text;
    
    // Remove bullet points from numbered items
    result = result.replace(/\n• (\d+\.\s)/g, '\n$1');
    result = result.replace(/\n• (\d+\.)/g, '\n$1 ');
    
    // Ensure proper line spacing between numbered items
    result = result.replace(/(\d+\.\s[^\n]+)(\n\n+)(\d+\.\s)/g, '$1\n$3');
    
    // Fix mixed bullet and number formatting in lists
    result = result.replace(/(\d+\.\s[^\n]+)(\n+)• /g, '$1\n');
    
    // Ensure numbers in numbered lists have a space after them
    result = result.replace(/(\n\d+\.)([^\s\n])/g, '$1 $2');
    
    // Fix the case where numbers might be concatenated with text
    result = result.replace(/(\n\d+\.)([A-Za-z])/g, '$1 $2');
    
    // Clean up excessive spaces
    result = result.replace(/(\n\d+\.)\s+/g, '$1 ');
    
    return result;
}
