(function () {


    function escapeHtml(text) {
        return String(text ?? "")
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#39;");
    }

    function sanitizeRichText(html) {
        return typeof DOMPurify !== "undefined"
            ? DOMPurify.sanitize(String(html ?? ""), { USE_PROFILES: { html: true } })
            : escapeHtml(html);
    }

    let loadingEl;
    let suggestionsEl;
    let selectedDescriptionText = "";
    let appendedDescriptions = [];
    let appendedSuggestionKeys = new Set();
    let suggestionHistory = [];
    let suggestions = [];
    let historyAcceptedSuggestions = [];
    let cachedWorkItem = null;
    var context = null;
    const DISCUSSION_REF = "System.History";
    const STEPS_REF = "Microsoft.VSTS.TCM.Steps";

    const GROOM_FIELDS = [
        { label: "Description", ref: "System.Description" },
        { label: "Acceptance Criteria", ref: "Microsoft.VSTS.Common.AcceptanceCriteria" },
        { label: "System Info", ref: "Microsoft.VSTS.TCM.SystemInfo" },
        { label: "Steps to Repro", ref: "Microsoft.VSTS.TCM.ReproSteps" },
        { label: "Discussion", ref: DISCUSSION_REF },
        { label: "Steps", ref: STEPS_REF }
    ];

    let availableGroomFields = [GROOM_FIELDS[0]];
    let selectedGroomFieldRef = GROOM_FIELDS[0].ref;


    async function init() {

        context = await getContext();
        const root = document.querySelector(".qa-groom-root");
        if (!root) {
            console.warn("qa-groom-root not found");
            return;
        }

        loadingEl = document.getElementById("qa-groom-loading");
        suggestionsEl = document.getElementById("groom-suggestions-list");

        wireEvents();
        wireFieldDropdown();
        await populateFieldDropdown();

        // -----------------------------
        // 1. Fetch existing chat context if any
        // -----------------------------
        GetGroomAssistChat();

    }

    async function populateFieldDropdown() {
        const menu = document.getElementById("groom-field-menu");
        if (!menu) return;

        availableGroomFields = [GROOM_FIELDS[0]];

        try {
            if (context.workItemId) {
                const wi = await IndexLibrary.GetWorkItemWithFields(
                    context.workItemId,
                    ["System.WorkItemType"]
                );
                const witName = wi?.fields?.["System.WorkItemType"];

                if (witName) {
                    const supportedRefs = await IndexLibrary.GetWorkItemTypeFieldRefNames(witName);
                    const supportedSet = new Set(supportedRefs || []);
                    const filtered = GROOM_FIELDS.filter(f => supportedSet.has(f.ref));
                    if (filtered.length) {
                        availableGroomFields = filtered;
                    }
                }
            }
        } catch (e) {
            console.warn("Failed to resolve groomable fields for work item type", e);
        }

        if (!availableGroomFields.some(f => f.ref === selectedGroomFieldRef)) {
            selectedGroomFieldRef = availableGroomFields[0].ref;
        }

        menu.innerHTML = "";
        availableGroomFields.forEach(f => {
            const opt = document.createElement("li");
            opt.setAttribute("role", "option");
            opt.dataset.ref = f.ref;
            opt.textContent = f.label;
            opt.addEventListener("click", () => {
                selectedGroomFieldRef = f.ref;
                renderFieldDropdown();
                menu.classList.add("hidden");
                renderSuggestions();
            });
            menu.appendChild(opt);
        });

        renderFieldDropdown();
    }

    function renderFieldDropdown() {
        const selected = getSelectedField();
        const labelEl = document.getElementById("groom-field-label");
        if (labelEl) labelEl.textContent = selected.label;

        document.querySelectorAll("#groom-field-menu li").forEach(li => {
            li.setAttribute("aria-selected", li.dataset.ref === selected.ref ? "true" : "false");
        });
    }

    function wireFieldDropdown() {
        const dropdown = document.getElementById("groom-field-dropdown");
        const toggle = document.getElementById("groom-field-toggle");
        const menu = document.getElementById("groom-field-menu");
        if (!dropdown || !toggle || !menu) return;

        toggle.addEventListener("click", (e) => {
            e.stopPropagation();
            if (!toggle.disabled) menu.classList.toggle("hidden");
        });

        document.addEventListener("click", (e) => {
            if (!dropdown.contains(e.target)) menu.classList.add("hidden");
        });

        document.addEventListener("keydown", (e) => {
            if (e.key === "Escape") menu.classList.add("hidden");
        });
    }

    function getSelectedField() {
        return availableGroomFields.find(f => f.ref === selectedGroomFieldRef)
            || availableGroomFields[0]
            || GROOM_FIELDS[0];
    }

    function isGroomReadOnlyUser() {
        const userType =
            window.QALicenseContext?.productUserTypes?.groom;
        return userType === 0;
    }

    async function GetGroomAssistChat() {


        try {

            if (!context.workItemId) return;
            const createdBy = context.userName || context.userEmail;

            const res = await IndexLibrary.GetRequest({
                baseAPIUrl: context.baseAPIUrl,
                endpoint: `/api/Groom/GetChatByContext?organizationId=${context.organizationId}&devOpsProjectId=${context.projectId}&workItemId=${context.workItemId}&createdBy=${encodeURIComponent(createdBy)}`,
                azureAuthenticationHeader: context.accessToken,
                organizationName: context.organizationName,
                organizationId: context.organizationId
            });

            if (res.ok) {
                const data = await res.json();


                if (data) {
                    // 1. Pre-fill prompt input with previous QueryContext
                    const promptInput = getPromptInput();
                    if (promptInput && data.queryContext) {
                        promptInput.value = data.queryContext;
                    }

                    // 2. Load suggestions and accepted suggestions
                    const normalSuggestions = data.suggestions ? JSON.parse(data.suggestions) : [];
                    const accepted = data.acceptedSuggestions ? JSON.parse(data.acceptedSuggestions) : [];
                    // -----------------------------
                    // SAFE: Parse suggestion history
                    // -----------------------------
                    suggestionHistory = [];

                    if (data && data.suggestionsHistory) {
                        try {
                            const historyRaw = JSON.parse(data.suggestionsHistory);

                            if (Array.isArray(historyRaw)) {
                                suggestionHistory = historyRaw
                                    .map(h => {
                                        try {
                                            return JSON.parse(h);
                                        } catch {
                                            return null;
                                        }
                                    })
                                    .filter(h => Array.isArray(h) && h.length);
                            }
                        } catch (e) {
                            console.warn("Invalid suggestionsHistory JSON", e);
                            suggestionHistory = [];
                        }
                    }

                    const mainAccepted = accepted.filter(a => !a.fromHistory);
                    historyAcceptedSuggestions = accepted
                        .filter(a => a.fromHistory)
                        .map(a => ({
                            Title: a.Title ?? a.title ?? "",
                            Description: a.Description ?? a.description ?? "",
                            fieldRef: a.fieldRef ?? a.FieldRef
                        }));

                    // Merge suggestions, mark accepted ones
                    suggestions = normalSuggestions.map(s => ({ ...s, isAccepted: false }));

                    mainAccepted.forEach(a => {
                        const exists = suggestions.find(s => s.Title === a.Title && s.Description === a.Description);
                        if (exists) {
                            exists.isAccepted = true; // mark checkbox as checked
                        } else {
                            suggestions.push({ ...a, isAccepted: true });
                        }
                    });

                    // -----------------------------
                    // FIX: Populate selectedDescriptionText for already accepted suggestions
                    // -----------------------------
                    rebuildSelectedDescriptionText();

                    // Enable the Append button if any accepted suggestions exist
                    updateAppendButtonState();

                    renderSuggestions();


                }

            } else {
                console.warn("No existing chat found for this context.");
                renderSuggestions(); // still render to show "No suggestions" message

            }
        } catch (e) {
            console.error("Failed to fetch existing GaChat:", e);

        }
    }
    function wireEvents() {
        document.getElementById("groom-generate-btn").addEventListener("click", onGenerate);
        document.getElementById("groom-select-all").addEventListener("change", onSelectAllChanged);
        document.getElementById("groom-appendtodescription-btn").addEventListener("click", onAppendToDescription);
    }

    function onSelectAllChanged(e) {
        const checked = e.target.checked;
        const checkboxes = document.querySelectorAll(".qa-suggestion-checkbox");

        checkboxes.forEach(cb => {
            cb.checked = checked;
            const index = parseInt(cb.dataset.index, 10);
            suggestions[index].isAccepted = checked;
        });

        rebuildSelectedDescriptionText();
        updateAppendButtonState();

        // ✅ NEW
        saveGroomAssistState();
    }


    async function getContext() {
        await window.ensureSDKReady();
        return window.QAContext;
    }

    function getPromptInput() {
        return document.getElementById("groom-prompt-input");
    }

    function showLoading() {
        loadingEl.classList.remove("hidden");
        suggestionsEl.innerHTML = "";
        setGenerateEnabled(false);
    }


    function hideLoading() {
        loadingEl.classList.add("hidden");
        setGenerateEnabled(true);
    }

    function setGenerateEnabled(enabled) {
        const btn = document.getElementById("groom-generate-btn");
        const input = getPromptInput();
        btn.disabled = !enabled;
        input.disabled = !enabled;
        btn.style.opacity = enabled ? "1" : "0.6";
    }

    function showInlineError(msg) {
        const el = document.getElementById("groom-prompt-error");
        el.textContent = msg;
        el.classList.remove("hidden");
    }

    function clearInlineError() {
        const el = document.getElementById("groom-prompt-error");
        el.textContent = "";
        el.classList.add("hidden");
    }

    function suggestionKey(s) {
        const title = (s.Title ?? s.title ?? "").trim().toLowerCase();
        const desc = (s.Description ?? s.description ?? "").trim().toLowerCase();
        return `${title}|||${desc}`;
    }

    function belongsToSelectedField(s) {
        const ref = s.fieldRef ?? s.FieldRef;
        return !ref || ref === selectedGroomFieldRef;
    }

    function sameHistorySuggestion(h, s) {
        const hTitle = h.Title ?? h.title ?? "";
        const sTitle = s.Title ?? s.title ?? "";
        const hDesc = h.Description ?? h.description ?? "";
        const sDesc = s.Description ?? s.description ?? "";
        return hTitle === sTitle && hDesc === sDesc;
    }

    function rebuildSelectedDescriptionText() {
        const mainParts = suggestions.filter(s => s.isAccepted && belongsToSelectedField(s)).map(s => s.Description);
        const historyParts = historyAcceptedSuggestions.filter(belongsToSelectedField).map(s => s.Description);
        selectedDescriptionText = [...mainParts, ...historyParts].filter(Boolean).join("\n\n");
    }

    function updateAppendButtonState() {
        const btn = document.getElementById("groom-appendtodescription-btn");
        if (!btn) return;
        if (isGroomReadOnlyUser()) {
            btn.disabled = true;
            btn.title =
                "You do not have permission to Append Description.";
            return;
        }
        const shouldDisable = !selectedDescriptionText?.trim();
        btn.disabled = shouldDisable;
        btn.style.backgroundColor = shouldDisable ? "#c8c6c4" : "#0078d4";
        btn.style.cursor = shouldDisable ? "not-allowed" : "pointer";
    }

    async function onGenerate() {

        const prompt = getPromptInput().value.trim();
        clearInlineError();

        if (!prompt) {
            showInlineError("Please describe what you want grooming suggestions for.");
            return;
        }

        showLoading();

        try {

            if (!context.workItemId) {
                showError("Work item ID not found in context.");
                return;
            }

            const selectedField = getSelectedField();

            const fields = ["System.Id", "System.Title", "System.WorkItemType", "System.State", selectedField.ref];
            cachedWorkItem = await IndexLibrary.GetWorkItemWithFields(context.workItemId, fields);

            const workItemContext = {
                id: context.workItemId,
                title: cachedWorkItem.fields["System.Title"] || "",
                type: cachedWorkItem.fields["System.WorkItemType"] || "",
                state: cachedWorkItem.fields["System.State"] || "",
                description: cachedWorkItem.fields[selectedField.ref] || "",
                targetFieldLabel: selectedField.label
            };

            const payload = {
                devopsProjectId: context.projectId,
                devopsProjectName: context.projectName,
                organizationName: context.organizationName,
                createdBy: context.userName || context.userEmail,
                promptText: prompt,
                workItemContext: workItemContext
            };

            // Fetch suggestions from API
            const res = await IndexLibrary.PostRequest({
                baseAPIUrl: context.baseAPIUrl,
                endpoint: `/api/Groom/GenerateSuggestions`,
                azureAuthenticationHeader: context.accessToken,
                organizationName: context.organizationName,
                organizationId: context.organizationId,
                body: payload
            });

            if (!res.ok) {
                const err = await res.text();
                showError(err || "Failed to generate grooming suggestions.");
                return;
            }

            const data = await res.json();


            // Parse normal suggestions
            const normalSuggestions = Array.isArray(data.suggestions) ? data.suggestions : [];

            const otherFieldSuggestions = suggestions.filter(s => !belongsToSelectedField(s));
            const currentFieldSuggestions = suggestions.filter(s => belongsToSelectedField(s));

            const unselected = currentFieldSuggestions
                .filter(s => !s.isAccepted)
                .map(s => ({ Title: s.Title, Description: s.Description, fieldRef: selectedField.ref }));

            if (unselected.length) {
                suggestionHistory.unshift(unselected);
            }
            const keptAccepted = currentFieldSuggestions
                .filter(s => s.isAccepted)
                .map(s => ({ ...s, fieldRef: selectedField.ref }));

            const existingKeys = new Set();
            keptAccepted.forEach(s => existingKeys.add(suggestionKey(s)));
            suggestionHistory.forEach(batch => {
                if (Array.isArray(batch)) batch.forEach(s => existingKeys.add(suggestionKey(s)));
            });
            historyAcceptedSuggestions.forEach(s => existingKeys.add(suggestionKey(s)));
            appendedSuggestionKeys.forEach(k => existingKeys.add(k));

            const fresh = [];
            normalSuggestions.forEach(s => {
                const key = suggestionKey(s);
                if (existingKeys.has(key)) return;
                existingKeys.add(key);
                fresh.push({ ...s, isAccepted: false, fieldRef: selectedField.ref });
            });

            suggestions = [...otherFieldSuggestions, ...keptAccepted, ...fresh];

            // Render main suggestions
            renderSuggestions();

            await saveGroomAssistState();

        } catch (e) {
            console.error(e);
            showError("Unexpected error occurred.");
        } finally {
            hideLoading();
        }
    }


    function renderSuggestions() {
        suggestionsEl.innerHTML = "";

        const visibleSuggestions = suggestions
            .map((s, index) => ({ s, index }))
            .filter(({ s }) => belongsToSelectedField(s));

        if (!visibleSuggestions.length) {
            rebuildSelectedDescriptionText();
            updateAppendButtonState();
            const emptyWrapper = document.createElement("div");
            emptyWrapper.className = "qa-empty-state-card";

            emptyWrapper.innerHTML = `
                <div class="qa-no-suggestions">
                    No items, please generate suggestions
                </div>`;
            suggestionsEl.appendChild(emptyWrapper);
            if (suggestionHistory.length) {
                renderSuggestionHistory();
                const footer = document.getElementById("groom-footer");
                if (footer) footer.classList.remove("hidden");
            }
            return;
        }

        visibleSuggestions.forEach(({ s, index }) => {
            const item = document.createElement("div");
            item.className = "qa-groom-suggestion-item";

            // Add a class if this came from history
            if (s.fromHistory) {
                item.classList.add("qa-from-history");
            }

            item.innerHTML = `
        <div class="qa-groom-header">
            <label class="qa-checkbox">
                <input
                    type="checkbox"
                    class="qa-suggestion-checkbox"
                    data-index="${index}"
                    ${s.isAccepted ? "checked" : ""}
                />
            </label>

            <span class="qa-groom-title qa-toggle-title" data-index="${index}">
                ${escapeHtml(s.Title || "")}
                ${s.fromHistory ? '<span class="qa-history-badge">(From History)</span>' : ''}
            </span>

            <button class="qa-accordion-toggle" data-index="${index}">
             <i class="bi bi-caret-down-fill qa-arrow"></i>
            </button>
        </div>

        <div class="qa-groom-description hidden" id="qa-desc-${index}">
            ${sanitizeRichText(s.Description || "")}
        </div>
        `;

            suggestionsEl.appendChild(item);
        });

        // Event bindings for current suggestions
        document.querySelectorAll(".qa-suggestion-checkbox").forEach(cb => {
            cb.addEventListener("change", onSuggestionChanged);
        });

        document.querySelectorAll(".qa-accordion-toggle, .qa-toggle-title").forEach(el => {
            el.addEventListener("click", toggleAccordion);
        });

        // Initialize selectedDescriptionText with all accepted suggestions
        rebuildSelectedDescriptionText();

        // Update "Select All" checkbox based on accepted suggestions
        const allChecked = visibleSuggestions.length && visibleSuggestions.every(({ s }) => s.isAccepted);
        document.getElementById("groom-select-all").checked = allChecked;

        updateAppendButtonState();

        // Render history separately if not already rendered
        const hasHistory = suggestionHistory.length > 0;
        if (hasHistory && !document.querySelector(".qa-history-container")) {
            renderSuggestionHistory();
        }

        // Show footer
        const footer = document.getElementById("groom-footer");
        if (footer) footer.classList.remove("hidden");
    }

    function renderSuggestionHistory() {
        const historyRoot = document.getElementById("groom-suggestions-list");
        if (!historyRoot) return;

        // Check if history is already expanded
        const existingContainer = historyRoot.querySelector(".qa-history-container");
        const wasExpanded = existingContainer && !existingContainer.classList.contains("hidden");

        // Remove old history
        const oldHistory = historyRoot.querySelector(".qa-history-header");
        const oldContainer = historyRoot.querySelector(".qa-history-container");

        if (oldHistory) oldHistory.remove();
        if (oldContainer) oldContainer.remove();

        const visibleBatches = (Array.isArray(suggestionHistory) ? suggestionHistory : [])
            .map((batch, index) => ({ batch, index }))
            .filter(({ batch }) => Array.isArray(batch) && batch.some(belongsToSelectedField));

        if (!visibleBatches.length) return;

        // Create header
        const header = document.createElement("div");
        header.className = "qa-history-header";

        // Set initial arrow based on previous state
        const initialClass = wasExpanded ? "bi-caret-up-fill" : "bi-caret-down-fill";
        header.innerHTML = `
    <span class="qa-history-title">
        Previous Suggestions (${visibleBatches.length})
    </span>
    <span class="qa-history-arrow">
        <i class="bi ${initialClass}"></i>
    </span>
`;


        // Create container
        const container = document.createElement("div");
        container.className = wasExpanded ? "qa-history-container" : "qa-history-container hidden";

        // Track which batches are expanded
        let expandedCount = wasExpanded ? 1 : 0;

        header.addEventListener('click', function () {
            container.classList.toggle("hidden");

            // Toggle Bootstrap caret icon
            const icon = header.querySelector(".qa-history-arrow i");
            if (container.classList.contains("hidden")) {
                icon.classList.remove("bi-caret-up-fill");
                icon.classList.add("bi-caret-down-fill");
            } else {
                icon.classList.remove("bi-caret-down-fill");
                icon.classList.add("bi-caret-up-fill");
            }

            if (!container.classList.contains("hidden")) {
                expandedCount = visibleBatches.length;
                renderVisibleBatches();
            } else {
                container.innerHTML = '';
                expandedCount = 0;
            }
        });


        // Function to render visible batches
        function renderVisibleBatches() {
            container.innerHTML = '';

            for (let v = 0; v < expandedCount && v < visibleBatches.length; v++) {
                const { batch, index: i } = visibleBatches[v];

                // 🔹 Batch wrapper (bordered group)
                const batchWrapper = document.createElement("div");
                batchWrapper.className = "qa-history-batch";

                // Click last batch to load next one
                batchWrapper.addEventListener("click", function (e) {
                    if (
                        v === expandedCount - 1 &&
                        expandedCount < visibleBatches.length
                    ) {
                        expandedCount++;
                        renderVisibleBatches();
                    }
                });

                // Render batch items
                batch.forEach((s, suggestionIndex) => {
                    if (!s || !s.Title || !belongsToSelectedField(s)) return;

                    const item = document.createElement("div");
                    item.className = "qa-groom-suggestion-item qa-history-item";

                    // Check if this suggestion is already accepted from history
                    const isAlreadyAdded = historyAcceptedSuggestions.some(h => sameHistorySuggestion(h, s));

                    item.innerHTML = `
                <div class="qa-groom-header">
                    <label class="qa-checkbox">
                        <input
                            type="checkbox"
                            class="qa-history-checkbox"
                            data-batch-index="${i}"
                            data-suggestion-index="${suggestionIndex}"
                            ${isAlreadyAdded ? "checked" : ""}
                        />
                    </label>
                    <span class="qa-groom-title qa-toggle-title">
                        ${escapeHtml(s.Title)}
                    </span>
                    <button class="qa-accordion-toggle">
                       <i class="bi bi-caret-down-fill qa-arrow"></i>
                    </button>
                </div>
                <div class="qa-groom-description hidden">
                    ${sanitizeRichText(s.Description || "")}
                </div>
                `;

                    // Add click handler for the checkbox
                    const checkbox = item.querySelector(".qa-history-checkbox");
                    checkbox.addEventListener("change", async function () {
                        const batchIdx = +this.dataset.batchIndex;
                        const suggIdx = +this.dataset.suggestionIndex;

                        const historySuggestion = suggestionHistory[batchIdx]?.[suggIdx];
                        if (!historySuggestion) return;

                        if (this.checked) {
                            if (!historyAcceptedSuggestions.some(h => sameHistorySuggestion(h, historySuggestion))) {
                                historyAcceptedSuggestions.push({
                                    Title: historySuggestion.Title ?? historySuggestion.title ?? "",
                                    Description: historySuggestion.Description ?? historySuggestion.description ?? "",
                                    fieldRef: historySuggestion.fieldRef ?? historySuggestion.FieldRef
                                });
                            }
                        } else {
                            historyAcceptedSuggestions = historyAcceptedSuggestions.filter(
                                h => !sameHistorySuggestion(h, historySuggestion)
                            );
                        }

                        rebuildSelectedDescriptionText();
                        updateAppendButtonState();
                        await saveGroomAssistState();
                    });

                    // Add accordion toggle for individual items
                    const toggleBtn = item.querySelector(".qa-accordion-toggle");
                    const titleEl = item.querySelector(".qa-toggle-title");
                    const descEl = item.querySelector(".qa-groom-description");

                    [toggleBtn, titleEl].forEach(el => {
                        el.addEventListener("click", (evt) => {
                            evt.stopPropagation();
                            const isHidden = descEl.classList.contains("hidden");
                            descEl.classList.toggle("hidden");
                            const arrow = toggleBtn.querySelector(".qa-arrow");
                            arrow.classList.toggle("bi-caret-up-fill");
                            arrow.classList.toggle("bi-caret-down-fill");
                        });
                    });

                    batchWrapper.appendChild(item);
                });

                container.appendChild(batchWrapper);
            }
        }

        // If history was previously expanded, render it now
        if (wasExpanded) {
            renderVisibleBatches();
        }

        historyRoot.appendChild(header);
        historyRoot.appendChild(container);
    }

    // New function to update only current suggestions without affecting history
    function updateCurrentSuggestionsOnly() {
        const suggestionsEl = document.getElementById("groom-suggestions-list");
        if (!suggestionsEl) return;

        // Remove only current suggestion items (not history)
        const currentItems = suggestionsEl.querySelectorAll(".qa-groom-suggestion-item:not(.qa-history-item)");
        currentItems.forEach(item => item.remove());

        // Remove the history header and container temporarily to preserve them
        const historyHeader = suggestionsEl.querySelector(".qa-history-header");
        const historyContainer = suggestionsEl.querySelector(".qa-history-container");

        if (historyHeader) historyHeader.remove();
        if (historyContainer) historyContainer.remove();

        // Now render current suggestions
        suggestions.forEach((s, index) => {
            const item = document.createElement("div");
            item.className = "qa-groom-suggestion-item";

            if (s.fromHistory) {
                item.classList.add("qa-from-history");
            }

            item.innerHTML = `
        <div class="qa-groom-header">
            <label class="qa-checkbox">
                <input
                    type="checkbox"
                    class="qa-suggestion-checkbox"
                    data-index="${index}"
                    ${s.isAccepted ? "checked" : ""}
                />
            </label>

            <span class="qa-groom-title qa-toggle-title" data-index="${index}">
                ${escapeHtml(s.Title || "")}
                ${s.fromHistory ? '<span class="qa-history-badge">(From History)</span>' : ''}
            </span>

            <button class="qa-accordion-toggle" data-index="${index}">
                <i class="bi bi-caret-down-fill qa-arrow"></i>
            </button>
        </div>

        <div class="qa-groom-description hidden" id="qa-desc-${index}">
            ${sanitizeRichText(s.Description || "")}
        </div>
        `;

            suggestionsEl.insertBefore(item, suggestionsEl.firstChild);
        });

        // Re-add the history header and container
        if (historyHeader) suggestionsEl.appendChild(historyHeader);
        if (historyContainer) suggestionsEl.appendChild(historyContainer);

        // Re-bind events for current suggestions
        document.querySelectorAll(".qa-suggestion-checkbox").forEach(cb => {
            cb.addEventListener("change", onSuggestionChanged);
        });

        document.querySelectorAll(".qa-accordion-toggle, .qa-toggle-title").forEach(el => {
            el.addEventListener("click", toggleAccordion);
        });

        // Update "Select All" checkbox
        const allChecked = suggestions.length && suggestions.every(s => s.isAccepted);
        const selectAllCheckbox = document.getElementById("groom-select-all");
        if (selectAllCheckbox) {
            selectAllCheckbox.checked = allChecked;
        }

        updateAppendButtonState();

        // Show footer
        const footer = document.getElementById("groom-footer");
        if (footer) footer.classList.remove("hidden");
    }


    function toggleAccordion(e) {
        const index = e.currentTarget.dataset.index;
        const desc = document.getElementById(`qa-desc-${index}`);
        const arrow = e.currentTarget
            .closest(".qa-groom-header")
            .querySelector(".qa-arrow");

        const isOpen = !desc.classList.contains("hidden");

        if (isOpen) {
            desc.classList.add("hidden");
            arrow.classList.remove("bi-caret-up-fill");
            arrow.classList.add("bi-caret-down-fill");
        } else {
            desc.classList.remove("hidden");
            arrow.classList.remove("bi-caret-down-fill");
            arrow.classList.add("bi-caret-up-fill");
        }

    }

    function onSuggestionChanged(e) {
        const checkbox = e.target;
        const index = parseInt(checkbox.dataset.index, 10);

        suggestions[index].isAccepted = checkbox.checked;

        rebuildSelectedDescriptionText();

        const all = document.querySelectorAll(".qa-suggestion-checkbox");
        document.getElementById("groom-select-all").checked =
            [...all].every(c => c.checked || c.disabled);

        updateAppendButtonState();

        // ✅ NEW: persist state
        saveGroomAssistState();
    }


    async function onAppendToDescription() {

        if (!selectedDescriptionText || !selectedDescriptionText.trim()) {
            showWarning("Please select at least one suggestion.");
            return;
        }

        try {


            const checkboxes = document.querySelectorAll(".qa-suggestion-checkbox");
            const newSelectedDescriptions = [];
            const newStepPairs = [];

            // Collect only **currently checked suggestions that have NOT been appended**
            checkboxes.forEach(cb => {
                if (!cb.checked) return;

                const index = parseInt(cb.dataset.index, 10);
                const title = suggestions[index].Title;
                const desc = suggestions[index].Description;
                const combinedText = `<strong>${title}:</strong> ${desc}`;

                if (!appendedDescriptions.includes(combinedText)) {
                    newSelectedDescriptions.push(combinedText);
                    newStepPairs.push({ title, desc });
                }
            });

            const currentFieldHistoryAccepted = historyAcceptedSuggestions.filter(belongsToSelectedField);
            currentFieldHistoryAccepted.forEach(s => {
                const combinedText = `<strong>${s.Title}:</strong> ${s.Description}`;
                if (!appendedDescriptions.includes(combinedText)) {
                    newSelectedDescriptions.push(combinedText);
                    newStepPairs.push({ title: s.Title, desc: s.Description });
                }
            });

            if (!newSelectedDescriptions.length) {
                showWarning("No new suggestions to append.");
                return;
            }
            const appendedHistorySuggestions = [...currentFieldHistoryAccepted];

            const selectedField = getSelectedField();
            if (selectedField.ref === STEPS_REF) {
                await appendStepsToWorkItem(context, newStepPairs);
            } else {
                const textToAppend = newSelectedDescriptions.join("\n\n");
                await appendToWorkItemField(context, selectedField, textToAppend);
            }

            showSuccess(`${selectedField.label} updated successfully`);

            // Mark as appended locally
            appendedDescriptions.push(...newSelectedDescriptions);
            suggestions
                .filter(s => s.isAccepted && belongsToSelectedField(s))
                .forEach(s => appendedSuggestionKeys.add(suggestionKey(s)));
            appendedHistorySuggestions.forEach(s => appendedSuggestionKeys.add(suggestionKey(s)));

            // Remove appended suggestions from the list
            suggestions = suggestions.filter(
                s => !(belongsToSelectedField(s) && newSelectedDescriptions.some(t => t.includes(s.Description)))
            );

            if (appendedHistorySuggestions.length) {
                suggestionHistory = suggestionHistory
                    .map(batch => Array.isArray(batch)
                        ? batch.filter(s => !appendedHistorySuggestions.some(h => sameHistorySuggestion(h, s)))
                        : batch)
                    .filter(batch => Array.isArray(batch) && batch.length);
            }

            historyAcceptedSuggestions = historyAcceptedSuggestions.filter(s => !belongsToSelectedField(s));

            rebuildSelectedDescriptionText();

            document.getElementById("groom-select-all").checked = false;

            renderSuggestions();

            await saveGroomAssistState(true);
        } catch (e) {
            console.error(e);
            showError("Failed to update work item description.");
        }
    }

    async function appendToWorkItemField(context, field, appendText) {
        if (!appendText || !appendText.trim()) return;

        // Wrap each suggestion in a <p> instead of <ul><li>
        const appendedHtml = appendText
            .split("\n\n")           // split by double newlines between suggestions
            .map(t => t.trim())       // trim extra spaces
            .filter(Boolean)          // ignore empty strings
            .map(t => `<p>${t}</p>`) // wrap in paragraph
            .join("");                // join all paragraphs

        if (field.ref === DISCUSSION_REF) {
            await IndexLibrary.AddWorkItemDiscussionComment(
                context.workItemId,
                context.projectName,
                appendedHtml
            );
            return;
        }

        const wi = await IndexLibrary.GetWorkItemWithFields(context.workItemId, [field.ref]);
        const existingValue = wi?.fields?.[field.ref] || "";

        const updatedValue = existingValue + appendedHtml;

        await IndexLibrary.UpdateWorkItemFieldInDevops(
            context.workItemId,
            context.projectName,
            field.ref,
            updatedValue
        );

        // Keep local cache in sync
        if (cachedWorkItem?.fields) {
            cachedWorkItem.fields[field.ref] = updatedValue;
        }

    }

    async function appendStepsToWorkItem(context, stepPairs) {
        if (!stepPairs || !stepPairs.length) return;

        const wi = await IndexLibrary.GetWorkItemWithFields(context.workItemId, [STEPS_REF]);
        const existingXml = wi?.fields?.[STEPS_REF] || "";

        const updatedXml = buildStepsXml(existingXml, stepPairs);

        await IndexLibrary.UpdateWorkItemFieldInDevops(
            context.workItemId,
            context.projectName,
            STEPS_REF,
            updatedXml
        );

        if (cachedWorkItem?.fields) {
            cachedWorkItem.fields[STEPS_REF] = updatedXml;
        }
    }

    // One suggestion -> one Test Case step: Title becomes Action, Description becomes Expected Result.
    function buildStepsXml(existingXml, stepPairs) {
        const parser = new DOMParser();
        let doc = null;
        let stepsEl = null;

        if (existingXml && existingXml.trim()) {
            const parsed = parser.parseFromString(existingXml, "text/xml");
            if (!parsed.getElementsByTagName("parsererror").length && parsed.documentElement.nodeName === "steps") {
                doc = parsed;
                stepsEl = parsed.documentElement;
            }
        }

        if (!stepsEl) {
            doc = parser.parseFromString('<steps id="0" last="0"></steps>', "text/xml");
            stepsEl = doc.documentElement;
        }

        let lastId = parseInt(stepsEl.getAttribute("last"), 10);
        if (isNaN(lastId)) lastId = 0;

        stepPairs.forEach(({ title, desc }) => {
            lastId += 1;

            const stepEl = doc.createElement("step");
            stepEl.setAttribute("id", String(lastId));
            stepEl.setAttribute("type", "ActionStep");

            const actionEl = doc.createElement("parameterizedString");
            actionEl.setAttribute("isformatted", "true");
            actionEl.textContent = `<DIV><P>${title || ""}</P></DIV>`;

            const expectedEl = doc.createElement("parameterizedString");
            expectedEl.setAttribute("isformatted", "true");
            expectedEl.textContent = `<DIV><P>${desc || ""}</P></DIV>`;

            stepEl.appendChild(actionEl);
            stepEl.appendChild(expectedEl);
            stepEl.appendChild(doc.createElement("description"));

            stepsEl.appendChild(stepEl);
        });

        stepsEl.setAttribute("last", String(lastId));

        return new XMLSerializer().serializeToString(stepsEl);
    }


    async function saveGroomAssistState(isSuggestionAppended = false) {

        try {

            if (!context?.workItemId) return;

            const queryContext = getPromptInput()?.value || "";

            const remainingSuggestions = suggestions
                .filter(s => !s.isAccepted)
                .map(s => ({
                    Title: s.Title,
                    Description: s.Description,
                    fieldRef: s.fieldRef ?? s.FieldRef
                }));

            const acceptedSuggestions = suggestions
                .filter(s => s.isAccepted)
                .map(s => ({
                    Title: s.Title,
                    Description: s.Description,
                    fieldRef: s.fieldRef ?? s.FieldRef
                }));

            const suggestionsHistoryPayload = JSON.stringify(
                (suggestionHistory || [])
                    .filter(batch => Array.isArray(batch) && batch.length)
                    .map(batch => JSON.stringify(batch))
            );

            const payload = {
                organizationId: context.organizationId,
                devOpsProjectId: context.projectId,
                devOpsProjectName: context.projectName,
                workItemId: context.workItemId,
                createdBy: context.userName || context.userEmail,
                queryContext: queryContext,

                // always save remaining suggestions
                suggestions: JSON.stringify(remainingSuggestions),

                // IMPORTANT LOGIC
                acceptedSuggestions: isSuggestionAppended
                    ? JSON.stringify([])
                    : JSON.stringify([
                        ...acceptedSuggestions,
                        ...historyAcceptedSuggestions.map(s => ({ ...s, fromHistory: true }))
                    ]),
                suggestionsHistory: suggestionsHistoryPayload
            };

            await IndexLibrary.PostRequest({
                baseAPIUrl: context.baseAPIUrl,
                endpoint: `/api/Groom/SaveGroomAssistState`,
                azureAuthenticationHeader: context.accessToken,
                organizationName: context.organizationName,
                organizationId: context.organizationId,
                body: payload
            });
        } catch (e) {
            console.warn("Failed to save groom assist state", e);
        }
    }



    ScreenManager.register("groom", {
        init,
        dispose: () => { }
    });

})();
