KAAUH Lab - Robust Buttons & Highlighting

Adds shortcuts, persistent filters, and a location logger. Implements an "Enforcement Loop" to win filter race conditions and enhances button UI. Makes the barcode popup draggable.

// ==UserScript==
// @name         KAAUH Lab - Robust Buttons & Highlighting
// @namespace    Violentmonkey Scripts
// @version      2.9.5
// @description  Adds shortcuts, persistent filters, and a location logger. Implements an "Enforcement Loop" to win filter race conditions and enhances button UI. Makes the barcode popup draggable.
// @match        *://his.kaauh.org/lab/*
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-idle
// @author       Hamad Al-Shegifi
// ==/UserScript==

(async function () { // The script must be async to use GM_getValue
    'use strict';

    console.log("KAAUH Lab - Robust Buttons & Highlighting Script v2.9.5 Loading...");

    //================================================================================
    // --- CONFIGURATION & STATE VARIABLES ---
    //================================================================================

    const WORKBENCH_SELECTION_KEY = 'kaauh_last_workbench_selection';
    const FILTER_PERSISTENCE_KEY = 'kaauh_filter_persistence';

    let state = {
        lastUrl: location.href,
        hasAppliedInitialFilters: false,
        filterRetryCount: 0,
        maxFilterRetries: 5,
        isApplyingFilters: false,
        lastFilterApplication: 0,
        observerThrottle: null,
        selectedWorkbenchId: null,
        resetButtonRelocated: false,
        isProcessingReset: false,
    };

    let scrollListenerAttached = false; // Flag to prevent attaching multiple scroll listeners

    const SELECTORS = {
        workbenchDropdown: '#filterSec',
        statusDropdownTrigger: 'option[translateid="lab-test-analyzer.result-status.Ordered"]',
        buttonGroupContainer: 'ul.nav.nav-tabs.tab-container',
        buttonGroup: '.filter-btn-group',
        agHeaderViewport: '.ag-header-viewport',
        agBodyViewport: '.ag-body-viewport', // Added selector for the grid's scrollable area
        resetButton: 'button[translateid="lab-order-list.Reset"]',
        referenceLabToggle: '.nova-toggle',
    };

    //================================================================================
    // --- STYLE INJECTION (GM_addStyle) ---
    //================================================================================

    GM_addStyle(`
        /* Button container styles */
        .filter-btn-group { display: flex !important; flex-wrap: nowrap !important; gap: 6px !important; margin-top: 12px !important; overflow-x: auto !important; padding-bottom: 6px !important; padding-inline: 10px !important; }
        .filter-btn-group::-webkit-scrollbar { height: 8px; }
        .filter-btn-group::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 4px; }
        .filter-btn-group::-webkit-scrollbar-thumb { background: #888; border-radius: 4px; }
        .filter-btn-group::-webkit-scrollbar-thumb:hover { background: #555; }

        /* General button styles */
        .filter-btn-group .btn { padding: 6px 12px !important; font-size: 13px !important; font-weight: bold !important; border-radius: 6px !important; border: none !important; color: #fff !important; white-space: nowrap !important; cursor: pointer !important; flex-shrink: 0 !important; transition: transform 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease; }

        /* Rule 1: All other buttons are 10% opaque */
        .filter-btn-group .btn:not(.selected) {
            opacity: 0.1 !important;
        }

        /* Rule 2: The selected button is 100% opaque */
        .filter-btn-group .btn.selected {
            opacity: 1 !important;
            box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.8), 0 0 0 5px rgba(0, 123, 255, 0.5) !important;
            transform: scale(1.02) !important;
            z-index: 10 !important;
            position: relative !important;
        }

        /* Rule 3: ANY button on hover is 100% opaque */
        .filter-btn-group .btn:hover {
            opacity: 1 !important;
            transform: scale(1.05);
            box-shadow: 0 4px 8px rgba(0,0,0,0.15);
        }

        /* Container for the relocated reset button */
        .reset-button-container { display: flex !important; align-items: center !important; gap: 15px !important; margin-bottom: 10px !important; }
        .relocated-reset-button { order: -1 !important; margin-right: 15px !important; }

        /* Color definitions for buttons */
        ${Array.from({ length: 20 }, (_, i) => {
            const colors = [ '#28a745', '#ffc107', '#17a2b8', '#dc3545', '#6f42c1', '#fd7e14', '#20c997', '#6610f2', '#e83e8c', '#343a40', '#198754', '#0d6efd', '#d63384', '#6c757d', '#ff5733', '#9c27b0', '#00bcd4', '#795548', '#3f51b5'];
            return `.btn-color-${i} { background-color: ${colors[i % colors.length]} !important; }`;
        }).join('\n')}

        /* Row highlighting on hover */
        .ag-row:hover .ag-cell { background-color: lightblue !important; }
    `);


    //================================================================================
    // --- ENHANCED FILTER PERSISTENCE FUNCTIONS ---
    //================================================================================

    async function saveFilterValues(filters) {
        try {
            await GM_setValue(FILTER_PERSISTENCE_KEY, JSON.stringify(filters));
            console.log("Filter values saved:", filters);
        } catch (e) {
            console.error("Error saving filter values:", e);
        }
    }

    async function loadFilterValues() {
        try {
            const filtersJSON = await GM_getValue(FILTER_PERSISTENCE_KEY, null);
            return filtersJSON ? JSON.parse(filtersJSON) : {};
        } catch (e) {
            console.error("Error loading filter values:", e);
            return {};
        }
    }

    async function clearSavedFilters() {
        try {
            await GM_setValue(FILTER_PERSISTENCE_KEY, JSON.stringify({}));
            console.log("Saved filters cleared");
        } catch (e) {
            console.error("Error clearing saved filters:", e);
        }
    }

    /**
     * [NEW] Aggressively clears an input field, fighting race conditions.
     * @param {HTMLInputElement} inputElement The input to clear.
     */
    function robustClearInput(inputElement) {
        if (!inputElement || inputElement.value === '') return;

        inputElement.value = '';
        inputElement.dispatchEvent(new Event('input', { bubbles: true }));
        inputElement.dispatchEvent(new Event('change', { bubbles: true }));
        inputElement.dispatchEvent(new Event('blur', { bubbles: true })); // Add blur for good measure

        // Start a short enforcement loop to ensure it stays cleared
        let cycles = 0;
        const maxCycles = 5; // Enforce for 500ms
        const enforcementInterval = setInterval(() => {
            if (!document.body.contains(inputElement) || cycles >= maxCycles) {
                clearInterval(enforcementInterval);
                return;
            }
            if (inputElement.value !== '') {
                console.warn(`Input value was reverted! Re-clearing.`);
                inputElement.value = '';
                inputElement.dispatchEvent(new Event('input', { bubbles: true }));
                inputElement.dispatchEvent(new Event('change', { bubbles: true }));
            }
            cycles++;
        }, 100);
    }

    /**
     * Reusable function to perform a full reset of all filters and script states.
     */
    async function performFullReset() {
        if (state.isProcessingReset) { return; }
        state.isProcessingReset = true;
        console.log("Starting full reset process...");
        try {
            // 1. Clear all text filters in the table header robustly
            document.querySelectorAll(SELECTORS.agHeaderViewport + ' .ag-floating-filter-input').forEach(robustClearInput);

            // 2. Clear any filters saved in storage by this script
            await clearSavedFilters();

            // 3. Reset Workbench dropdown to its first option ("---select---")
            const workbenchSelect = document.getElementById(SELECTORS.workbenchDropdown.substring(1));
            if (workbenchSelect) {
                await setAndVerifyDropdown(workbenchSelect, workbenchSelect.options[0].value, 'Workbench');
            }

            // 4. Reset Status dropdown to its first option ("---select---")
            const statusDropdown = document.querySelector(SELECTORS.statusDropdownTrigger)?.closest('select');
            if (statusDropdown) {
                await setAndVerifyDropdown(statusDropdown, statusDropdown.options[0].value, 'Status');
            }

            // 5. Reset script-specific state
            state.selectedWorkbenchId = null;
            await GM_setValue(WORKBENCH_SELECTION_KEY, JSON.stringify({}));
            document.querySelectorAll('.filter-btn-group .btn').forEach(btn => btn.classList.remove('selected'));
            console.log("Full reset process completed successfully.");
        } catch (error) {
            console.error("Error during reset process:", error);
        } finally {
            setTimeout(() => { state.isProcessingReset = false; }, 1000); // Cooldown period
        }
    }


    //================================================================================
    // --- BARCODE POPUP & SHORTCUTS MODULE ---
    //================================================================================
    (function() {
        'use strict';

        // --- Configuration ---
        const TARGET_SEARCH_PLACEHOLDER = 'Search by MRN / NationalId & IqamaId';
        const TARGET_BARCODE_COLUMN_HEADER = 'Barcode'; // <--- IMPORTANT: This should match the column title exactly.
        const BARCODE_POPUP_POSITION_KEY = 'kaauh_barcode_popup_position'; // Key for saving position

        // --- Core Functions ---

        function clearAllFilters() {
            console.log("Clearing all filters.");
            const clearAndNotify = (inputElement) => {
                if (inputElement && inputElement.value !== '') {
                    inputElement.value = '';
                    const updateEvent = new Event('input', { bubbles: true });
                    inputElement.dispatchEvent(updateEvent);
                }
            };
            const mainSearchInput = document.querySelector(`input[placeholder="${TARGET_SEARCH_PLACEHOLDER}"]`);
            clearAndNotify(mainSearchInput);
            const agGridFilters = document.querySelectorAll('input.ag-floating-filter-input');
            agGridFilters.forEach(clearAndNotify);
        }

        // --- Manual 'Delete' key listener ---
        document.addEventListener('keydown', (event) => {
            // Do not trigger if user is typing in the popup
            if (document.activeElement.id === 'barcode-popup-input') return;

            if (event.key === 'Delete') {
                console.log("Manual clear triggered by 'Delete' key.");
                clearAllFilters();
            }
        });


        // --- Barcode Popup Functionality ---

        function findBarcodeFilterInput() {
            // 1. Find the header cell containing the title "Barcode"
            const allTitleSpans = document.querySelectorAll('.ag-header-row[aria-rowindex="1"] .ag-header-cell-text');
            let titleHeaderCell = null;
            allTitleSpans.forEach(span => {
                if (span.textContent.trim() === TARGET_BARCODE_COLUMN_HEADER) {
                    titleHeaderCell = span.closest('.ag-header-cell');
                }
            });

            if (!titleHeaderCell) {
                console.error(`Could not find a column header with the text: "${TARGET_BARCODE_COLUMN_HEADER}"`);
                return null;
            }

            // 2. Get the horizontal position (left style) of that header cell
            const targetLeftPosition = titleHeaderCell.style.left;
            if (!targetLeftPosition) {
                console.error('Found the barcode header, but it has no "left" style property to match with.');
                return null;
            }

            // 3. Find the corresponding filter cell in the second header row that has the same horizontal position
            const allFilterCells = document.querySelectorAll('.ag-header-row[aria-rowindex="2"] .ag-header-cell');
            let filterCell = null;
            allFilterCells.forEach(cell => {
                if (cell.style.left === targetLeftPosition) {
                    filterCell = cell;
                }
            });

            if (!filterCell) {
                console.error(`Found barcode header at left=${targetLeftPosition}, but could not find a filter cell at the same position.`);
                return null;
            }

            // 4. Find the input field within that specific filter cell
            const filterInput = filterCell.querySelector('input.ag-floating-filter-input');
            if (!filterInput) {
                console.error('Found the correct filter cell, but no input field was inside it.');
                return null;
            }

            console.log(`Successfully found barcode filter input at left: ${targetLeftPosition}`);
            return filterInput;
        }


        async function createBarcodePopup() {
            // Check if popup already exists and return it if it does
            let popupContainer = document.getElementById('barcode-popup-container');
            if (popupContainer) return popupContainer;

            const savedPositionJSON = await GM_getValue(BARCODE_POPUP_POSITION_KEY, null);
            const savedPosition = savedPositionJSON ? JSON.parse(savedPositionJSON) : null;

            popupContainer = document.createElement('div');
            popupContainer.id = 'barcode-popup-container';
            Object.assign(popupContainer.style, {
                position: 'fixed', top: '0', left: '0', width: '100%', height: '100%',
                backgroundColor: 'rgba(0, 0, 0, 0.5)', display: 'none',
                zIndex: '10000'
            });

            const popupBox = document.createElement('div');
            const initialStyle = {
                position: 'absolute',
                background: '#fff', padding: '25px', borderRadius: '8px',
                boxShadow: '0 5px 15px rgba(0,0,0,0.3)', textAlign: 'center',
                width: '350px'
            };

            if (savedPosition && savedPosition.top && savedPosition.left) {
                initialStyle.top = savedPosition.top;
                initialStyle.left = savedPosition.left;
            } else {
                initialStyle.top = '50%';
                initialStyle.left = '50%';
                initialStyle.transform = 'translate(-50%, -50%)';
            }
            Object.assign(popupBox.style, initialStyle);

            const popupTitle = document.createElement('h3');
            popupTitle.textContent = 'Rapid Barcode Entry';
            Object.assign(popupTitle.style, {
                margin: '0 0 15px 0', color: '#333',
                cursor: 'move', userSelect: 'none'
            });

            const popupInput = document.createElement('input');
            popupInput.id = 'barcode-popup-input';
            popupInput.type = 'text';
            popupInput.placeholder = 'Scan or type barcode and press Enter';
            Object.assign(popupInput.style, {
                width: '100%', padding: '10px', fontSize: '16px',
                border: '2px solid #ccc', borderRadius: '4px'
            });

            popupBox.appendChild(popupTitle);
            popupBox.appendChild(popupInput);
            popupContainer.appendChild(popupBox);
            document.body.appendChild(popupContainer);

            // --- Drag and Drop Logic ---
            popupTitle.addEventListener('mousedown', (e) => {
                e.preventDefault();
                if (popupBox.style.transform && popupBox.style.transform !== 'none') {
                    const rect = popupBox.getBoundingClientRect();
                    popupBox.style.left = `${rect.left}px`;
                    popupBox.style.top = `${rect.top}px`;
                    popupBox.style.transform = 'none';
                }
                const initialLeft = popupBox.offsetLeft;
                const initialTop = popupBox.offsetTop;
                const startX = e.clientX;
                const startY = e.clientY;

                const onMouseMove = (moveEvent) => {
                    const dx = moveEvent.clientX - startX;
                    const dy = moveEvent.clientY - startY;
                    popupBox.style.left = `${initialLeft + dx}px`;
                    popupBox.style.top = `${initialTop + dy}px`;
                };

                const onMouseUp = async () => {
                    document.removeEventListener('mousemove', onMouseMove);
                    document.removeEventListener('mouseup', onMouseUp);
                    const newPosition = { top: popupBox.style.top, left: popupBox.style.left };
                    await GM_setValue(BARCODE_POPUP_POSITION_KEY, JSON.stringify(newPosition));
                };
                document.addEventListener('mousemove', onMouseMove);
                document.addEventListener('mouseup', onMouseUp);
            });

            popupContainer.addEventListener('click', (e) => {
                if (e.target === popupContainer) {
                    popupContainer.style.display = 'none';
                }
            });

            popupInput.addEventListener('keydown', (event) => {
                if (event.key === 'Enter') {
                    event.preventDefault();
                    const barcodeValue = popupInput.value.trim();
                    if (!barcodeValue) return;

                    const barcodeFilterInput = findBarcodeFilterInput();

                    if (barcodeFilterInput) {
                        barcodeFilterInput.value = barcodeValue;
                        barcodeFilterInput.dispatchEvent(new Event('input', { bubbles: true }));
                        popupInput.value = ''; // Clear for next scan
                    } else {
                        console.error(`Critical Error: Could not find the barcode filter on the page. Make sure a column is named "${TARGET_BARCODE_COLUMN_HEADER}".`);
                        popupInput.style.borderColor = 'red';
                        setTimeout(() => { popupInput.style.borderColor = '#ccc'; }, 2000);
                    }
                }
            });

            return popupContainer;
        }


        // --- UI Setup ---

        async function addControls(container) {
            // Create the popup on first run, but don't show it.
            const popup = await createBarcodePopup();

            // Add the Barcode Entry Button if it doesn't exist
            if (!document.getElementById('barcode-entry-btn')) {
                const barcodeButton = document.createElement('button');
                barcodeButton.id = 'barcode-entry-btn';
                barcodeButton.textContent = 'Barcode Entry';
                Object.assign(barcodeButton.style, {
                    backgroundColor: '#5bc0de',
                    transition: 'background-color 0.3s', padding: '6px 12px', fontSize: '13px',
                    fontWeight: 'bold', borderRadius: '6px', color: '#ffffff',
                    border: '1px solid #285e79', cursor: 'pointer', marginLeft: '8px'
                });

                // Now clears filters before showing the popup
                barcodeButton.addEventListener('click', async () => {
                    await performFullReset();
                    popup.style.display = 'block';
                    document.getElementById('barcode-popup-input').focus();
                });
                container.appendChild(barcodeButton);
                console.log('Barcode Entry button added.');
            }
        }

        // --- Persistent Injection Logic ---
        async function placeButton() {
            const buttonContainer = document.querySelector('.reset-button-container');
            if (buttonContainer) {
                await addControls(buttonContainer);
            }
        }

        // Use a MutationObserver as the primary, efficient method.
        const observer = new MutationObserver(placeButton);
        observer.observe(document.body, { childList: true, subtree: true });

        // Use a setInterval as a persistent backup
        setInterval(placeButton, 1000);

    })();


    //================================================================================
    // --- COLUMN FILTERING & PERSISTENCE ---
    //================================================================================

    function setColumnFilter(columnName, value, shouldPersist = true) {
        const headerViewport = document.querySelector(SELECTORS.agHeaderViewport);
        if (!headerViewport) { return false; }

        const allCols = Array.from(headerViewport.querySelectorAll('.ag-header-cell')).map(cell => cell.getAttribute('col-id'));
        const columnIndex = allCols.indexOf(columnName);
        if (columnIndex === -1) { return false; }

        const filterInput = headerViewport.querySelector(`.ag-header-row[aria-rowindex="2"]`)?.children[columnIndex]?.querySelector('.ag-floating-filter-input');
        if (!filterInput) { return false; }

        if (filterInput.value === value) { return true; }

        console.log(`Starting aggressive filter set for ${columnName} to "${value}".`);
        filterInput.value = value;
        filterInput.dispatchEvent(new Event('input', { bubbles: true }));
        filterInput.dispatchEvent(new Event('change', { bubbles: true }));

        let enforcementCycles = 0;
        const maxCycles = 10;
        const enforcementInterval = setInterval(() => {
            if (!document.body.contains(filterInput)) {
                clearInterval(enforcementInterval);
                return;
            }
            if (filterInput.value !== value) {
                console.warn(`Filter for '${columnName}' was reverted! Re-enforcing value: "${value}".`);
                filterInput.value = value;
                filterInput.dispatchEvent(new Event('input', { bubbles: true }));
                filterInput.dispatchEvent(new Event('change', { bubbles: true }));
            }
            enforcementCycles++;
            if (enforcementCycles >= maxCycles) {
                clearInterval(enforcementInterval);
            }
        }, 200);

        if (shouldPersist) {
            setTimeout(async () => {
                const currentFilters = await loadFilterValues();
                currentFilters[columnName] = value;
                await saveFilterValues(currentFilters);
            }, 250);
        }
        return true;
    }

    async function applySavedFilters() {
        if (state.isApplyingFilters) { return true; }
        const now = Date.now();
        if (now - state.lastFilterApplication < 1000) { return true; }
        state.isApplyingFilters = true;
        state.lastFilterApplication = now;

        try {
            const savedFilters = await loadFilterValues();
            if (Object.keys(savedFilters).length === 0) { return true; }
            console.log("Applying saved filters:", savedFilters);
            for (const [columnName, value] of Object.entries(savedFilters)) {
                setColumnFilter(columnName, value, false);
                await new Promise(resolve => setTimeout(resolve, 250));
            }
            return true;
        } finally {
            setTimeout(() => { state.isApplyingFilters = false; }, 500);
        }
    }

    //================================================================================
    // --- [IMPROVED] CORE LOGIC & HELPER FUNCTIONS ---
    //================================================================================

    /**
     * [IMPROVED FOR ROBUSTNESS]
     * Sets a dropdown's value and starts an "enforcement loop" to win race conditions.
     */
    function setAndVerifyDropdown(dropdown, targetValue, description, duration = 1000) {
        return new Promise((resolve) => {
            if (!dropdown) {
                console.error(`[Enforcer] Cannot set dropdown: ${description} dropdown not found.`);
                return resolve(false);
            }
            if (dropdown.value === targetValue) {
                console.log(`[Enforcer] ${description} dropdown already set to "${targetValue}".`);
                return resolve(true);
            }

            console.log(`[Enforcer] Starting enforcement for ${description} dropdown. Target: "${targetValue}".`);

            // Initial set and event dispatch
            dropdown.value = targetValue;
            dropdown.dispatchEvent(new Event('input', { bubbles: true }));
            dropdown.dispatchEvent(new Event('change', { bubbles: true }));

            let enforcementCycles = 0;
            const intervalDuration = 100;
            const maxCycles = duration / intervalDuration;

            const enforcementInterval = setInterval(() => {
                if (!document.body.contains(dropdown)) {
                    clearInterval(enforcementInterval);
                    console.warn(`[Enforcer] ${description} dropdown was removed from the page during enforcement.`);
                    return resolve(false);
                }

                if (dropdown.value !== targetValue) {
                    console.warn(`[Enforcer] ${description} value was reverted! Re-applying "${targetValue}".`);
                    dropdown.value = targetValue;
                    dropdown.dispatchEvent(new Event('input', { bubbles: true }));
                    dropdown.dispatchEvent(new Event('change', { bubbles: true }));
                }

                enforcementCycles++;
                if (enforcementCycles >= maxCycles) {
                    clearInterval(enforcementInterval);
                    const success = dropdown.value === targetValue;
                    if (success) {
                        console.log(`[Enforcer] Successfully set and verified ${description} to "${targetValue}".`);
                    } else {
                        console.error(`[Enforcer] FAILED to set ${description} to "${targetValue}". Final value: "${dropdown.value}".`);
                    }
                    return resolve(success);
                }
            }, intervalDuration);
        });
    }

    //================================================================================
    // --- LOCATION LOGGER MODULE ---
    //================================================================================
    (function() {
        'use strict';

        /**
         * Extracts the patient's location.
         */
        function getPatientLocation() {
            // First, try the most specific selector (often includes unit/ward)
            let locElement = document.querySelector('div.patient-info span[title*="UNIT/"]');

            // If that fails, fall back to the more general selector
            if (!locElement) {
                locElement = document.querySelector('div.patient-info span[title]');
            }

            if (locElement) {
                // The 'title' attribute is the most reliable source
                const titleAttr = locElement.getAttribute('title');
                if (titleAttr && titleAttr.trim() !== '') {
                    // Return the cleaned-up title attribute
                    return titleAttr.trim().replace(/\s+/g, ' ');
                } else {
                    // If title is empty, fall back to the element's text content
                    const clone = locElement.cloneNode(true);
                    // Remove the 'h6' label (e.g., "Location") to get only the value
                    const h6InLoc = clone.querySelector('h6');
                    if (h6InLoc) h6InLoc.remove();

                    let cleanedText = clone.textContent.trim().replace(/\s+/g, ' ');
                    // Further clean up common prefixes like "Bed"
                    cleanedText = cleanedText.replace(/^Bed\s*/i, '').trim();

                    return cleanedText || null; // Return the text, or null if it's empty
                }
            }
            // Return null if no location element was found
            return null;
        }

        /**
         * Creates and inserts the location element into the barcode display box.
         */
        function addLocationToHeader() {
            const mrnDisplay = document.getElementById('mrn-display');
            const barcodeBox = document.getElementById('barcode-display-box');

            // Exit if the necessary elements aren't on the page yet,
            // or if we have already added the location display.
            if (!mrnDisplay || !barcodeBox || document.getElementById('suite-location-display')) {
                return;
            }

            const location = getPatientLocation();

            if (location) {
                const locationDiv = document.createElement('div');
                locationDiv.id = 'suite-location-display';
                locationDiv.textContent = `${location}`;

                // Apply styles to make it a distinct blue badge
                Object.assign(locationDiv.style, {
                    fontWeight: 'bold',
                    fontSize: '18px',
                    color: '#ffffff',
                    backgroundColor: '#0000ff',
                    borderRadius: '4px',
                    padding: '4px 10px',
                    marginLeft: '12px',
                    display: 'flex',
                    alignItems: 'center'
                });


                // Insert the new location element right after the MRN display
                mrnDisplay.after(locationDiv);
            }
        }

        // Use a MutationObserver to watch for when the header bar is added to the page.
        const observer = new MutationObserver(() => {
            addLocationToHeader();
        });

        // Start observing the entire document for changes to its structure.
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // Also run the function once on script start.
        addLocationToHeader();

    })();

    //================================================================================
    // --- HIDE INFO PANEL MODULE ---
    //================================================================================
    (function() {
        'use strict';

        // --- Configuration ---
        const elementToHideSelector = '.lo-view-detail-top';
        const buttonContainerSelector = '.btn-area'; // The container where the button will be placed

        // --- Icons (SVG) ---
        const eyeIcon = `
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: middle; margin-right: 4px;">
            <path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/>
            <circle cx="12" cy="12" r="3"/>
        </svg>`;
        const eyeOffIcon = `
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: middle; margin-right: 4px;">
            <path d="M9.88 9.88a3 3 0 1 0 4.24 4.24"/>
            <path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/>
            <path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/>
            <line x1="2" x2="22" y1="2" y2="22"/>
        </svg>`;

        // --- Styling ---
        GM_addStyle(`
        /* This class is used to hide the patient info panel */
        .gm-hide-element {
            display: none !important;
        }
        /* MODIFIED: Force the text and icon color of the toggle button to be white */
        #gm-toggle-button {
            color: white !important;
        }
    `);

        // --- Main Logic ---

        /**
         * Updates the visibility of the target element based on the stored preference.
         */
        const updateElementVisibility = (element) => {
            if (!element) return;
            const isHidden = GM_getValue('elementHidden', false);
            if (isHidden) {
                element.classList.add('gm-hide-element');
            } else {
                element.classList.remove('gm-hide-element');
            }
        };

        /**
         * Creates and injects the toggle button into the button container.
         */
        const createToggleButton = (container) => {
            const toggleButton = document.createElement('button');
            toggleButton.id = 'gm-toggle-button';
            // Add classes to match the other buttons on the page.
            toggleButton.className = 'btn btn-color-11';

            // Function to update the button's icon and title
            const updateButtonState = () => {
                const isHidden = GM_getValue('elementHidden', false);
                if (isHidden) {
                    toggleButton.innerHTML = eyeOffIcon + ' Show Info';
                    toggleButton.setAttribute('title', 'Show patient info header');
                } else {
                    toggleButton.innerHTML = eyeIcon + ' Hide Info';
                    toggleButton.setAttribute('title', 'Hide patient info header');
                }
            };

            // Add the click event listener
            toggleButton.addEventListener('click', (e) => {
                e.preventDefault(); // Prevent any default button action
                const isCurrentlyHidden = GM_getValue('elementHidden', false);
                GM_setValue('elementHidden', !isCurrentlyHidden); // Save the new state
                updateButtonState(); // Update the button's look

                // Immediately apply the change to the element if it exists
                const elementToHide = document.querySelector(elementToHideSelector);
                if (elementToHide) {
                    updateElementVisibility(elementToHide);
                }
            });

            // Create a wrapper div to match the structure of other buttons
            const buttonWrapper = document.createElement('div');
            buttonWrapper.className = 'btn-group mr-1';
            buttonWrapper.appendChild(toggleButton);

            // Insert the button at the beginning of the container.
            container.prepend(buttonWrapper);

            updateButtonState(); // Set the initial icon and text
        };

        // Use a MutationObserver to watch for the button container and the element to hide
        const observer = new MutationObserver(() => {
            // --- Handle Button Creation ---
            const buttonContainer = document.querySelector(buttonContainerSelector);
            if (buttonContainer && !document.getElementById('gm-toggle-button')) {
                createToggleButton(buttonContainer);
            }

            // --- Handle Element Visibility ---
            const targetElement = document.querySelector(elementToHideSelector);
            if (targetElement) {
                updateElementVisibility(targetElement);
            }
        });

        // Start observing the entire page for changes.
        observer.observe(document.documentElement, {
            childList: true,
            subtree: true
        });

    })();

    //================================================================================
    // --- UI SETUP, STYLING, & MAIN OBSERVER ---
    //================================================================================

    function setupNavigationShortcut() {
        const labOrdersLink = document.querySelector('span.csi-menu-text[title="Lab Orders"]')?.closest('a');
        if (!labOrdersLink || labOrdersLink.dataset.shortcutAttached === 'true') { return; }
        labOrdersLink.addEventListener('click', () => {
            setTimeout(() => {
                const labTestStatusTab = document.querySelector('a[href="#/lab-orders/lab-test-analyzer"]');
                if (labTestStatusTab) { labTestStatusTab.click(); }
            }, 100);
        });
        labOrdersLink.dataset.shortcutAttached = 'true';
    }

    function relocateResetButton() {
        if (state.resetButtonRelocated) return;
        const resetButton = document.querySelector(SELECTORS.resetButton);
        const referenceLabToggle = document.querySelector(SELECTORS.referenceLabToggle);
        if (!resetButton || !referenceLabToggle || resetButton.classList.contains('relocated-reset-button')) { return; }

        console.log("Relocating Reset button...");
        const container = document.createElement('div');
        container.className = 'reset-button-container';
        const relocatedResetButton = resetButton.cloneNode(true);
        relocatedResetButton.classList.add('relocated-reset-button');
        referenceLabToggle.parentNode.insertBefore(container, referenceLabToggle);
        container.appendChild(relocatedResetButton);
        container.appendChild(referenceLabToggle);
        resetButton.remove();

        // Now uses the reusable performFullReset function
        relocatedResetButton.addEventListener('click', async (event) => {
            event.preventDefault();
            event.stopPropagation();
            await performFullReset();
        });
        state.resetButtonRelocated = true;
    }

    function applyConditionalCellStyles() {
        const rows = document.querySelectorAll('.ag-center-cols-container .ag-row');
        for (const row of rows) {
            const clinicCell = row.querySelector('.ag-cell[col-id="clinic"]');
            const isEmergency = clinicCell && clinicCell.textContent.trim().toUpperCase() === 'EMERGENCY';
            const cellsInRow = row.querySelectorAll('.ag-cell');
            for (const cell of cellsInRow) {
                cell.style.backgroundColor = '';
                cell.style.color = '';
                cell.style.fontWeight = '';
                if (isEmergency) {
                    cell.style.backgroundColor = '#ffcccb';
                    cell.style.color = 'black';
                }
                const colId = cell.getAttribute('col-id');
                const text = cell.textContent.trim();
                if (colId === 'testStatus') {
                    switch (text) {
                        case 'Resulted': cell.style.backgroundColor = '#ffb733'; cell.style.color = 'black'; break;
                        case 'Ordered': cell.style.backgroundColor = 'yellow'; cell.style.color = 'black'; break;
                        case 'VerifiedLevel1':
                        case 'VerifiedLevel2': cell.style.backgroundColor = 'lightgreen'; cell.style.color = 'black'; break;
                    }
                } else if (colId === 'sampleStatus') {
                    switch (text) {
                        case 'Received': cell.style.backgroundColor = 'lightgreen'; cell.style.color = 'black'; cell.style.fontWeight = 'bold'; break;
                        case 'Rejected': cell.style.backgroundColor = 'red'; cell.style.color = 'black'; cell.style.fontWeight = 'bold'; break;
                        case 'Collected': cell.style.backgroundColor = 'orange'; cell.style.color = 'black'; cell.style.fontWeight = 'bold'; break;
                    }
                }
            }
        }
    }

    /**
     * [FIX] Attaches a scroll listener to the grid to re-apply styles in real-time.
     */
    function setupGridScrollListener() {
        if (scrollListenerAttached) return;
        const gridViewport = document.querySelector(SELECTORS.agBodyViewport);

        if (gridViewport) {
            let scrollTimeout;
            gridViewport.addEventListener('scroll', () => {
                // Use requestAnimationFrame to throttle the style function for smooth scrolling
                if (scrollTimeout) {
                    window.cancelAnimationFrame(scrollTimeout);
                }
                scrollTimeout = window.requestAnimationFrame(() => {
                    applyConditionalCellStyles();
                });
            }, { passive: true }); // Use passive listener for better scroll performance

            scrollListenerAttached = true;
            console.log("Grid scroll listener attached for live cell styling.");
        }
    }

    function addStatusDropdownListener() {
        const statusDropdown = document.querySelector(SELECTORS.statusDropdownTrigger)?.closest('select');
        if (!statusDropdown || statusDropdown.dataset.statusListenerAttached === 'true') { return; }
        statusDropdown.addEventListener('change', async (event) => {
            try {
                const selectedOption = event.target.options[event.target.selectedIndex];
                const selectedText = selectedOption.textContent.trim();
                if (selectedOption.value === '0' || selectedText.toLowerCase().includes('select')) {
                    if (state.isProcessingReset) return;
                    const relocatedResetButton = document.querySelector('.relocated-reset-button');
                    if (relocatedResetButton) relocatedResetButton.click();
                    return;
                }
                setTimeout(async () => {
                    if (selectedText === "Sample Rejected") {
                        setColumnFilter('sampleStatus', 'Rejected'); setColumnFilter('testStatus', '');
                    } else if (selectedText === "Sample Refused") {
                        setColumnFilter('sampleStatus', 'Refused'); setColumnFilter('testStatus', '');
                    } else {
                        const statusMap = { "Verified 1": "VerifiedLevel1", "Verified 2": "VerifiedLevel2", "Cancelled": "Cancelled" };
                        const filterText = statusMap[selectedText] || selectedText;
                        setColumnFilter('testStatus', filterText);
                        setColumnFilter('sampleStatus', 'Received');
                    }
                }, 100);
            } catch (error) { console.error("Error in status dropdown listener:", error); }
        });
        statusDropdown.dataset.statusListenerAttached = 'true';
    }

    function updateButtonSelection(selectedId) {
        state.selectedWorkbenchId = selectedId;
        document.querySelectorAll('.filter-btn-group .btn').forEach(btn => {
            btn.classList.toggle('selected', btn.dataset.workbenchId === selectedId);
        });
    }

    function insertFilterButtons() {
        if (document.querySelector(SELECTORS.buttonGroup)) return;
        const target = document.querySelector(SELECTORS.buttonGroupContainer);
        const select = document.getElementById(SELECTORS.workbenchDropdown.substring(1));
        if (!target || !select || select.options.length <= 1) return;

        const workbenches = Array.from(select.options).reduce((acc, option) => {
            const id = option.value?.trim();
            let name = option.textContent?.trim();
            if (id && name) {
                if (name.toLowerCase().includes('---select---') || ['select', 'all'].includes(name.toLowerCase())) { name = 'ALL WORK BENCHES'; }
                acc[name] = id;
            }
            return acc;
        }, {});
        if (Object.keys(workbenches).length <= 1) return;

        const group = document.createElement('div');
        group.className = 'filter-btn-group';
        let colorIndex = 0;
        for (const [name, id] of Object.entries(workbenches)) {
            const btn = document.createElement('button');
            btn.className = `btn btn-color-${colorIndex++ % 20}`;
            btn.dataset.workbenchId = id;
            const sessionKey = `workbench_status_${id || 'all'}`;
            let currentStatus = sessionStorage.getItem(sessionKey) || 'Ordered';
            btn.textContent = `${name} (${currentStatus})`;
            if (select.value === id) { btn.classList.add('selected'); state.selectedWorkbenchId = id; }

            // Button click now uses the robust dropdown setter
            btn.addEventListener('click', async () => {
                currentStatus = (currentStatus === 'Ordered') ? 'Resulted' : 'Ordered';
                sessionStorage.setItem(sessionKey, currentStatus);
                btn.textContent = `${name} (${currentStatus})`;

                updateButtonSelection(id);
                GM_setValue(WORKBENCH_SELECTION_KEY, JSON.stringify({ id, status: currentStatus }));

                const workbenchSelect = document.getElementById(SELECTORS.workbenchDropdown.substring(1));
                await setAndVerifyDropdown(workbenchSelect, id, 'Workbench');

                const statusDropdown = document.querySelector(SELECTORS.statusDropdownTrigger)?.closest('select');
                if (statusDropdown) {
                    const optionToSelect = Array.from(statusDropdown.options).find(opt => opt.textContent.trim() === currentStatus);
                    if (optionToSelect) {
                        await setAndVerifyDropdown(statusDropdown, optionToSelect.value, 'Status');
                    }
                }
            });
            group.appendChild(btn);
        }
        target.parentNode.insertBefore(group, target.nextSibling);
        if (!state.selectedWorkbenchId && select.value) { updateButtonSelection(select.value); }
    }

    async function applyPersistentWorkbenchFilter() {
        const workbenchSelect = document.getElementById(SELECTORS.workbenchDropdown.substring(1));
        const statusDropdown = document.querySelector(SELECTORS.statusDropdownTrigger)?.closest('select');
        if (!workbenchSelect || !statusDropdown) return;

        try {
            const savedWorkbenchJSON = await GM_getValue(WORKBENCH_SELECTION_KEY, null);
            if (savedWorkbenchJSON) {
                const savedWorkbench = JSON.parse(savedWorkbenchJSON);
                if (savedWorkbench?.id && savedWorkbench?.status) {
                    console.log("Applying persistent workbench filter:", savedWorkbench);

                    // Set workbench robustly
                    const workbenchSuccess = await setAndVerifyDropdown(workbenchSelect, savedWorkbench.id, 'Workbench');

                    // Set status robustly
                    const optionToSelect = Array.from(statusDropdown.options).find(opt => opt.textContent.trim() === savedWorkbench.status);
                    let statusSuccess = false;
                    if (optionToSelect) {
                        statusSuccess = await setAndVerifyDropdown(statusDropdown, optionToSelect.value, 'Status');
                    } else {
                        console.warn(`Could not find status option for "${savedWorkbench.status}"`);
                    }

                    // Only update the visual button state if both changes were successful
                    if (workbenchSuccess && statusSuccess) {
                        updateButtonSelection(savedWorkbench.id);
                    }
                }
            }
        } catch (e) { console.error("Error applying persistent workbench filter:", e); }
    }

    async function applyFiltersWithRetry() {
        const headerViewport = document.querySelector(SELECTORS.agHeaderViewport);
        if (!headerViewport) return;
        const success = await applySavedFilters();
        if (!success && state.filterRetryCount < state.maxFilterRetries) {
            state.filterRetryCount++;
            console.log(`Filter application failed, retrying... (${state.filterRetryCount}/${state.maxFilterRetries})`);
            setTimeout(() => applyFiltersWithRetry(), 1500);
        } else if (!success) {
            console.warn("Max filter retry attempts reached");
        }
    }

    async function masterObserverCallback() {
        if (state.observerThrottle) clearTimeout(state.observerThrottle);
        state.observerThrottle = setTimeout(async () => {
            if (location.href !== state.lastUrl) {
                state.lastUrl = location.href;
                Object.assign(state, { hasAppliedInitialFilters: false, filterRetryCount: 0, isApplyingFilters: false, selectedWorkbenchId: null, resetButtonRelocated: false, isProcessingReset: false });
                scrollListenerAttached = false; // Reset listener flag on navigation
            }
            setupNavigationShortcut();
            if (!location.href.includes('/lab-orders/lab-test-analyzer')) return;

            relocateResetButton();
            insertFilterButtons();
            addStatusDropdownListener();
            setupGridScrollListener(); // Attach the scroll listener for live styling

            if (!state.hasAppliedInitialFilters) {
                console.log("Running one-time filter application...");
                await applyPersistentWorkbenchFilter(); // This is now robust
                await applyFiltersWithRetry();
                state.hasAppliedInitialFilters = true;
                console.log("One-time filter application complete.");
            }
            applyConditionalCellStyles(); // Apply styles on initial load and other changes
        }, 100);
    }

    const observer = new MutationObserver(masterObserverCallback);
    observer.observe(document.body, { childList: true, subtree: true });
    masterObserverCallback();
})();