{% extends "base.html" %}

{% block content %}
<div class="px-4 py-5 my-5 text-center">
    <img class="d-block mx-auto mb-4" src="{{ url_for('static', filename='FHIRFLARE.png') }}" alt="FHIRFLARE Ig Toolkit" width="192" height="192">
    <h1 class="display-5 fw-bold text-body-emphasis">{{ title }}</h1>
    <div class="col-lg-6 mx-auto">
        <p class="lead mb-4">
            View details of the processed FHIR Implementation Guide.
        </p>
    </div>
</div>

<div class="container mt-4">
    <div class="d-flex justify-content-between align-items-center mb-3">
        <h2><i class="bi bi-info-circle me-2"></i>{{ title }}</h2>
        <a href="{{ url_for('view_igs') }}" class="btn btn-secondary"><i class="bi bi-arrow-left"></i> Back to Package List</a>
    </div>

    {% if processed_ig %}
        <div class="card">
            <div class="card-header">Package Details</div>
            <div class="card-body">
                <dl class="row">
                    <dt class="col-sm-3">Package Name</dt>
                    <dd class="col-sm-9"><code>{{ processed_ig.package_name }}</code></dd>
                    <dt class="col-sm-3">Package Version</dt>
                    <dd class="col-sm-9">{{ processed_ig.version }}</dd>
                    <dt class="col-sm-3">Processed At</dt>
                    <dd class="col-sm-9">{{ processed_ig.processed_date.strftime('%Y-%m-%d %H:%M:%S UTC') }}</dd>
                </dl>
            </div>
        </div>

        {% if config.DISPLAY_PROFILE_RELATIONSHIPS %}
        <div class="card mt-4">
            <div class="card-header">Profile Relationships</div>
            <div class="card-body">
                <h6>Complies With</h6>
                {% if complies_with_profiles %}
                    <ul>
                        {% for profile in complies_with_profiles %}
                            <li>{{ profile }}</li>
                        {% endfor %}
                    </ul>
                {% else %}
                    <p class="text-muted"><em>No profiles declared as compatible.</em></p>
                {% endif %}

                <h6>Required Dependent Profiles (Must Also Validate Against)</h6>
                {% if imposed_profiles %}
                    <ul>
                        {% for profile in imposed_profiles %}
                            <li>{{ profile }}</li>
                        {% endfor %}
                    </ul>
                {% else %}
                    <p class="text-muted"><em>No imposed profiles.</em></p>
                {% endif %}
            </div>
        </div>
        {% endif %}

        <div class="card mt-4">
            <div class="card-header">Resource Types Found / Defined</div>
            <div class="card-body">
                {% if profile_list or base_list %}
                    <p class="mb-2">
                        <small>
                            <span class="badge bg-warning text-dark border me-1" style="font-size: 0.8em;" title="Profile contains Must Support elements">MS</span> = Contains Must Support Elements<br>
                            <span class="badge bg-info text-dark border me-1" style="font-size: 0.8em;" title="An optional Extension which contains Must Support sub-elements (e.g., value[x], type)">Optional MS Ext</span> = Optional Extension with Must Support Sub-Elements
                        </small>
                    </p>
                    {% if profile_list %}
                        <p class="mb-2"><small><span class="badge bg-primary text-light border me-1">Examples</span> = Examples will be displayed when selecting profile Types if contained in the IG</small></p>
                        <h6>Profiles Defined ({{ profile_list|length }}):</h6>
                        <div class="d-flex flex-wrap gap-1 mb-3 resource-type-list">
                            {% for type_info in profile_list %}
                                <a href="#" class="resource-type-link text-decoration-none"
                                   data-package-name="{{ processed_ig.package_name }}"
                                   data-package-version="{{ processed_ig.version }}"
                                   data-resource-type="{{ type_info.name }}"
                                   aria-label="View structure for {{ type_info.name }}">
                                    {% if type_info.must_support %}
                                        {% if optional_usage_elements.get(type_info.name) %}
                                            <span class="badge bg-info text-dark border" title="Optional Extension with Must Support sub-elements">{{ type_info.name }}</span>
                                        {% else %}
                                            <span class="badge bg-warning text-dark border" title="Contains Must Support elements">{{ type_info.name }}</span>
                                        {% endif %}
                                    {% else %}
                                        <span class="badge bg-light text-dark border">{{ type_info.name }}</span>
                                    {% endif %}
                                </a>
                            {% endfor %}
                        </div>
                    {% else %}
                        <p class="text-muted"><em>No profiles defined.</em></p>
                    {% endif %}
                    {% if base_list %}
                          <h6>Base Resource Types Referenced ({{ base_list|length }}):</h6>
                          <div class="d-flex flex-wrap gap-1 resource-type-list">
                               {% for type_info in base_list %}
                                   <a href="#" class="resource-type-link text-decoration-none"
                                      data-package-name="{{ processed_ig.package_name }}"
                                      data-package-version="{{ processed_ig.version }}"
                                      data-resource-type="{{ type_info.name }}"
                                      aria-label="View structure for {{ type_info.name }}">
                                        {% if type_info.must_support %}
                                             <span class="badge bg-warning text-dark border" title="Contains Must Support elements">{{ type_info.name }}</span>
                                        {% else %}
                                             <span class="badge bg-light text-dark border">{{ type_info.name }}</span>
                                        {% endif %}
                                   </a>
                               {% endfor %}
                          </div>
                    {% else %}
                        <p class="text-muted"><em>No base resource types referenced.</em></p>
                    {% endif %}
                {% else %}
                    <p class="text-muted"><em>No resource type information extracted or stored.</em></p>
                {% endif %}
            </div>
        </div>

        <div id="structure-display-wrapper" class="mt-4" style="display: none;">
            <div class="card">
                <div class="card-header d-flex justify-content-between align-items-center">
                    <span>Structure Definition for: <code id="structure-title"></code></span>
                    <button type="button" class="btn-close" aria-label="Close" onclick="document.getElementById('structure-display-wrapper').style.display='none'; document.getElementById('example-display-wrapper').style.display='none'; document.getElementById('raw-structure-wrapper').style.display='none';"></button>
                </div>
                <div class="card-body">
                    <div id="structure-loading" class="text-center py-3" style="display: none;">
                        <div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div>
                    </div>
                    <div id="structure-fallback-message" class="alert alert-info" style="display: none;"></div>
                    <ul class="nav nav-tabs" id="structureTabs" role="tablist">
                        <li class="nav-item">
                            <a class="nav-link active" id="differential-tab" data-bs-toggle="tab" href="#differential" role="tab" aria-controls="differential" aria-selected="true">Differential</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" id="snapshot-tab" data-bs-toggle="tab" href="#snapshot" role="tab" aria-controls="snapshot" aria-selected="false">Snapshot</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" id="must-support-tab" data-bs-toggle="tab" href="#must-support" role="tab" aria-controls="must-support" aria-selected="false">Must Support</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" id="key-elements-tab" data-bs-toggle="tab" href="#key-elements" role="tab" aria-controls="key-elements" aria-selected="false">Key Elements</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" id="constraints-tab" data-bs-toggle="tab" href="#constraints-tab-pane" role="tab">Constraints</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" id="terminology-tab" data-bs-toggle="tab" href="#terminology-tab-pane" role="tab">Terminology</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" id="searchparams-tab" data-bs-toggle="tab" href="#searchparams-tab-pane" role="tab">Search Params</a>
                        </li>
                    </ul>
                    <div class="tab-content mt-3">
                        <div class="tab-pane fade show active" id="differential" role="tabpanel" aria-labelledby="differential-tab">
                            <div class="row gx-2 small fw-bold border-bottom mb-1 d-none d-md-flex">
                                <div class="col-lg-4 col-md-3">Path</div>
                                <div class="col-lg-1 col-md-1 text-center">Card.</div>
                                <div class="col-lg-3 col-md-3">Type(s)</div>
                                <div class="col-lg-1 col-md-1 text-center">Status</div>
                                <div class="col-lg-3 col-md-4">Description</div>
                            </div>
                            <ul id="structure-tree-differential" class="list-group list-group-flush structure-tree-root"></ul>
                        </div>
                        <div class="tab-pane fade" id="snapshot" role="tabpanel" aria-labelledby="snapshot-tab">
                            <div class="row gx-2 small fw-bold border-bottom mb-1 d-none d-md-flex">
                                <div class="col-lg-4 col-md-3">Path</div>
                                <div class="col-lg-1 col-md-1 text-center">Card.</div>
                                <div class="col-lg-3 col-md-3">Type(s)</div>
                                <div class="col-lg-1 col-md-1 text-center">Status</div>
                                <div class="col-lg-3 col-md-4">Description</div>
                            </div>
                            <ul id="structure-tree-snapshot" class="list-group list-group-flush structure-tree-root"></ul>
                        </div>
                        <div class="tab-pane fade" id="must-support" role="tabpanel" aria-labelledby="must-support-tab">
                            <div class="row gx-2 small fw-bold border-bottom mb-1 d-none d-md-flex">
                                <div class="col-lg-4 col-md-3">Path</div>
                                <div class="col-lg-1 col-md-1 text-center">Card.</div>
                                <div class="col-lg-3 col-md-3">Type(s)</div>
                                <div class="col-lg-1 col-md-1 text-center">Status</div>
                                <div class="col-lg-3 col-md-4">Description</div>
                            </div>
                            <ul id="structure-tree-must-support" class="list-group list-group-flush structure-tree-root"></ul>
                        </div>
                        <div class="tab-pane fade" id="key-elements" role="tabpanel" aria-labelledby="key-elements-tab">
                            <div class="row gx-2 small fw-bold border-bottom mb-1 d-none d-md-flex">
                                <div class="col-lg-4 col-md-3">Path</div>
                                <div class="col-lg-1 col-md-1 text-center">Card.</div>
                                <div class="col-lg-3 col-md-3">Type(s)</div>
                                <div class="col-lg-1 col-md-1 text-center">Status</div>
                                <div class="col-lg-3 col-md-4">Description</div>
                            </div>
                            <ul id="structure-tree-key-elements" class="list-group list-group-flush structure-tree-root"></ul>
                        </div>
                        <div class="tab-pane fade" id="constraints-tab-pane" role="tabpanel" aria-labelledby="constraints-tab">
                            <div class="mt-3 table-responsive">
                                <p>Constraints defined in this profile:</p>
                                <table class="table table-sm table-bordered table-striped" id="constraints-table">
                                    <thead class="table-light">
                                        <tr>
                                            <th>Key</th>
                                            <th>Severity</th>
                                            <th>Path</th>
                                            <th>Description</th>
                                            <th>Expression (FHIRPath)</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr><td colspan="5">No constraints found or data not loaded.</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                        <div class="tab-pane fade" id="terminology-tab-pane" role="tabpanel" aria-labelledby="terminology-tab">
                            <div class="mt-3 table-responsive">
                                <p>Terminology bindings defined in this profile:</p>
                                <table class="table table-sm table-bordered table-striped" id="bindings-table">
                                    <thead class="table-light">
                                        <tr>
                                            <th>Path</th>
                                            <th>Strength</th>
                                            <th>ValueSet</th>
                                            <th>Description</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr><td colspan="4">No bindings found or data not loaded.</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                        <div class="tab-pane fade" id="searchparams-tab-pane" role="tabpanel" aria-labelledby="searchparams-tab">
                            <div class="mt-3">
                                <p>Search parameters associated with this profile:</p>
                                <div class="alert alert-warning" role="alert">
                                    <strong>Note:</strong> SearchParameter resources. This functionality is NEWLY implemented, please report any bugs)
                                </div>
                                <table class="table table-sm table-bordered table-striped" id="searchparams-table">
                                    <thead class="table-light">
                                        <tr>
                                            <th>Parameter</th>
                                            <th>Type</th>
                                            <th>Conformance</th>
                                            <th>Requirements / Description</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr><td colspan="4">Search Parameter data not available. Requires backend implementation.</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div id="raw-structure-wrapper" class="mt-4" style="display: none;">
            <div class="card">
                <div class="card-header d-flex justify-content-between align-itemsitum-center">
                    <span>Raw Structure Definition for <code id="raw-structure-title"></code></span>
                    <button type="button" class="btn btn-sm btn-outline-secondary btn-copy" id="copy-raw-def-button"
                            data-bs-toggle="tooltip" data-bs-placement="top" title="Copy Raw Definition JSON">
                        <i class="bi bi-clipboard" aria-hidden="true"></i>
                        <span class="visually-hidden">Copy Raw Definition JSON to clipboard</span>
                    </button>
                </div>
                <div class="card-body">
                    <div id="raw-structure-loading" class="text-center py-3" style="display: none;">
                        <div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div>
                    </div>
                    <pre><code id="raw-structure-content" class="p-2 d-block border bg-light language-json" style="max-height: 400px; overflow-y: auto;"></code></pre>
                </div>
            </div>
        </div>
        <div id="example-display-wrapper" class="mt-4" style="display: none;">
            <div class="card">
                <div class="card-header">Examples for <code id="example-resource-type-title"></code></div>
                <div class="card-body">
                    <div class="mb-3" id="example-selector-wrapper" style="display: none;">
                        <label for="example-select" class="form-label">Select Example:</label>
                        <select class="form-select form-select-sm" id="example-select"><option selected value="">-- Select --</option></select>
                    </div>
                    <div id="example-loading" class="text-center py-3" style="display: none;">
                        <div class="spinner-border spinner-border-sm text-secondary" role="status"><span class="visually-hidden">Loading...</span></div>
                    </div>
                    <div id="example-content-wrapper" style="display: none;">
                        <div class="form-check mb-2">
                            <input type="checkbox" class="form-check-input" id="includeNarrative" checked>
                            <label class="form-check-label" for="includeNarrative">Include Narrative</label>
                        </div>
                        <h6 id="example-filename" class="mt-2 small text-muted"></h6>
                        <div class="row">
                            <div class="col-md-6">
                                <div class="d-flex justify-content-between align-items-center mb-1">
                                    <h6>Raw Content</h6>
                                    <button type="button" class="btn btn-sm btn-outline-secondary btn-copy" id="copy-raw-ex-button"
                                            data-bs-toggle="tooltip" data-bs-placement="top" title="Copy Raw Content">
                                        <i class="bi bi-clipboard" aria-hidden="true"></i>
                                        <span class="visually-hidden">Copy Raw Content to clipboard</span>
                                    </button>
                                </div>
                                <pre><code id="example-content-raw" class="p-2 d-block border bg-light language-json" style="max-height: 400px; overflow-y: auto; white-space: pre;"></code></pre>
                            </div>
                            <div class="col-md-6">
                                <div class="d-flex justify-content-between align-items-center mb-1">
                                    <h6>Pretty-Printed JSON</h6>
                                    <button type="button" class="btn btn-sm btn-outline-secondary btn-copy" id="copy-pretty-json-button"
                                            data-bs-toggle="tooltip" data-bs-placement="top" title="Copy JSON">
                                        <i class="bi bi-clipboard" aria-hidden="true"></i>
                                        <span class="visually-hidden">Copy JSON example to clipboard</span>
                                    </button>
                                </div>
                                <pre><code id="example-content-json" class="p-2 d-block border bg-light language-json" style="max-height: 400px; overflow-y: auto;"></code></pre>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    {% else %}
        <div class="alert alert-warning" role="alert">Processed IG details not available.</div>
    {% endif %}
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">

<script>const examplesData = {{ examples_by_type | tojson | safe }};</script>

<script>
// --- START OF COMPLETE SCRIPT BLOCK ---

// --- Global Variables (Accessed by DOMContentLoaded) ---
let structureDisplayWrapper, structureTitle, structureLoading, structureFallbackMessage;
let structureTreeDifferential, structureTreeSnapshot, structureTreeMustSupport, structureTreeKeyElements;
let exampleDisplayWrapper, exampleSelectorWrapper, exampleSelect, exampleResourceTypeTitle;
let exampleLoading, exampleContentWrapper, exampleFilename, exampleContentRaw, exampleContentJson;
let rawStructureWrapper, rawStructureTitle, rawStructureContent, rawStructureLoading;
let copyRawDefButton, copyRawExButton, copyPrettyJsonButton;
let copyRawDefTooltipInstance = null;
let copyRawExTooltipInstance = null;
let copyPrettyJsonTooltipInstance = null;
let structureDataCache = {}; // Cache for fetched structure data
let includeNarrativeCheckbox; // New global for narrative toggle

// --- Global Helper Functions ---
function parseFhirPath(path) {
    if (!path || typeof path !== 'string') return [];
    // Split by dot, but look ahead for '[' to handle paths like Observation.component[slice].code
    const parts = path.split(/\.(?![^\[]*\])|(?=\[)/) // Split on dots NOT inside brackets, or before opening bracket
                      .map(part => part.replace(/\[x\]/g, '')); // Remove [x]
    return parts.filter(part => part); // Remove empty strings
}

function escapeHtmlAttr(str) {
    if (!str) return '';
    return str
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;');
}

// Helper to get consistent node key
function getNodeKey(element) {
    if (!element) return null;
    // Use id if it looks like a structured path (contains '.'), otherwise default to path
    const baseKey = (element.id && element.id.includes('.')) ? element.id : element.path;
    if (!baseKey) {
        console.warn("Cannot generate key: element missing structured id and path", element);
        return `no-key-${Math.random()}`;
    }
    // Append sliceName if present to ensure uniqueness for slices
    return element.sliceName ? `${baseKey}::slice::${element.sliceName}` : baseKey;
}

// Helper function to initialize a node
function createNode(path, name, parentPathKey, element = null) {
    // Determine flags based on element data passed from backend
    const isInDifferential = element?.isInDifferential || false;
    const mustSupport = element?.mustSupport || false;

    return {
        path: path,
        name: name,
        parentPathKey: parentPathKey, // Store the KEY of the parent for easier lookup
        element: element,
        children: [],
        isInDifferential: isInDifferential, // Store flag for direct access
        mustSupport: mustSupport         // Store flag for direct access
        // containsMustSupportSlice will be added later if applicable
    };
}

// Refined Filter for Key Elements view
function filterKeyElements(node) {
    if (!node || !node.element) return false; // Node must exist and have element data
    const el = node.element;

    // Criteria from definition:
    // - Marked as mustSupport
    if (el.mustSupport) return true;
    // - Listed in differential (flag set by backend)
    if (node.isInDifferential) return true; // Check the flag on the *node*
    // - Mandatory (min cardinality > 0)
    if (el.min !== undefined && el.min > 0) return true;
    // - Max cardinality constrained (max defined and not '*')
    //   (We include any constraint, e.g., max=1 or max=0)
    if (el.max !== undefined && el.max !== '*') return true;
    // - Implicated in a constraint (element has constraints)
    if (el.constraint && Array.isArray(el.constraint) && el.constraint.length > 0) return true;
    // - Introduces slicing
    if (el.slicing) return true;
    // - Is a slice itself
    if (el.sliceName) return true;
    // - Is a modifier element
    if (el.isModifier) return true;

    return false; // Default to false if no criteria met
}

// --- Helper Function to Propagate MS Flag to Slicing Entries V2 ---
function flagSlicingEntriesWithMSSlices(node) {
    if (!node) return false; // Base case for recursion

    let containedMSSliceInChildren = false; // Flag for MS anywhere in the descendant tree
    let directChildIsMSSlice = false; // Flag for MS in a direct child slice

    if (node.children && node.children.length > 0) {
        // Check direct children first for being MS slices
        directChildIsMSSlice = node.children.some(child => child.element?.sliceName && child.mustSupport);

        // Recursively check descendants AND collect whether any descendant branch contains an MS slice
        node.children.forEach(child => {
            // If the recursive call on ANY child returns true, it means an MS slice exists somewhere below that child
            if (flagSlicingEntriesWithMSSlices(child)) {
                containedMSSliceInChildren = true;
            }
        });
    }

    // Determine if this node ITSELF is a must-support slice
    const isMustSupportSlice = node.element?.sliceName && node.mustSupport;

    // Flag THIS node if it defines slicing AND (a direct child is an MS slice OR a deeper descendant is an MS slice)
    if (node.element?.slicing && (directChildIsMSSlice || containedMSSliceInChildren)) {
        node.containsMustSupportSlice = true;
    }

    // Return true if THIS node is an MS slice OR if it was flagged as containing one below it
    // This ensures the status propagates up correctly.
    return isMustSupportSlice || node.containsMustSupportSlice === true;
} // End flagSlicingEntriesWithMSSlices V2

// --- Build Tree Data - V13 (Correct Parent Finding for Nested Slices) ---
function buildTreeData(elements, view, mustSupportPaths) {
    const treeData = [];
    const nodeMap = new Map(); // Map uses getNodeKey(element) as key

    if (!elements || elements.length === 0) {
        console.warn(`No elements provided for view '${view}'`);
        return treeData;
    }

    // --- PRE-SORT elements (Keep V12 sorting) ---
    try {
        elements.sort((a, b) => {
            const pathA = a.path || '';
            const pathB = b.path || '';
            const depthA = pathA.split('.').length;
            const depthB = pathB.split('.').length;
            if (depthA !== depthB) return depthA - depthB;
            if (pathA !== pathB) return pathA.localeCompare(pathB);
            const sliceA = a.sliceName || '';
            const sliceB = b.sliceName || '';
            return sliceA.localeCompare(sliceB);
        });
    } catch (e) {
        console.error("Error sorting elements:", e, elements);
    }
    // --- END PRE-SORT ---

    // --- Create Root Node (Keep V12 logic) ---
    const rootElementData = elements.find(el => el.path && !el.path.includes('.'));
    let rootNode;
    if (rootElementData) {
        const rootNodeKey = getNodeKey(rootElementData);
        if (rootNodeKey) {
            rootNode = createNode(rootElementData.path, rootElementData.path, 'Root', rootElementData);
            treeData.push(rootNode);
            nodeMap.set(rootNodeKey, rootNode);
        } else {
            console.error("Could not generate key for root element:", rootElementData);
            return treeData;
        }
    } else {
        console.error(`Cannot find root element in provided elements for view '${view}'. Cannot build tree.`);
        return treeData;
    }

    const mustSupportPathsSet = mustSupportPaths instanceof Set ? mustSupportPaths : new Set(mustSupportPaths || []);

    // --- Build Tree Structure ---
    elements.forEach((element, index) => {
        const path = element.path;
        const id = element.id;
        const nodeKey = getNodeKey(element);
        const isSlice = !!element.sliceName;

        if (!path || !nodeKey) { console.warn(`Skipping element ${index} with missing path/key`, element); return; }

        // Root element handling (Keep V12 logic)
        if (nodeKey === getNodeKey(rootElementData)) {
            rootNode.isInDifferential = element.isInDifferential || rootNode.isInDifferential;
            rootNode.mustSupport = element.mustSupport || rootNode.mustSupport || mustSupportPathsSet.has(path) || (id && mustSupportPathsSet.has(id)) || mustSupportPathsSet.has(nodeKey);
            if (element.isInDifferential && !rootNode.element.isInDifferential) { rootNode.element = element; }
            return;
        }

        // Set flags (Keep V12 logic)
        element.isInDifferential = element.isInDifferential || false;
        element.mustSupport = element.mustSupport || mustSupportPathsSet.has(path) || (id && mustSupportPathsSet.has(id)) || mustSupportPathsSet.has(nodeKey);

        // --- Parent Finding Logic (V13) ---
        let parentNodeKey = getNodeKey(rootElementData); // Default to root
        let parentElement = rootElementData;
        let parentFound = false;

        // Check 1: Direct Slice Definition (e.g., component:DiastolicBP or coding:DBPCode)
        if (isSlice) {
            let expectedParentId = null;
            let expectedParentPath = null;

            // Derive the expected parent ID/Path from the slice's ID or Path
            if (id && id.includes('.')) {
                // Try deriving from ID first (more specific)
                const idParts = id.split(':');
                if (idParts.length > 1) {
                    const parentIdGuess = idParts.slice(0, -1).join(':');
                    if (parentIdGuess.includes('.')) {
                        expectedParentId = parentIdGuess;
                    }
                }
                // Fallback: if ID didn't work well, try deriving from path
                if (!expectedParentId && path && path.includes('.')) {
                    expectedParentPath = path; // The base path is the parent slicing entry path
                }
            } else if (path && path.includes('.')) {
                // If no complex ID, use the path
                expectedParentPath = path;
            }

            // Now, find the slicing entry element using the derived parent identifiers
            let slicingEntryElement = null;
            if (expectedParentId) {
                // Prefer ID match
                slicingEntryElement = elements.find(el => el.id === expectedParentId && el.slicing);
            }
            if (!slicingEntryElement && expectedParentPath) {
                // Fallback to path match if ID didn't work or wasn't derived
                slicingEntryElement = elements.find(el => el.path === expectedParentPath && !el.sliceName && el.slicing);
            }

            if (slicingEntryElement) {
                parentElement = slicingEntryElement;
                parentNodeKey = getNodeKey(parentElement);
                parentFound = true;
            } else {
                console.warn(`Slicing entry element NOT FOUND for expected parent (ID: ${expectedParentId}, Path: ${expectedParentPath}) needed by slice '${nodeKey}'. Assigning root.`);
                parentElement = rootElementData;
                parentNodeKey = getNodeKey(parentElement);
                parentFound = true; // Consider parent determined (fallback)
            }
        }
        // Check 2: Descendant of a Slice (using ID structure) (Keep V12 logic)
        else if (id && id.includes(':') && id.includes('.')) {
            const idParts = id.split('.');
            let potentialSliceParentId = null;
            for (let i = idParts.length - 2; i >= 0; i--) {
                const tempId = idParts.slice(0, i + 1).join('.');
                if (tempId.includes(':')) { potentialSliceParentId = tempId; break; }
            }
            if (potentialSliceParentId) {
                const potentialParentKey = potentialSliceParentId;
                if (nodeMap.has(potentialParentKey)) {
                    const potentialParentNode = nodeMap.get(potentialParentKey);
                    if (potentialParentNode?.element) {
                        parentNodeKey = potentialParentKey; parentElement = potentialParentNode.element; parentFound = true;
                    } else { console.warn(`Node found in map for key ${potentialParentKey} but its element was missing. Falling back.`); }
                } else {
                    const sliceParentElement = elements.find(el => el.id === potentialSliceParentId);
                    if (sliceParentElement) {
                        parentNodeKey = getNodeKey(sliceParentElement); parentElement = sliceParentElement; parentFound = true;
                    } else { console.warn(`Slice parent element ID '${potentialSliceParentId}' not found for descendant '${id}'. Falling back.`); }
                }
            }
        }

        // Check 3 & 4: Regular or Choice Descendant (Keep V12 logic)
        if (!parentFound) {
            const pathParts = parseFhirPath(path);
            if (pathParts.length > 1) {
                const parentPathString = pathParts.slice(0, -1).join('.');
                let potentialParentNode = nodeMap.get(parentPathString);
                if (!potentialParentNode && path.includes('[x]')) {
                    const originalPathParts = path.split('.');
                    const parentPathWithChoice = originalPathParts.slice(0, -1).join('.');
                    potentialParentNode = nodeMap.get(parentPathWithChoice);
                }
                if (potentialParentNode?.element) {
                    parentElement = potentialParentNode.element;
                    parentNodeKey = getNodeKey(parentElement);
                    parentFound = true;
                } else {
                    parentElement = rootElementData; parentNodeKey = getNodeKey(parentElement);
                    parentFound = true;
                }
            } else {
                parentElement = rootElementData; parentNodeKey = getNodeKey(parentElement);
                parentFound = true;
            }
        }
        // --- End Parent Finding Logic ---

        // --- Node Creation / Update / Attachment (Keep V12 logic) ---
        let parentNode = nodeMap.get(parentNodeKey);
        if (!parentNode) {
            console.error(`Parent node OBJECT NOT FOUND in map for resolved key: '${parentNodeKey}' (child: ${nodeKey}). Assigning child to root.`);
            parentNode = rootNode;
            parentNodeKey = getNodeKey(rootElementData);
        }

        if (nodeMap.has(nodeKey)) {
            const existingNode = nodeMap.get(nodeKey);
            existingNode.element = element;
            existingNode.isInDifferential = existingNode.isInDifferential || element.isInDifferential;
            existingNode.mustSupport = existingNode.mustSupport || element.mustSupport;
            if (existingNode.parentPathKey && existingNode.parentPathKey !== parentNodeKey) {
                console.warn(`[!] Ambiguous Parent: Node ${nodeKey} already exists with parent ${existingNode.parentPathKey}, but current logic suggests parent ${parentNodeKey}. Keeping original parent.`);
            } else {
                existingNode.parentPathKey = parentNodeKey;
            }
        } else {
            const pathPartsForName = parseFhirPath(path);
            const baseName = pathPartsForName.length > 0 ? pathPartsForName[pathPartsForName.length - 1] : path;
            const name = element.sliceName ? `${baseName}:${element.sliceName}` : baseName;
            const newNode = createNode(path, name, parentNodeKey, element);
            nodeMap.set(nodeKey, newNode);
            if (parentNode) {
                if (!parentNode.children) parentNode.children = [];
                parentNode.children.push(newNode);
            } else {
                console.error(`Cannot add child ${nodeKey} as parent node object is unexpectedly null.`);
            }
        }
    }); // End elements.forEach

    // --- Filtering Logic (Keep V12 logic) ---
    if ((view === 'must-support' || view === 'key-elements' || view === 'differential') && treeData.length > 0 && treeData[0]) {
        const filterNodesRecursively = (nodes, filterFnParam) => {
            if (!nodes) return [];
            return nodes.map(node => {
                if (!node) return null;
                const filteredChildren = filterNodesRecursively(node.children || [], filterFnParam);
                const filterMatch = filterFnParam(node);
                if (filterMatch || filteredChildren.length > 0) {
                    node.children = filteredChildren;
                    return node;
                }
                return null;
            }).filter(node => node !== null);
        };
        let filterFunction;
        if (view === 'must-support') { filterFunction = (node) => node.mustSupport || node.containsMustSupportSlice; }
        else if (view === 'key-elements') { filterFunction = filterKeyElements; }
        else { filterFunction = (node) => node.isInDifferential; } // Differential view

        if (treeData[0]) {
            treeData[0].children = filterNodesRecursively(treeData[0].children || [], filterFunction);
            if (!filterFunction(treeData[0]) && (!treeData[0].children || treeData[0].children.length === 0)) {
                if (view !== 'snapshot') {
                    console.log(`Root node ${treeData[0].path} does not meet criteria for view '${view}' and has no matching children. Clearing tree.`);
                    return [];
                }
            }
        }
    } // End Filtering Logic

    // --- Post-processing step for MS highlighting (Keep V12 logic) ---
    if (treeData.length > 0 && treeData[0]) { flagSlicingEntriesWithMSSlices(treeData[0]); }

    return treeData;
} // End buildTreeData V13

// --- Render Node as List Item - V19 (Fixes isSlice error, keeps V18 logic) ---
function renderNodeAsLi(node, mustSupportPathsSet, resourceType, level = 0, view = 'snapshot') {
    if (!node || !node.path || !node.name) { console.warn(`Skipping render for invalid node:`, node); return ''; }
    const el = node.element || {};
    const path = el.path || node.path || `node-${level}-${Math.random()}`;
    const elementId = el.id || null; // Renamed variable
    const nodeKey = getNodeKey(el);

    const sliceName = el.sliceName || null;
    // Define isSlice based on sliceName
    const isSlice = sliceName ? true : false;
    const min = el.min !== undefined ? el.min : '';
    const max = el.max !== undefined ? el.max : '*';
    const short = el.short || '';
    const definition = el.definition || short || '';
    const isChoiceElement = (el.path && el.path.endsWith('[x]'));
    const definesSlicing = el.slicing ? true : false;

    // Must Support Logic & Icon (V15 logic)
    let isMustSupport = node.mustSupport || false;
    mustSupportPathsSet = mustSupportPathsSet instanceof Set ? mustSupportPathsSet : new Set(mustSupportPathsSet || []);
    let mustSupportTitle = isMustSupport ? 'Must Support' : '';
    let fhirPathExpression = path;
    if (sliceName && isMustSupport) {
        mustSupportTitle = `Must Support (Slice: ${sliceName})`;
        fhirPathExpression = `${path}[sliceName='${sliceName}']`;
    }
    const msIconClass = (isMustSupport || node.containsMustSupportSlice) ? 'text-warning' : '';
    const mustSupportDisplay = (isMustSupport || node.containsMustSupportSlice) ? `<i class="bi bi-check-circle-fill ${msIconClass} ms-1" title="${escapeHtmlAttr(mustSupportTitle)}" data-bs-toggle="tooltip" data-fhirpath="${escapeHtmlAttr(fhirPathExpression)}"></i>` : '';

    // Styling Logic (V15 logic)
    let liClass = (isMustSupport || node.containsMustSupportSlice) ? 'list-group-item py-1 px-2 list-group-item-warning' : 'list-group-item py-1 px-2';
    if (view === 'differential') {
        if (!node.isInDifferential) { liClass += ' text-muted'; }
        if (max === '0') { liClass += ' text-decoration-line-through'; }
    }

    const hasActualChildren = node.children && node.children.length > 0;
    // Show toggle logic (V18 logic - reverted primitive filtering)
    const showToggle = hasActualChildren || definesSlicing || (isChoiceElement && !definesSlicing);

    // Collapse ID Generation (V13 logic)
    let uniquePartBase = nodeKey || path;
    if (!uniquePartBase || typeof uniquePartBase !== 'string') { uniquePartBase = `fallback-${level}-${Math.random()}`; }
    const uniquePart = uniquePartBase.replace(/[^a-zA-Z0-9\-:_]/g, '-') + `-${view}-${level}`;
    const collapseId = `collapse-${uniquePart}`;

    const padding = level * 20;
    const pathStyle = `padding-left: ${padding}px; white-space: nowrap;`;

    // Type String Logic
    let typeString = '<span class="text-muted">N/A</span>';
    if (el.type && Array.isArray(el.type) && el.type.length > 0) {
        typeString = el.type.map(t => {
            let s = escapeHtmlAttr(t.code || 'Unknown');
            let profiles = t.targetProfile || t.profile || [];
            if (profiles.length > 0) {
                const targetTypes = profiles.map(p => (p || '').split('/').pop()).filter(Boolean).join(', ');
                if (targetTypes) { s += `(<span class="fst-italic" title="Profile(s): ${escapeHtmlAttr(profiles.join(', '))}">${escapeHtmlAttr(targetTypes)}</span>)`; }
            }
            return s;
        }).join(' | ');
    } else if (el.contentReference) { typeString = `<span class="text-info" title="Content Reference">Ref: ${escapeHtmlAttr(el.contentReference)}</span>`; }
    else if (el.sliceName && path.endsWith('extension')) { typeString = '<span class="text-muted">Extension</span>'; }

    // Children HTML / Choice Type Display (V18 logic - reverted primitive filtering)
    let childrenOrChoiceHtml = '';
    if (showToggle) {
        childrenOrChoiceHtml += `<ul class="collapse list-group list-group-flush ms-3" id="${collapseId}">`;
        // Render children if they exist OR if slicing defined
        if (hasActualChildren || definesSlicing) {
            const sortedChildren = (node.children || []).sort((a, b) => (a.name || '').localeCompare(b.name || ''));
            sortedChildren.forEach(childNode => {
                if (childNode) { childrenOrChoiceHtml += renderNodeAsLi(childNode, mustSupportPathsSet, resourceType, level + 1, view); }
            });
        }
        // Render choice types ONLY if it's a choice element AND not sliced
        else if (isChoiceElement && !definesSlicing && el.type && Array.isArray(el.type)) {
            el.type.forEach(choiceType => {
                const typeCode = choiceType.code || 'Unknown';
                const baseName = (node.name || path.split('.').pop()).replace('[x]', '');
                const choiceDisplayName = escapeHtmlAttr(baseName + typeCode.charAt(0).toUpperCase() + typeCode.slice(1));
                const choiceTypeCode = escapeHtmlAttr(typeCode);
                const targetProfiles = choiceType.targetProfile || choiceType.profile || [];
                let profileDisplay = '';
                if (targetProfiles.length > 0) {
                    const targetTypes = targetProfiles.map(p => (p || '').split('/').pop()).filter(Boolean).join(', ');
                    if (targetTypes) { profileDisplay = ` (<span class="fst-italic" title="Profile(s): ${escapeHtmlAttr(targetProfiles.join(', '))}">${escapeHtmlAttr(targetTypes)}</span>)`; }
                }
                const choiceTooltipAttr = definition ? `title="${escapeHtmlAttr(definition)}"` : '';
                const choicePadding = padding + 20;
                childrenOrChoiceHtml += `<li class="list-group-item py-1 border-0 choice-type-item" ${choiceTooltipAttr} ${definition ? 'data-bs-toggle="tooltip" data-bs-placement="top"' : ''}>` +
                                        `<div class="row gx-2 align-items-center">` +
                                        `<div class="col-lg-4 col-md-3 text-truncate" style="padding-left: ${choicePadding}px;"><code>${choiceDisplayName}</code></div>` +
                                        `<div class="col-lg-1 col-md-1 text-center small"></div>` +
                                        `<div class="col-lg-3 col-md-3 text-truncate small"><code>${choiceTypeCode}</code>${profileDisplay}</div>` +
                                        `<div class="col-lg-1 col-md-1 text-center"></div>` +
                                        `<div class="col-lg-3 col-md-4 text-truncate small">${escapeHtmlAttr(short)}</div>` +
                                        `</div>` +
                                        `</li>`;
            });
        }
        childrenOrChoiceHtml += `</ul>`;
    }

    // Build list item HTML (Main row)
    let itemHtml = `<li class="${liClass}" style="display: block;">`;
    itemHtml += `<div class="row gx-2 align-items-center ${showToggle ? 'collapse-toggle' : ''}" ${showToggle ? `data-bs-toggle="collapse" data-bs-target="#${collapseId}" role="button" aria-expanded="false" aria-controls="${collapseId}" style="cursor: pointer;"` : ''}>`;
    itemHtml += `<div class="col-lg-4 col-md-3 text-truncate" style="${pathStyle}">`;
    itemHtml += `<span style="display: inline-block; width: 1.2em; text-align: center;">`;
    if (showToggle) itemHtml += `<i class="bi bi-chevron-right small toggle-icon"></i>`;
    itemHtml += `</span>`;
    let displayName = escapeHtmlAttr(node.name);
    if (definesSlicing && !isSlice) { displayName = `Slices for ${displayName}`; } // Use defined isSlice
    const pathTitle = fhirPathExpression ? `${path} (FHIRPath: ${fhirPathExpression})` : path;
    itemHtml += `<code class="fw-bold ms-1" title="${escapeHtmlAttr(pathTitle)}" data-bs-toggle="tooltip">${displayName}</code>`;
    itemHtml += `</div>`;
    const cardString = (min !== '' || max !== '') ? `${min}..${max}` : '';
    itemHtml += `<div class="col-lg-1 col-md-1 text-center small"><code>${cardString}</code></div>`;
    itemHtml += `<div class="col-lg-3 col-md-3 text-truncate small">${typeString}</div>`;
    itemHtml += `<div class="col-lg-1 col-md-1 text-center">${mustSupportDisplay}</div>`;
    const descriptionTooltipAttr = definition ? `title="${escapeHtmlAttr(definition)}"` : '';
    itemHtml += `<div class="col-lg-3 col-md-4 text-truncate small" ${descriptionTooltipAttr} ${definition ? 'data-bs-toggle="tooltip" data-bs-placement="top"' : ''}>${escapeHtmlAttr(short)}</div>`;
    itemHtml += `</div>`; // End row
    itemHtml += childrenOrChoiceHtml;
    itemHtml += `</li>`;
    return itemHtml;
} // End renderNodeAsLi (V19)

// --- Function to Initialize Collapse Icon Listeners (Bootstrap Events) V3 - Explicit Cleanup ---
function initializeBootstrapCollapseListeners(containerElement) {
    if (!containerElement) { return; }
    const viewName = containerElement.id.replace('structure-tree-', '');
    const collapseElements = containerElement.querySelectorAll('.collapse');
    collapseElements.forEach((collapseEl, index) => {
        const collapseId = collapseEl.id; if (!collapseId) { return; }
        const triggerEl = containerElement.querySelector(`[data-bs-target="#${collapseId}"]`);
        const icon = triggerEl?.querySelector('.toggle-icon');
        if (!triggerEl) { console.warn(`Trigger not found for #${collapseId}`); }
        if (collapseEl._handleShow && typeof collapseEl._handleShow === 'function') { collapseEl.removeEventListener('show.bs.collapse', collapseEl._handleShow); }
        if (collapseEl._handleHide && typeof collapseEl._handleHide === 'function') { collapseEl.removeEventListener('hide.bs.collapse', collapseEl._handleHide); }
        const handleShow = (event) => { if (event.target === collapseEl && icon) { icon.classList.replace('bi-chevron-right', 'bi-chevron-down'); } };
        const handleHide = (event) => { if (event.target === collapseEl && icon) { icon.classList.replace('bi-chevron-down', 'bi-chevron-right'); } };
        collapseEl._handleShow = handleShow; collapseEl._handleHide = handleHide;
        collapseEl.addEventListener('show.bs.collapse', handleShow);
        collapseEl.addEventListener('hide.bs.collapse', handleHide);
        if (icon) { /* Set initial icon */ if (collapseEl.classList.contains('show')) { icon.classList.replace('bi-chevron-right', 'bi-chevron-down'); } else { icon.classList.replace('bi-chevron-down', 'bi-chevron-right'); } }
    });
} // End initializeBootstrapCollapseListeners V3

// --- Render Structure Tree (Calls V13 buildTreeData, V19 renderNode, V3 initBSCollapse) ---
async function renderStructureTree(resourceType, view, snapshotElements, mustSupportPaths) { // Accepts snapshot elements
    const treeContainer = document.getElementById(`structure-tree-${view}`);
    if (!treeContainer) { console.error(`Tree container missing: ${view}`); return; }
    treeContainer.innerHTML = '';

    try {
        // Build tree using V13 buildTreeData and snapshot data
        const treeData = buildTreeData(snapshotElements, view, mustSupportPaths);

        // Render HTML using V19 renderNodeAsLi
        let html = '<p class="ms-2 mb-1"><small>...</small></p>'; // Legend
        html += '<ul class="list-group list-group-flush structure-tree-root">';
        if (treeData.length > 0 && treeData[0]) {
            html += renderNodeAsLi(treeData[0], mustSupportPaths, resourceType, 0, view); // V19 Call
        } else { html += `<li class="list-group-item"><em class="text-muted">No elements match...</em></li>`; }
        html += '</ul>';
        treeContainer.innerHTML = html;

        // Init listeners/tooltips
        initializeBootstrapCollapseListeners(treeContainer); // V3
        const tooltipTriggerList = treeContainer.querySelectorAll('[data-bs-toggle="tooltip"]');
        tooltipTriggerList.forEach(tooltipTriggerEl => { 
            const e = bootstrap.Tooltip.getInstance(tooltipTriggerEl); 
            if (e) { e.dispose(); }
            if (tooltipTriggerEl.getAttribute('title') || tooltipTriggerEl.getAttribute('data-bs-original-title')) {
                new bootstrap.Tooltip(tooltipTriggerEl);
            }
        });

    } catch (error) {
        console.error(`Error rendering ${view} tree:`, error);
        treeContainer.innerHTML = `<div class="alert alert-danger m-2">Error rendering ${view}: ${error.message}</div>`;
    }
} // End renderStructureTree

// --- Fetch Structure Definition for Specific View ---
async function fetchStructure(resourceType, view, includeNarrative, raw = false) {
    const cacheKey = `${resourceType}-${view}-${includeNarrative}-${raw}`;
    if (structureDataCache[cacheKey]) {
        try { return JSON.parse(JSON.stringify(structureDataCache[cacheKey])); } catch (e) { return structureDataCache[cacheKey]; }
    }
    const structureBaseUrl = "{{ url_for('get_structure') }}";
    const params = new URLSearchParams({ 
        package_name: "{{ processed_ig.package_name }}", 
        version: "{{ processed_ig.version }}",
        resource_type: resourceType, 
        view: view,
        include_narrative: includeNarrative,
        raw: raw
    });
    const fetchUrl = `${structureBaseUrl}?${params.toString()}`;
    try {
        const response = await fetch(fetchUrl);
        if (!response.ok) { throw new Error(`HTTP error ${response.status}`); }
        const data = await response.json();
        try { structureDataCache[cacheKey] = JSON.parse(JSON.stringify(data)); } catch(e) { structureDataCache[cacheKey] = data; }
        return JSON.parse(JSON.stringify(data));
    } catch (error) { console.error(`Error fetching ${raw ? 'raw' : view} structure:`, error); throw error; }
}

// --- Populate Structure for All Views - V5 (Add Search Param Logging, Include Narrative) ---
async function populateStructure(resourceType) {
    if (structureTitle) structureTitle.textContent = `${resourceType} ({{ processed_ig.package_name }}#{{ processed_ig.version }})`;
    if (rawStructureTitle) rawStructureTitle.textContent = `${resourceType} ({{ processed_ig.package_name }}#{{ processed_ig.version }})`;
    if (structureLoading) structureLoading.style.display = 'block';
    if (rawStructureLoading) rawStructureLoading.style.display = 'block';
    if (structureDisplayWrapper) structureDisplayWrapper.style.display = 'block';
    if (rawStructureWrapper) rawStructureWrapper.style.display = 'block';
    if (structureFallbackMessage) { structureFallbackMessage.style.display = 'none'; structureFallbackMessage.textContent = ''; }
    const views = ['differential', 'snapshot', 'must-support', 'key-elements'];
    views.forEach(v => { const tc = document.getElementById(`structure-tree-${v}`); if(tc) tc.innerHTML = ''; });
    const constraintsTableBody = document.getElementById('constraints-table')?.querySelector('tbody');
    const bindingsTableBody = document.getElementById('bindings-table')?.querySelector('tbody');
    const searchParamsTableBody = document.getElementById('searchparams-table')?.querySelector('tbody');
    if (constraintsTableBody) constraintsTableBody.innerHTML = '<tr><td colspan="5" class="text-center text-muted fst-italic">Loading...</td></tr>';
    if (bindingsTableBody) bindingsTableBody.innerHTML = '<tr><td colspan="4" class="text-center text-muted fst-italic">Loading...</td></tr>';
    if (searchParamsTableBody) searchParamsTableBody.innerHTML = '<tr><td colspan="4" class="text-center text-muted fst-italic">Loading...</td></tr>';
    if (rawStructureContent) rawStructureContent.textContent = 'Loading...';
    try {
        console.log(`PopulateStructure V4: Fetching structure and search params for ${resourceType}`);
        const includeNarrative = includeNarrativeCheckbox ? includeNarrativeCheckbox.checked : true;
        // Fetch processed data for UI tabs
        const processedData = await fetchStructure(resourceType, 'snapshot', includeNarrative, false);
        if (!processedData || !processedData.elements) { throw new Error(`Structure data or elements missing for ${resourceType}.`); }
        const snapshotElementsCopy = JSON.parse(JSON.stringify(processedData.elements));
        const mustSupportPaths = new Set(processedData.must_support_paths || []);
        const searchParams = processedData.search_parameters || [];
        const fallbackUsed = processedData.fallback_used || false;
        const sourcePackage = processedData.source_package || 'FHIR core';
        console.log('[populateStructure] Received search_parameters:', searchParams);
        // Fetch raw StructureDefinition for raw view
        const rawData = await fetchStructure(resourceType, 'snapshot', includeNarrative, true);
        if (rawStructureContent) {
            rawStructureContent.textContent = JSON.stringify(rawData, null, 4);
            if (rawStructureContent.classList.contains('hljs')) { rawStructureContent.classList.remove('hljs'); }
            rawStructureContent.dataset.highlighted = '';
            hljs.highlightElement(rawStructureContent);
            if (fallbackUsed && structureFallbackMessage) {
                structureFallbackMessage.textContent = `Note: Displaying structure from fallback package: ${sourcePackage}`;
                structureFallbackMessage.style.display = 'block';
            }
        } else { if (rawStructureContent) rawStructureContent.textContent = '(Raw content display element not found)'; }
        for (const view of views) {
            console.log(`PopulateStructure V4: Rendering view '${view}' for ${resourceType}`);
            const treeContainer = document.getElementById(`structure-tree-${view}`);
            if (!treeContainer) { console.error(`Container missing for ${view}`); continue; }
            await renderStructureTree(resourceType, view, JSON.parse(JSON.stringify(snapshotElementsCopy)), mustSupportPaths);
        }
        renderConstraintsTable(processedData.elements);
        renderBindingsTable(processedData.elements);
        renderSearchParametersTable(searchParams);
    } catch (error) {
        console.error("Error populating structure:", error);
        views.forEach(v => { const tc = document.getElementById(`structure-tree-${v}`); if(tc) tc.innerHTML = `<div class="alert alert-danger m-2">Error loading structure: ${error.message}</div>`; });
        if (constraintsTableBody) constraintsTableBody.innerHTML = `<tr><td colspan="5" class="text-danger text-center">Error loading constraints: ${error.message}</td></tr>`;
        if (bindingsTableBody) bindingsTableBody.innerHTML = `<tr><td colspan="4" class="text-danger text-center">Error loading bindings: ${error.message}</td></tr>`;
        if (searchParamsTableBody) searchParamsTableBody.innerHTML = `<tr><td colspan="4" class="text-danger text-center">Error loading search params: ${error.message}</td></tr>`;
        if (rawStructureContent) { rawStructureContent.textContent = `Error: ${error.message}`; }
    } finally {
        if (structureLoading) structureLoading.style.display = 'none';
        if (rawStructureLoading) rawStructureLoading.style.display = 'none';
    }
}// End populateStructure V5

// --- Populate Example Selector Dropdown ---
function populateExampleSelector(resourceOrProfileIdentifier) {
    if (!exampleResourceTypeTitle || !exampleSelect || !exampleContentWrapper || !exampleFilename || !exampleContentRaw || !exampleContentJson || !exampleLoading || !exampleSelectorWrapper || !examplesData) { return; }
    exampleResourceTypeTitle.textContent = resourceOrProfileIdentifier;
    const availableExamples = examplesData[resourceOrProfileIdentifier] || [];
    exampleSelect.innerHTML = '<option selected value="">-- Select an Example --</option>';
    exampleContentWrapper.style.display = 'none'; exampleFilename.textContent = ''; exampleContentRaw.textContent = ''; exampleContentJson.textContent = ''; exampleLoading.style.display = 'none';
    if (availableExamples.length > 0) {
        availableExamples.forEach(filePath => { const f=filePath.split('/').pop(); const o=document.createElement('option'); o.value=filePath; o.textContent=f; exampleSelect.appendChild(o); });
        exampleSelectorWrapper.style.display = 'block'; if (exampleDisplayWrapper) exampleDisplayWrapper.style.display = 'block';
    } else { exampleSelectorWrapper.style.display = 'none'; if (exampleDisplayWrapper) exampleDisplayWrapper.style.display = 'none'; }
}

// --- Fetch and Display Selected Example ---
async function fetchAndDisplayExample(selectedFilePath) {
    if (!exampleContentRaw || !exampleContentJson || !exampleFilename || !exampleContentWrapper || !exampleLoading) { return; }
    exampleContentRaw.textContent = ''; exampleContentJson.textContent = ''; exampleFilename.textContent = ''; exampleContentWrapper.style.display = 'none'; exampleLoading.style.display = 'block';
    const resetCopyButton = (button, tooltipInstance, originalTitle) => { if (tooltipInstance && button?.isConnected) { tooltipInstance.hide(); button.setAttribute('data-bs-original-title', originalTitle); button.querySelector('i')?.classList.replace('bi-check-lg', 'bi-clipboard'); } };
    resetCopyButton(copyRawExButton, copyRawExTooltipInstance, 'Copy Raw Content'); resetCopyButton(copyPrettyJsonButton, copyPrettyJsonTooltipInstance, 'Copy JSON');
    if (!selectedFilePath) { exampleLoading.style.display = 'none'; return; }
    const exampleBaseUrl = "{{ url_for('get_example') }}";
    const includeNarrative = includeNarrativeCheckbox ? includeNarrativeCheckbox.checked : true;
    const exampleParams = new URLSearchParams({ 
        package_name: "{{ processed_ig.package_name }}", 
        version: "{{ processed_ig.version }}",  // Changed from package_version to version
        filename: selectedFilePath,
        include_narrative: includeNarrative
    });
    const exampleFetchUrl = `${exampleBaseUrl}?${exampleParams.toString()}`;
    try {
        const response = await fetch(exampleFetchUrl); 
        if (!response.ok) { throw new Error(`HTTP error ${response.status}`); } 
        const rawData = await response.text();
        if(exampleFilename) exampleFilename.textContent = `Source: ${selectedFilePath.split('/').pop()}`; 
        if(exampleContentRaw) exampleContentRaw.textContent = rawData; 
        let prettyJson = '(Not valid JSON)';
        try { prettyJson = JSON.stringify(JSON.parse(rawData), null, 4); } catch (e) { prettyJson = rawData.startsWith('<') ? '(Content is XML, not JSON)' : `(Error parsing JSON: ${e.message})`; } 
        if(exampleContentJson) exampleContentJson.textContent = prettyJson;
        if (exampleContentRaw) hljs.highlightElement(exampleContentRaw); 
        if (exampleContentJson) hljs.highlightElement(exampleContentJson); 
        if(exampleContentWrapper) exampleContentWrapper.style.display = 'block';
    } catch (error) { 
        console.error("Error fetching or displaying example:", error); 
        if (exampleFilename) exampleFilename.textContent = 'Error loading example'; 
        if (exampleContentRaw) exampleContentRaw.textContent = `Error: ${error.message}`; 
        if (exampleContentJson) exampleContentJson.textContent = `Error: ${error.message}`; 
        if (exampleContentWrapper) exampleContentWrapper.style.display = 'block'; 
    } finally { 
        if (exampleLoading) exampleLoading.style.display = 'none'; 
    }
}

// --- Generic Copy Logic Function ---
function setupCopyButton(buttonElement, sourceElement, tooltipInstance, successTitle, originalTitle, errorTitle, nothingTitle) {
    if (!buttonElement || !sourceElement) { return null; }
    bootstrap.Tooltip.getInstance(buttonElement)?.dispose();
    tooltipInstance = new bootstrap.Tooltip(buttonElement, { title: originalTitle });
    const clickHandler = () => { 
        const textToCopy = sourceElement.textContent; 
        const copyIcon = buttonElement.querySelector('i'); 
        const updateTooltip = (newTitle, iconClass) => { 
            buttonElement.setAttribute('data-bs-original-title', newTitle); 
            tooltipInstance?.setContent({ '.tooltip-inner': newTitle }); 
            tooltipInstance?.show(); 
            if (copyIcon) copyIcon.className = `bi ${iconClass}`; 
            setTimeout(() => { 
                if (buttonElement.isConnected) { 
                    tooltipInstance?.hide(); 
                    buttonElement.setAttribute('data-bs-original-title', originalTitle); 
                    if (copyIcon) copyIcon.className = 'bi bi-clipboard'; 
                } 
            }, 1500); 
        }; 
        if (textToCopy && textToCopy.trim() && !textToCopy.startsWith('(Could not') && !textToCopy.startsWith('(Not valid') && !textToCopy.startsWith('Error:')) { 
            navigator.clipboard.writeText(textToCopy).then(() => { 
                updateTooltip(successTitle, 'bi-check-lg'); 
            }).catch(err => { 
                console.error(`Copy failed:`, err); 
                updateTooltip(errorTitle, 'bi-exclamation-triangle'); 
            }); 
        } else { 
            updateTooltip(nothingTitle, 'bi-clipboard'); 
        } 
    };
    buttonElement.removeEventListener('click', clickHandler); 
    buttonElement.addEventListener('click', clickHandler); 
    return tooltipInstance;
}

// --- Function to Render Constraints Table ---
function renderConstraintsTable(elements) {
    const tableBody = document.getElementById('constraints-table')?.querySelector('tbody');
    if (!tableBody) {
        console.error('Constraints table body not found');
        return;
    }
    tableBody.innerHTML = ''; // Clear existing rows
    let constraintsFound = false;

    if (!elements || !Array.isArray(elements)) {
        console.warn("renderConstraintsTable called with invalid elements data:", elements);
        elements = []; // Prevent errors later
    }

    elements.forEach(element => {
        if (element && element.constraint && Array.isArray(element.constraint) && element.constraint.length > 0) {
            element.constraint.forEach(constraint => {
                if (constraint) { // Ensure constraint object itself exists
                    constraintsFound = true;
                    const row = tableBody.insertRow();
                    row.insertCell().textContent = constraint.key || 'N/A';
                    row.insertCell().textContent = constraint.severity || 'N/A';
                    row.insertCell().textContent = element.path || 'N/A'; // Path of the element the constraint is on
                    row.insertCell().textContent = constraint.human || 'N/A';
                    const expressionCell = row.insertCell();
                    const codeElement = document.createElement('code');
                    codeElement.className = 'language-fhirpath'; // Use 'language-fhirpath' if you have a FHIRPath grammar for highlight.js
                    codeElement.textContent = constraint.expression || 'N/A';
                    expressionCell.appendChild(codeElement);
                }
            });
        }
    });

    if (!constraintsFound) {
        const row = tableBody.insertRow();
        const cell = row.insertCell();
        cell.colSpan = 5; // Match number of columns
        cell.textContent = 'No constraints defined in this profile.';
        cell.style.textAlign = 'center';
    }

    // Re-run highlight.js for the new code blocks
    setTimeout(() => {
        document.querySelectorAll('#constraints-table code.language-fhirpath').forEach((block) => {
            block.classList.remove('hljs');
            hljs.highlightElement(block);
        });
    }, 0);
}

// --- Function to Render Terminology Bindings Table ---
function renderBindingsTable(elements) {
    const tableBody = document.getElementById('bindings-table')?.querySelector('tbody');
    if (!tableBody) {
        console.error('Bindings table body not found');
        return;
    }
    tableBody.innerHTML = ''; // Clear existing rows
    let bindingsFound = false;

    if (!elements || !Array.isArray(elements)) {
        console.warn("renderBindingsTable called with invalid elements data:", elements);
        elements = []; // Prevent errors later
    }

    elements.forEach(element => {
        if (element && element.binding && typeof element.binding === 'object') {
            bindingsFound = true;
            const binding = element.binding;
            const row = tableBody.insertRow();
            row.insertCell().textContent = element.path || 'N/A';
            row.insertCell().textContent = binding.strength || 'N/A';
            const valueSetCell = row.insertCell();
            if (binding.valueSet) {
                const valueSetLink = document.createElement('a');
                valueSetLink.href = binding.valueSet; // Ideally, resolve canonical to actual URL if possible
                const urlParts = binding.valueSet.split('/');
                valueSetLink.textContent = urlParts.length > 1 ? urlParts[urlParts.length - 1] : binding.valueSet;
                valueSetLink.target = '_blank'; // Open in new tab
                valueSetLink.title = `Open ValueSet: ${binding.valueSet}`; // Add tooltip
                valueSetLink.setAttribute('data-bs-toggle', 'tooltip'); // Enable tooltip
                valueSetCell.appendChild(valueSetLink);
                // Re-initialize tooltips for dynamically added links
                const tooltip = new bootstrap.Tooltip(valueSetLink);
            } else {
                valueSetCell.textContent = 'N/A';
            }
            row.insertCell().textContent = binding.description || 'N/A';
        }
    });

    if (!bindingsFound) {
        const row = tableBody.insertRow();
        const cell = row.insertCell();
        cell.colSpan = 4; // Match number of columns
        cell.textContent = 'No terminology bindings defined in this profile.';
        cell.style.textAlign = 'center';
    }
}

// --- Function to Render Search Parameters Table (Includes Conformance Badges & Tooltips) ---
function renderSearchParametersTable(searchParamsData) {
    const tableBody = document.getElementById('searchparams-table')?.querySelector('tbody');
    if (!tableBody) {
        console.error('Search Params table body element (#searchparams-table > tbody) not found');
        return;
    }

    tableBody.innerHTML = '';
    console.log('[renderSearchParametersTable] Received data:', searchParamsData);

    if (!searchParamsData || !Array.isArray(searchParamsData) || searchParamsData.length === 0) {
        console.log('[renderSearchParametersTable] No valid search parameter data found, displaying message.');
        const row = tableBody.insertRow();
        const cell = row.insertCell();
        cell.colSpan = 4;
        cell.textContent = 'No relevant search parameters found for this resource type.';
        cell.style.textAlign = 'center';
        cell.classList.add('text-muted', 'fst-italic');
        return;
    }

    searchParamsData.sort((a, b) => (a.code || '').localeCompare(b.code || ''));

    searchParamsData.forEach((param, index) => {
        console.log(`[renderSearchParametersTable] Processing param ${index + 1}:`, param);
        const row = tableBody.insertRow();
        const nameCell = row.insertCell();
        nameCell.innerHTML = `<code>${escapeHtmlAttr(param.code || 'N/A')}</code>`;
        row.insertCell().textContent = param.type || 'N/A';
        const conformanceCell = row.insertCell();
        const conformanceValue = param.conformance || 'Optional';
        let badgeClass = 'bg-secondary';
        let titleText = 'Conformance level not specified in CapabilityStatement.';
        if (conformanceValue === 'SHALL') {
            badgeClass = 'bg-danger';
            titleText = 'Server SHALL support this parameter.';
        } else if (conformanceValue === 'SHOULD') {
            badgeClass = 'bg-warning text-dark';
            titleText = 'Server SHOULD support this parameter.';
        } else if (conformanceValue === 'MAY') {
            badgeClass = 'bg-info text-dark';
            titleText = 'Server MAY support this parameter.';
        } else if (conformanceValue === 'Optional') {
            badgeClass = 'bg-light text-dark border';
            titleText = 'Server support for this parameter is optional.';
        }
        conformanceCell.setAttribute('title', titleText);
        conformanceCell.setAttribute('data-bs-toggle', 'tooltip');
        conformanceCell.setAttribute('data-bs-placement', 'top');
        conformanceCell.innerHTML = `<span class="badge ${badgeClass}">${escapeHtmlAttr(conformanceValue)}</span>`;
        const existingTooltip = bootstrap.Tooltip.getInstance(conformanceCell);
        if (existingTooltip) { existingTooltip.dispose(); }
        new bootstrap.Tooltip(conformanceCell);
        const descriptionCell = row.insertCell();
        descriptionCell.innerHTML = `<small>${escapeHtmlAttr(param.description || 'No description available.')}</small>`;
        if (param.expression) {
            descriptionCell.setAttribute('title', `FHIRPath: ${param.expression}`);
            descriptionCell.setAttribute('data-bs-toggle', 'tooltip');
            descriptionCell.setAttribute('data-bs-placement', 'top');
            const existingDescTooltip = bootstrap.Tooltip.getInstance(descriptionCell);
            if (existingDescTooltip) { existingDescTooltip.dispose(); }
            new bootstrap.Tooltip(descriptionCell);
        }
    });
    console.log('[renderSearchParametersTable] Finished rendering parameters.');
} // End renderSearchParametersTable

// --- DOMContentLoaded Listener ---
document.addEventListener('DOMContentLoaded', function() {
    try {
        // --- Assign Global Variables to DOM Elements ---
        structureDisplayWrapper = document.getElementById('structure-display-wrapper');
        structureTitle = document.getElementById('structure-title');
        structureLoading = document.getElementById('structure-loading');
        structureFallbackMessage = document.getElementById('structure-fallback-message');
        structureTreeDifferential = document.getElementById('structure-tree-differential');
        structureTreeSnapshot = document.getElementById('structure-tree-snapshot');
        structureTreeMustSupport = document.getElementById('structure-tree-must-support');
        structureTreeKeyElements = document.getElementById('structure-tree-key-elements');
        exampleDisplayWrapper = document.getElementById('example-display-wrapper');
        exampleSelectorWrapper = document.getElementById('example-selector-wrapper');
        exampleSelect = document.getElementById('example-select');
        exampleResourceTypeTitle = document.getElementById('example-resource-type-title');
        exampleLoading = document.getElementById('example-loading');
        exampleContentWrapper = document.getElementById('example-content-wrapper');
        exampleFilename = document.getElementById('example-filename');
        exampleContentRaw = document.getElementById('example-content-raw');
        exampleContentJson = document.getElementById('example-content-json');
        rawStructureWrapper = document.getElementById('raw-structure-wrapper');
        rawStructureTitle = document.getElementById('raw-structure-title');
        rawStructureContent = document.getElementById('raw-structure-content');
        rawStructureLoading = document.getElementById('raw-structure-loading');
        copyRawDefButton = document.getElementById('copy-raw-def-button');
        copyRawExButton = document.getElementById('copy-raw-ex-button');
        copyPrettyJsonButton = document.getElementById('copy-pretty-json-button');
        includeNarrativeCheckbox = document.getElementById('includeNarrative');

        // --- Initialize Highlight.js ---
        hljs.configure({ languages: ['json'] });

        // --- Initialize Tooltips for static elements ---
        const staticTooltips = document.querySelectorAll('[data-bs-toggle="tooltip"]');
        staticTooltips.forEach(t => { if (!bootstrap.Tooltip.getInstance(t)) { new bootstrap.Tooltip(t); } });

        // --- Event Listener Setup ---
        copyRawDefTooltipInstance = setupCopyButton(copyRawDefButton, rawStructureContent, copyRawDefTooltipInstance, 'Copied Definition!', 'Copy Raw Definition JSON', 'Copy Failed!', 'Nothing to copy');
        copyRawExTooltipInstance = setupCopyButton(copyRawExButton, exampleContentRaw, copyRawExTooltipInstance, 'Copied Raw!', 'Copy Raw Content', 'Copy Failed!', 'Nothing to copy');
        copyPrettyJsonTooltipInstance = setupCopyButton(copyPrettyJsonButton, exampleContentJson, copyPrettyJsonTooltipInstance, 'Copied JSON!', 'Copy JSON', 'Copy Failed!', 'Nothing to copy');

        // Resource Type Link Click Handler
        document.querySelectorAll('.resource-type-list').forEach(container => {
            container.addEventListener('click', async function(event) {
                const link = event.target.closest('.resource-type-link');
                if (!link) return;
                event.preventDefault();
                const resourceType = link.dataset.resourceType;
                if (!resourceType) { console.error("Missing data-resource-type"); return; }
                console.log("Resource type link clicked:", resourceType);
                await populateStructure(resourceType);
                populateExampleSelector(resourceType);
                if (structureDisplayWrapper) { structureDisplayWrapper.scrollIntoView({ behavior: 'smooth', block: 'start' }); }
            });
        });

        // Example Select Dropdown Change Handler
        if (exampleSelect) {
            exampleSelect.addEventListener('change', function(event) { fetchAndDisplayExample(this.value); });
        } else { console.warn("Example select dropdown not found."); }

        // Narrative Toggle Checkbox Handler
        if (includeNarrativeCheckbox) {
            includeNarrativeCheckbox.addEventListener('change', async function() {
                const selectedFilePath = exampleSelect?.value;
                const resourceType = exampleResourceTypeTitle?.textContent;
                if (selectedFilePath) {
                    await fetchAndDisplayExample(selectedFilePath);
                }
                if (resourceType && resourceType !== '(unknown)') {
                    await populateStructure(resourceType);
                }
            });
        } else {
            console.warn("Narrative checkbox not found.");
        }

        // --- Initial UI State ---
        if(structureDisplayWrapper) structureDisplayWrapper.style.display = 'none';
        if(rawStructureWrapper) rawStructureWrapper.style.display = 'none';
        if(exampleDisplayWrapper) exampleDisplayWrapper.style.display = 'none';
        if(structureLoading) structureLoading.style.display = 'none';
        if(rawStructureLoading) rawStructureLoading.style.display = 'none';
        if(exampleLoading) exampleLoading.style.display = 'none';
        if(structureFallbackMessage) structureFallbackMessage.style.display = 'none';

    } catch (e) {
        console.error("JavaScript error during DOMContentLoaded setup:", e);
        const body = document.querySelector('body');
        if (body) {
            const errorDiv = document.createElement('div');
            errorDiv.className = 'alert alert-danger m-3';
            errorDiv.textContent = 'A critical error occurred while initializing the page view.';
            if(body.firstChild) { body.insertBefore(errorDiv, body.firstChild); } else { body.appendChild(errorDiv); }
        }
    }
}); // End DOMContentLoaded Listener

// --- END OF COMPLETE SCRIPT BLOCK ---
</script>
{% endblock %}